1require 'dl/import'
2module Win32
3
4=begin rdoc
5= Win32 Registry
6
7win32/registry is registry accessor library for Win32 platform.
8It uses dl/import to call Win32 Registry APIs.
9
10== example
11  Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
12    value = reg['foo']                               # read a value
13    value = reg['foo', Win32::Registry::REG_SZ]      # read a value with type
14    type, value = reg.read('foo')                    # read a value
15    reg['foo'] = 'bar'                               # write a value
16    reg['foo', Win32::Registry::REG_SZ] = 'bar'      # write a value with type
17    reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
18
19    reg.each_value { |name, type, data| ... }        # Enumerate values
20    reg.each_key { |key, wtime| ... }                # Enumerate subkeys
21
22    reg.delete_value(name)                         # Delete a value
23    reg.delete_key(name)                           # Delete a subkey
24    reg.delete_key(name, true)                     # Delete a subkey recursively
25  end
26
27= Reference
28
29== Win32::Registry class
30
31--- info
32
33--- num_keys
34
35--- max_key_length
36
37--- num_values
38
39--- max_value_name_length
40
41--- max_value_length
42
43--- descriptor_length
44
45--- wtime
46    Returns an item of key information.
47
48=== constants
49--- HKEY_CLASSES_ROOT
50
51--- HKEY_CURRENT_USER
52
53--- HKEY_LOCAL_MACHINE
54
55--- HKEY_PERFORMANCE_DATA
56
57--- HKEY_CURRENT_CONFIG
58
59--- HKEY_DYN_DATA
60
61    Win32::Registry object whose key is predefined key.
62For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article.
63
64=end rdoc
65
66  class Registry
67
68    #
69    # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp].
70    #
71    # --- HKEY_*
72    #
73    #     Predefined key ((*handle*)).
74    #     These are Integer, not Win32::Registry.
75    #
76    # --- REG_*
77    #
78    #     Registry value type.
79    #
80    # --- KEY_*
81    #
82    #     Security access mask.
83    #
84    # --- KEY_OPTIONS_*
85    #
86    #     Key options.
87    #
88    # --- REG_CREATED_NEW_KEY
89    #
90    # --- REG_OPENED_EXISTING_KEY
91    #
92    #     If the key is created newly or opened existing key.
93    #     See also Registry#disposition method.
94    module Constants
95      HKEY_CLASSES_ROOT = 0x80000000
96      HKEY_CURRENT_USER = 0x80000001
97      HKEY_LOCAL_MACHINE = 0x80000002
98      HKEY_USERS = 0x80000003
99      HKEY_PERFORMANCE_DATA = 0x80000004
100      HKEY_PERFORMANCE_TEXT = 0x80000050
101      HKEY_PERFORMANCE_NLSTEXT = 0x80000060
102      HKEY_CURRENT_CONFIG = 0x80000005
103      HKEY_DYN_DATA = 0x80000006
104
105      REG_NONE = 0
106      REG_SZ = 1
107      REG_EXPAND_SZ = 2
108      REG_BINARY = 3
109      REG_DWORD = 4
110      REG_DWORD_LITTLE_ENDIAN = 4
111      REG_DWORD_BIG_ENDIAN = 5
112      REG_LINK = 6
113      REG_MULTI_SZ = 7
114      REG_RESOURCE_LIST = 8
115      REG_FULL_RESOURCE_DESCRIPTOR = 9
116      REG_RESOURCE_REQUIREMENTS_LIST = 10
117      REG_QWORD = 11
118      REG_QWORD_LITTLE_ENDIAN = 11
119
120      STANDARD_RIGHTS_READ = 0x00020000
121      STANDARD_RIGHTS_WRITE = 0x00020000
122      KEY_QUERY_VALUE = 0x0001
123      KEY_SET_VALUE = 0x0002
124      KEY_CREATE_SUB_KEY = 0x0004
125      KEY_ENUMERATE_SUB_KEYS = 0x0008
126      KEY_NOTIFY = 0x0010
127      KEY_CREATE_LINK = 0x0020
128      KEY_READ = STANDARD_RIGHTS_READ |
129        KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY
130      KEY_WRITE = STANDARD_RIGHTS_WRITE |
131        KEY_SET_VALUE | KEY_CREATE_SUB_KEY
132      KEY_EXECUTE = KEY_READ
133      KEY_ALL_ACCESS = KEY_READ | KEY_WRITE | KEY_CREATE_LINK
134
135      REG_OPTION_RESERVED = 0x0000
136      REG_OPTION_NON_VOLATILE = 0x0000
137      REG_OPTION_VOLATILE = 0x0001
138      REG_OPTION_CREATE_LINK = 0x0002
139      REG_OPTION_BACKUP_RESTORE = 0x0004
140      REG_OPTION_OPEN_LINK = 0x0008
141      REG_LEGAL_OPTION = REG_OPTION_RESERVED |
142        REG_OPTION_NON_VOLATILE | REG_OPTION_CREATE_LINK |
143        REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK
144
145      REG_CREATED_NEW_KEY = 1
146      REG_OPENED_EXISTING_KEY = 2
147
148      REG_WHOLE_HIVE_VOLATILE = 0x0001
149      REG_REFRESH_HIVE = 0x0002
150      REG_NO_LAZY_FLUSH = 0x0004
151      REG_FORCE_RESTORE = 0x0008
152
153      MAX_KEY_LENGTH = 514
154      MAX_VALUE_LENGTH = 32768
155    end
156    include Constants
157    include Enumerable
158
159    #
160    # Error
161    #
162    class Error < ::StandardError
163      module Kernel32
164        extend DL::Importer
165        dlload "kernel32.dll"
166      end
167      FormatMessageA = Kernel32.extern "int FormatMessageA(int, void *, int, int, void *, int, void *)", :stdcall
168      def initialize(code)
169        @code = code
170        msg = "\0".force_encoding(Encoding::ASCII_8BIT) * 1024
171        len = FormatMessageA.call(0x1200, 0, code, 0, msg, 1024, 0)
172        msg = msg[0, len].force_encoding(Encoding.find(Encoding.locale_charmap))
173        super msg.tr("\r", '').chomp
174      end
175      attr_reader :code
176    end
177
178    #
179    # Predefined Keys
180    #
181    class PredefinedKey < Registry
182      def initialize(hkey, keyname)
183        @hkey = hkey
184        @parent = nil
185        @keyname = keyname
186        @disposition = REG_OPENED_EXISTING_KEY
187      end
188
189      # Predefined keys cannot be closed
190      def close
191        raise Error.new(5) ## ERROR_ACCESS_DENIED
192      end
193
194      # Fake #class method for Registry#open, Registry#create
195      def class
196        Registry
197      end
198
199      # Make all
200      Constants.constants.grep(/^HKEY_/) do |c|
201        Registry.const_set c, new(Constants.const_get(c), c.to_s)
202      end
203    end
204
205    #
206    # Win32 APIs
207    #
208    module API
209      extend DL::Importer
210      dlload "advapi32.dll"
211      [
212        "long RegOpenKeyExA(void *, void *, long, long, void *)",
213        "long RegCreateKeyExA(void *, void *, long, long, long, long, void *, void *, void *)",
214        "long RegEnumValueA(void *, long, void *, void *, void *, void *, void *, void *)",
215        "long RegEnumKeyExA(void *, long, void *, void *, void *, void *, void *, void *)",
216        "long RegQueryValueExA(void *, void *, void *, void *, void *, void *)",
217        "long RegSetValueExA(void *, void *, long, long, void *, long)",
218        "long RegDeleteValue(void *, void *)",
219        "long RegDeleteKey(void *, void *)",
220        "long RegFlushKey(void *)",
221        "long RegCloseKey(void *)",
222        "long RegQueryInfoKey(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)",
223      ].each do |fn|
224        cfunc = extern fn, :stdcall
225        const_set cfunc.name.intern, cfunc
226      end
227
228      module_function
229
230      def check(result)
231        raise Error, result, caller(2) if result != 0
232      end
233
234      def packdw(dw)
235        [dw].pack('V')
236      end
237
238      def unpackdw(dw)
239        dw += [0].pack('V')
240        dw.unpack('V')[0]
241      end
242
243      def packqw(qw)
244        [ qw & 0xFFFFFFFF, qw >> 32 ].pack('VV')
245      end
246
247      def unpackqw(qw)
248        qw = qw.unpack('VV')
249        (qw[1] << 32) | qw[0]
250      end
251
252      def OpenKey(hkey, name, opt, desired)
253        result = packdw(0)
254        check RegOpenKeyExA.call(hkey, name, opt, desired, result)
255        unpackdw(result)
256      end
257
258      def CreateKey(hkey, name, opt, desired)
259        result = packdw(0)
260        disp = packdw(0)
261        check RegCreateKeyExA.call(hkey, name, 0, 0, opt, desired,
262                                   0, result, disp)
263        [ unpackdw(result), unpackdw(disp) ]
264      end
265
266      def EnumValue(hkey, index)
267        name = ' ' * Constants::MAX_KEY_LENGTH
268        size = packdw(Constants::MAX_KEY_LENGTH)
269        check RegEnumValueA.call(hkey, index, name, size, 0, 0, 0, 0)
270        name[0, unpackdw(size)]
271      end
272
273      def EnumKey(hkey, index)
274        name = ' ' * Constants::MAX_KEY_LENGTH
275        size = packdw(Constants::MAX_KEY_LENGTH)
276        wtime = ' ' * 8
277        check RegEnumKeyExA.call(hkey, index, name, size, 0, 0, 0, wtime)
278        [ name[0, unpackdw(size)], unpackqw(wtime) ]
279      end
280
281      def QueryValue(hkey, name)
282        type = packdw(0)
283        size = packdw(0)
284        check RegQueryValueExA.call(hkey, name, 0, type, 0, size)
285        data = ' ' * unpackdw(size)
286        check RegQueryValueExA.call(hkey, name, 0, type, data, size)
287        [ unpackdw(type), data[0, unpackdw(size)] ]
288      end
289
290      def SetValue(hkey, name, type, data, size)
291        check RegSetValueExA.call(hkey, name, 0, type, data, size)
292      end
293
294      def DeleteValue(hkey, name)
295        check RegDeleteValue.call(hkey, name)
296      end
297
298      def DeleteKey(hkey, name)
299        check RegDeleteKey.call(hkey, name)
300      end
301
302      def FlushKey(hkey)
303        check RegFlushKey.call(hkey)
304      end
305
306      def CloseKey(hkey)
307        check RegCloseKey.call(hkey)
308      end
309
310      def QueryInfoKey(hkey)
311        subkeys = packdw(0)
312        maxsubkeylen = packdw(0)
313        values = packdw(0)
314        maxvaluenamelen = packdw(0)
315        maxvaluelen = packdw(0)
316        secdescs = packdw(0)
317        wtime = ' ' * 8
318        check RegQueryInfoKey.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0,
319          values, maxvaluenamelen, maxvaluelen, secdescs, wtime)
320        [ unpackdw(subkeys), unpackdw(maxsubkeylen), unpackdw(values),
321          unpackdw(maxvaluenamelen), unpackdw(maxvaluelen),
322          unpackdw(secdescs), unpackqw(wtime) ]
323      end
324    end
325
326    #
327    # Replace %\w+% into the environment value of what is contained between the %'s
328    # This method is used for REG_EXPAND_SZ.
329    #
330    # For detail, see expandEnvironmentStrings[http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp] \Win32 \API.
331    #
332    def self.expand_environ(str)
333      str.gsub(/%([^%]+)%/) { ENV[$1] || ENV[$1.upcase] || $& }
334    end
335
336    @@type2name = { }
337    %w[
338      REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD
339      REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ
340      REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR
341      REG_RESOURCE_REQUIREMENTS_LIST REG_QWORD
342    ].each do |type|
343      @@type2name[Constants.const_get(type)] = type
344    end
345
346    #
347    # Convert registry type value to readable string.
348    #
349    def self.type2name(type)
350      @@type2name[type] || type.to_s
351    end
352
353    #
354    # Convert 64-bit FILETIME integer into Time object.
355    #
356    def self.wtime2time(wtime)
357      Time.at((wtime - 116444736000000000) / 10000000)
358    end
359
360    #
361    # Convert Time object or Integer object into 64-bit FILETIME.
362    #
363    def self.time2wtime(time)
364      time.to_i * 10000000 + 116444736000000000
365    end
366
367    #
368    # constructor
369    #
370    private_class_method :new
371
372    #
373    # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
374    #
375    # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... }
376    #
377    # Open the registry key subkey under key.
378    # key is Win32::Registry object of parent key.
379    # You can use predefined key HKEY_* (see Constants)
380    # desired and opt is access mask and key option.
381    # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp].
382    # If block is given, the key is closed automatically.
383    def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
384      subkey = subkey.chomp('\\')
385      newkey = API.OpenKey(hkey.hkey, subkey, opt, desired)
386      obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY)
387      if block_given?
388        begin
389          yield obj
390        ensure
391          obj.close
392        end
393      else
394        obj
395      end
396    end
397
398    #
399    # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
400    #
401    # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... }
402    #
403    # Create or open the registry key subkey under key.
404    # You can use predefined key HKEY_* (see Constants)
405    #
406    # If subkey is already exists, key is opened and Registry#created?
407    # method will return false.
408    #
409    # If block is given, the key is closed automatically.
410    #
411    def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
412      newkey, disp = API.CreateKey(hkey.hkey, subkey, opt, desired)
413      obj = new(newkey, hkey, subkey, disp)
414      if block_given?
415        begin
416          yield obj
417        ensure
418          obj.close
419        end
420      else
421        obj
422      end
423    end
424
425    #
426    # finalizer
427    #
428    @@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } }
429
430    #
431    # initialize
432    #
433    def initialize(hkey, parent, keyname, disposition)
434      @hkey = hkey
435      @parent = parent
436      @keyname = keyname
437      @disposition = disposition
438      @hkeyfinal = [ hkey ]
439      ObjectSpace.define_finalizer self, @@final.call(@hkeyfinal)
440    end
441
442    #  Returns key handle value.
443    attr_reader :hkey
444    # Win32::Registry object of parent key, or nil if predefeined key.
445    attr_reader :parent
446    # Same as subkey value of Registry.open or
447    # Registry.create method.
448    attr_reader :keyname
449    #  Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY).
450    attr_reader :disposition
451
452    #
453    # Returns if key is created ((*newly*)).
454    # (see Registry.create) -- basically you call create
455    # then when you call created? on the instance returned
456    # it will tell if it was successful or not
457    #
458    def created?
459      @disposition == REG_CREATED_NEW_KEY
460    end
461
462    #
463    # Returns if key is not closed.
464    #
465    def open?
466      !@hkey.nil?
467    end
468
469    #
470    # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'.
471    #
472    def name
473      parent = self
474      name = @keyname
475      while parent = parent.parent
476        name = parent.keyname + '\\' + name
477      end
478      name
479    end
480
481    def inspect
482      "\#<Win32::Registry key=#{name.inspect}>"
483    end
484
485    #
486    # marshalling is not allowed
487    #
488    def _dump(depth)
489      raise TypeError, "can't dump Win32::Registry"
490    end
491
492    #
493    # Same as Win32::Registry.open (self, subkey, desired, opt)
494    #
495    def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk)
496      self.class.open(self, subkey, desired, opt, &blk)
497    end
498
499    #
500    # Same as Win32::Registry.create (self, subkey, desired, opt)
501    #
502    def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
503      self.class.create(self, subkey, desired, opt, &blk)
504    end
505
506    #
507    # Close key.
508    #
509    # After close, most method raise an error.
510    #
511    def close
512      API.CloseKey(@hkey)
513      @hkey = @parent = @keyname = nil
514      @hkeyfinal[0] = nil
515    end
516
517    #
518    # Enumerate values.
519    #
520    def each_value
521      index = 0
522      while true
523        begin
524          subkey = API.EnumValue(@hkey, index)
525        rescue Error
526          break
527        end
528        begin
529          type, data = read(subkey)
530        rescue Error
531          next
532        end
533        yield subkey, type, data
534        index += 1
535      end
536      index
537    end
538    alias each each_value
539
540    #
541    # Enumerate subkeys.
542    #
543    # subkey is String which contains name of subkey.
544    # wtime is last write time as FILETIME (64-bit integer).
545    # (see Registry.wtime2time)
546    #
547    def each_key
548      index = 0
549      while true
550        begin
551          subkey, wtime = API.EnumKey(@hkey, index)
552        rescue Error
553          break
554        end
555        yield subkey, wtime
556        index += 1
557      end
558      index
559    end
560
561    #
562    # return keys as an array
563    #
564    def keys
565      keys_ary = []
566      each_key { |key,| keys_ary << key }
567      keys_ary
568    end
569
570    # Read a registry value named name and return array of
571    # [ type, data ].
572    # When name is nil, the `default' value is read.
573    # type is value type. (see Win32::Registry::Constants module)
574    # data is value data, its class is:
575    # :REG_SZ, REG_EXPAND_SZ
576    #    String
577    # :REG_MULTI_SZ
578    #    Array of String
579    # :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
580    #    Integer
581    # :REG_BINARY
582    #    String (contains binary data)
583    #
584    # When rtype is specified, the value type must be included by
585    # rtype array, or TypeError is raised.
586    def read(name, *rtype)
587      type, data = API.QueryValue(@hkey, name)
588      unless rtype.empty? or rtype.include?(type)
589        raise TypeError, "Type mismatch (expect #{rtype.inspect} but #{type} present)"
590      end
591      case type
592      when REG_SZ, REG_EXPAND_SZ
593        [ type, data.chop ]
594      when REG_MULTI_SZ
595        [ type, data.split(/\0/) ]
596      when REG_BINARY
597        [ type, data ]
598      when REG_DWORD
599        [ type, API.unpackdw(data) ]
600      when REG_DWORD_BIG_ENDIAN
601        [ type, data.unpack('N')[0] ]
602      when REG_QWORD
603        [ type, API.unpackqw(data) ]
604      else
605        raise TypeError, "Type #{type} is not supported."
606      end
607    end
608
609    #
610    # Read a registry value named name and return its value data.
611    # The class of value is same as #read method returns.
612    #
613    # If the value type is REG_EXPAND_SZ, returns value data whose environment
614    # variables are replaced.
615    # If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD,
616    # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised.
617    #
618    # The meaning of rtype is same as #read method.
619    #
620    def [](name, *rtype)
621      type, data = read(name, *rtype)
622      case type
623      when REG_SZ, REG_DWORD, REG_QWORD, REG_MULTI_SZ
624        data
625      when REG_EXPAND_SZ
626        Registry.expand_environ(data)
627      else
628        raise TypeError, "Type #{type} is not supported."
629      end
630    end
631
632    # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
633    # registry value named name.
634    #
635    # If the values type does not match, TypeError is raised.
636    def read_s(name)
637      read(name, REG_SZ)[1]
638    end
639
640    #
641    # Read a REG_SZ or REG_EXPAND_SZ registry value named name.
642    #
643    # If the value type is REG_EXPAND_SZ, environment variables are replaced.
644    # Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised.
645    #
646    def read_s_expand(name)
647      type, data = read(name, REG_SZ, REG_EXPAND_SZ)
648      if type == REG_EXPAND_SZ
649        Registry.expand_environ(data)
650      else
651        data
652      end
653    end
654
655    #
656    # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
657    # registry value named name.
658    #
659    # If the values type does not match, TypeError is raised.
660    #
661    def read_i(name)
662      read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1]
663    end
664
665    #
666    # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
667    # registry value named name.
668    #
669    # If the values type does not match, TypeError is raised.
670    #
671    def read_bin(name)
672      read(name, REG_BINARY)[1]
673    end
674
675    #
676    # Write data to a registry value named name.
677    # When name is nil, write to the `default' value.
678    #
679    # type is type value. (see Registry::Constants module)
680    # Class of data must be same as which #read
681    # method returns.
682    #
683    def write(name, type, data)
684      case type
685      when REG_SZ, REG_EXPAND_SZ
686        data = data.to_s + "\0"
687      when REG_MULTI_SZ
688        data = data.to_a.join("\0") + "\0\0"
689      when REG_BINARY
690        data = data.to_s
691      when REG_DWORD
692        data = API.packdw(data.to_i)
693      when REG_DWORD_BIG_ENDIAN
694        data = [data.to_i].pack('N')
695      when REG_QWORD
696        data = API.packqw(data.to_i)
697      else
698        raise TypeError, "Unsupported type #{type}"
699      end
700      API.SetValue(@hkey, name, type, data, data.length)
701    end
702
703    #
704    # Write value to a registry value named name.
705    #
706    # If wtype is specified, the value type is it.
707    # Otherwise, the value type is depend on class of value:
708    # :Integer
709    #   REG_DWORD
710    # :String
711    #   REG_SZ
712    # :Array
713    #   REG_MULTI_SZ
714    #
715    def []=(name, rtype, value = nil)
716      if value
717        write name, rtype, value
718      else
719        case value = rtype
720        when Integer
721          write name, REG_DWORD, value
722        when String
723          write name, REG_SZ, value
724        when Array
725          write name, REG_MULTI_SZ, value
726        else
727          raise TypeError, "Unexpected type #{value.class}"
728        end
729      end
730      value
731    end
732
733    #
734    # Write value to a registry value named name.
735    #
736    # The value type is REG_SZ(write_s), REG_DWORD(write_i), or
737    # REG_BINARY(write_bin).
738    #
739    def write_s(name, value)
740      write name, REG_SZ, value.to_s
741    end
742
743    #
744    # Write value to a registry value named name.
745    #
746    # The value type is REG_SZ(write_s), REG_DWORD(write_i), or
747    # REG_BINARY(write_bin).
748    #
749    def write_i(name, value)
750      write name, REG_DWORD, value.to_i
751    end
752
753    #
754    # Write value to a registry value named name.
755    #
756    # The value type is REG_SZ(write_s), REG_DWORD(write_i), or
757    # REG_BINARY(write_bin).
758    #
759    def write_bin(name, value)
760      write name, REG_BINARY, value.to_s
761    end
762
763    #
764    # Delete a registry value named name.
765    # We can not delete the `default' value.
766    #
767    def delete_value(name)
768      API.DeleteValue(@hkey, name)
769    end
770    alias delete delete_value
771
772    #
773    # Delete a subkey named name and all its values.
774    #
775    # If recursive is false, the subkey must not have subkeys.
776    # Otherwise, this method deletes all subkeys and values recursively.
777    #
778    def delete_key(name, recursive = false)
779      if recursive
780        open(name, KEY_ALL_ACCESS) do |reg|
781          reg.keys.each do |key|
782            begin
783              reg.delete_key(key, true)
784            rescue Error
785              #
786            end
787          end
788        end
789        API.DeleteKey(@hkey, name)
790      else
791        begin
792          API.EnumKey @hkey, 0
793        rescue Error
794          return API.DeleteKey(@hkey, name)
795        end
796        raise Error.new(5) ## ERROR_ACCESS_DENIED
797      end
798    end
799
800    #
801    # Write all the attributes into the registry file.
802    #
803    def flush
804      API.FlushKey @hkey
805    end
806
807    #
808    # Returns key information as Array of:
809    # :num_keys
810    #   The number of subkeys.
811    # :max_key_length
812    #   Maximum length of name of subkeys.
813    # :num_values
814    #   The number of values.
815    # :max_value_name_length
816    #   Maximum length of name of values.
817    # :max_value_length
818    #   Maximum length of value of values.
819    # :descriptor_length
820    #   Length of security descriptor.
821    # :wtime
822    #   Last write time as FILETIME(64-bit integer)
823    #
824    # For detail, see RegQueryInfoKey[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API.
825    #
826    def info
827      API.QueryInfoKey(@hkey)
828    end
829
830    #
831    # Returns an item of key information.
832    #
833    %w[
834      num_keys max_key_length
835      num_values max_value_name_length max_value_length
836      descriptor_length wtime
837    ].each_with_index do |s, i|
838      eval <<-__END__
839        def #{s}
840          info[#{i}]
841        end
842      __END__
843    end
844  end
845end
846