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