diff --git a/.document b/.document new file mode 100644 index 0000000..1d07bdf --- /dev/null +++ b/.document @@ -0,0 +1,5 @@ +BSDL +COPYING +README.md +docs/ +lib/ diff --git a/.gitignore b/.gitignore index a704c3c..21a28a0 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /.yardoc /_yardoc/ /coverage/ -/doc/ +/html/ /pkg/ /spec/reports/ /tmp/ diff --git a/.rdoc_options b/.rdoc_options new file mode 100644 index 0000000..7aa5a53 --- /dev/null +++ b/.rdoc_options @@ -0,0 +1,3 @@ +--- +main_page: README.md +op_dir: html diff --git a/docs/win32.rb b/docs/win32.rb new file mode 100644 index 0000000..4ef9154 --- /dev/null +++ b/docs/win32.rb @@ -0,0 +1,3 @@ +# Wrapper module for \Win32 platforms +module Win32 +end diff --git a/lib/win32/registry.rb b/lib/win32/registry.rb index 8e2c8b2..734d698 100644 --- a/lib/win32/registry.rb +++ b/lib/win32/registry.rb @@ -2,83 +2,74 @@ require 'fiddle/import' module Win32 - -=begin rdoc -= Win32 Registry - -win32/registry is registry accessor library for Win32 platform. -It uses importer to call Win32 Registry APIs. - -== example - Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg| - value = reg['foo'] # read a value - value = reg['foo', Win32::Registry::REG_SZ] # read a value with type - type, value = reg.read('foo') # read a value - reg['foo'] = 'bar' # write a value - reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type - reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value - - reg.each_value { |name, type, data| ... } # Enumerate values - reg.each_key { |key, wtime| ... } # Enumerate subkeys - - reg.delete_value(name) # Delete a value - reg.delete_key(name) # Delete a subkey - reg.delete_key(name, true) # Delete a subkey recursively - end - -= Reference - -== Win32::Registry class - ---- info - ---- num_keys - ---- max_key_length - ---- num_values - ---- max_value_name_length - ---- max_value_length - ---- descriptor_length - ---- wtime - Returns an item of key information. - -=== constants ---- HKEY_CLASSES_ROOT - ---- HKEY_CURRENT_USER - ---- HKEY_LOCAL_MACHINE - ---- HKEY_PERFORMANCE_DATA - ---- HKEY_CURRENT_CONFIG - ---- HKEY_DYN_DATA - - Win32::Registry object whose key is predefined key. -For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article. - -=end rdoc - + # :stopdoc: WCHAR = Encoding::UTF_16LE WCHAR_NUL = "\0".encode(WCHAR).freeze WCHAR_CR = "\r".encode(WCHAR).freeze WCHAR_SIZE = WCHAR_NUL.bytesize LOCALE = Encoding::UTF_8 + # :startdoc: + + # win32/registry is registry accessor library for Win32 platform. + # It uses importer to call Win32 Registry APIs. + # + # == example + # Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg| + # value = reg['foo'] # read a value + # value = reg['foo', Win32::Registry::REG_SZ] # read a value with type + # type, value = reg.read('foo') # read a value + # reg['foo'] = 'bar' # write a value + # reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type + # reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value + # + # reg.each_value { |name, type, data| ... } # Enumerate values + # reg.each_key { |key, wtime| ... } # Enumerate subkeys + # + # reg.delete_value(name) # Delete a value + # reg.delete_key(name) # Delete a subkey + # reg.delete_key(name, true) # Delete a subkey recursively + # end + # + # == Predefined keys + # + # * +HKEY_CLASSES_ROOT+ + # * +HKEY_CURRENT_USER+ + # * +HKEY_LOCAL_MACHINE+ + # * +HKEY_PERFORMANCE_DATA+ + # * +HKEY_CURRENT_CONFIG+ + # * +HKEY_DYN_DATA+ + # + # Win32::Registry object whose key is predefined key. + # For detail, see the article[https://learn.microsoft.com/en-us/windows/win32/sysinfo/predefined-keys]. + # + # == Value types + # + # * +REG_NONE+ + # * +REG_SZ+ + # * +REG_EXPAND_SZ+ + # * +REG_BINARY+ + # * +REG_DWORD+ + # * +REG_DWORD_BIG_ENDIAN+ + # * +REG_LINK+ + # * +REG_MULTI_SZ+ + # * +REG_RESOURCE_LIST+ + # * +REG_FULL_RESOURCE_DESCRIPTOR+ + # * +REG_RESOURCE_REQUIREMENTS_LIST+ + # * +REG_QWORD+ + # + # For detail, see the article[https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types]. + # class Registry + # :stopdoc: + # # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp]. # # --- HKEY_* # - # Predefined key ((*handle*)). + # Predefined key *handle*. # These are Integer, not Win32::Registry. # # --- REG_* @@ -100,6 +91,7 @@ class Registry # If the key is created newly or opened existing key. # See also Registry#disposition method. module Constants + # :stopdoc: HKEY_CLASSES_ROOT = 0x80000000 HKEY_CURRENT_USER = 0x80000001 HKEY_LOCAL_MACHINE = 0x80000002 @@ -115,7 +107,6 @@ module Constants REG_EXPAND_SZ = 2 REG_BINARY = 3 REG_DWORD = 4 - REG_DWORD_LITTLE_ENDIAN = 4 REG_DWORD_BIG_ENDIAN = 5 REG_LINK = 6 REG_MULTI_SZ = 7 @@ -163,16 +154,23 @@ module Constants end include Constants include Enumerable + # :startdoc: # # Error # class Error < ::StandardError + # :stopdoc: module Kernel32 extend Fiddle::Importer dlload "kernel32.dll" end FormatMessageW = Kernel32.extern "int FormatMessageW(int, void *, int, int, void *, int, void *)", :stdcall + # :startdoc: + + # new(code) -> error object + # + # Initializes the message for Win32 API error +code+. def initialize(code) @code = code buff = WCHAR_NUL * 1024 @@ -190,6 +188,8 @@ def initialize(code) end super msg end + + # Win32 API error code. attr_reader :code end @@ -197,6 +197,7 @@ def initialize(code) # Predefined Keys # class PredefinedKey < Registry + # :stopdoc: def initialize(hkey, keyname) @hkey = Fiddle::Pointer.new(hkey) @parent = nil @@ -224,6 +225,7 @@ def class # Win32 APIs # module API + # :stopdoc: include Constants extend Fiddle::Importer dlload "advapi32.dll" @@ -367,12 +369,14 @@ def QueryInfoKey(hkey) unpackdw(secdescs), unpackqw(wtime) ] end end + # :startdoc: # - # Replace %\w+% into the environment value of what is contained between the %'s + # Replace %-enclosed substrings in +str+ into the + # environment value of what is contained between the %s. # This method is used for REG_EXPAND_SZ. # - # For detail, see expandEnvironmentStrings[https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsa] \Win32 \API. + # For detail, see ExpandEnvironmentStrings[https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsw] \Win32 \API. # def self.expand_environ(str) str.gsub(Regexp.compile("%([^%]+)%".encode(str.encoding))) { @@ -392,21 +396,21 @@ def self.expand_environ(str) end.freeze # - # Convert registry type value to readable string. + # Convert registry type value +type+ to readable string. # def self.type2name(type) @@type2name[type] || type.to_s end # - # Convert 64-bit FILETIME integer into Time object. + # Convert 64-bit FILETIME integer +wtime+ into Time object. # def self.wtime2time(wtime) Time.at((wtime - 116444736000000000) / 10000000) end # - # Convert Time object or Integer object into 64-bit FILETIME. + # Convert Time object or Integer object +time+ into 64-bit FILETIME. # def self.time2wtime(time) time.to_i * 10000000 + 116444736000000000 @@ -418,16 +422,19 @@ def self.time2wtime(time) private_class_method :new # - # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) + # call-seq: + # open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) + # open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... } # - # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... } + # Open the registry key +subkey+ under +key+. + # +key+ is Win32::Registry object of parent key. + # You can use {predefined key}[rdoc-ref:Win32::Registry@Predefined+keys] +HKEY_+*. + # +desired+ and +opt+ is access mask and key option. # - # Open the registry key subkey under key. - # key is Win32::Registry object of parent key. - # You can use predefined key HKEY_* (see Constants) - # desired and opt is access mask and key option. # For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp]. - # If block is given, the key is closed automatically. + # + # If block is given, the key +reg+ is yielded and closed + # automatically after the block exists. def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) subkey = subkey.chomp('\\') newkey = API.OpenKey(hkey.instance_variable_get(:@hkey), subkey, opt, desired) @@ -444,17 +451,19 @@ def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) end # - # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) - # - # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... } + # call-seq: + # create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) + # create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... } # - # Create or open the registry key subkey under key. - # You can use predefined key HKEY_* (see Constants) + # Create or open the registry key +subkey+ under +key+. + # You can use {predefined key}[rdoc-ref:Win32::Registry@Predefined+keys] +HKEY_+*. + # +desired+ and +opt+ is access mask and key option. # - # If subkey is already exists, key is opened and Registry#created? + # If +subkey+ is already exists, key is opened and Registry#created? # method will return false. # - # If block is given, the key is closed automatically. + # If block is given, the key +reg+ is yielded and closed + # automatically after the block exists. # def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) newkey, disp = API.CreateKey(hkey.instance_variable_get(:@hkey), subkey, opt, desired) @@ -476,7 +485,9 @@ def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVE @@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } } # - # initialize + # :nodoc: + # + # Use self.open, self.create, #open and #create. # def initialize(hkey, parent, keyname, disposition) @hkey = Fiddle::Pointer.new(hkey) @@ -501,7 +512,7 @@ def hkey end # - # Returns if key is created ((*newly*)). + # Returns +true+ if key is created *newly*. # (see Registry.create) -- basically you call create # then when you call created? on the instance returned # it will tell if it was successful or not @@ -518,7 +529,7 @@ def open? end # - # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'. + # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'. # def name parent = self @@ -529,6 +540,9 @@ def name name end + # + # Retruns inspected string + # def inspect "\#" end @@ -541,14 +555,14 @@ def _dump(depth) end # - # Same as Win32::Registry.open (self, subkey, desired, opt) + # Same as Win32::Registry.open(self, subkey, desired, opt) # def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk) self.class.open(self, subkey, desired, opt, &blk) end # - # Same as Win32::Registry.create (self, subkey, desired, opt) + # Same as Win32::Registry.create(self, subkey, desired, opt) # def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk) self.class.create(self, subkey, desired, opt, &blk) @@ -571,7 +585,7 @@ def close # For each value it yields key, type and data. # # key is a String which contains name of key. - # type is a type constant kind of Win32::Registry::REG_* + # type is a type constant kind of +Win32::Registry::REG_+* # data is the value of this key. # def each_value @@ -640,21 +654,23 @@ def keys end # Read a registry value named name and return array of - # [ type, data ]. - # When name is nil, the `default' value is read. - # type is value type. (see Win32::Registry::Constants module) - # data is value data, its class is: - # :REG_SZ, REG_EXPAND_SZ + # [ type, data ]. + # When name is +nil+, the `default' value is read. + # + # +type+ is {value type}[rdoc-ref:Win32::Registry@Value+types]. + # + # +data+ is value data, its class is: + # REG_SZ, REG_EXPAND_SZ:: # String - # :REG_MULTI_SZ + # REG_MULTI_SZ:: # Array of String - # :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD + # REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD:: # Integer - # :REG_BINARY, REG_NONE + # REG_BINARY, REG_NONE:: # String (contains binary data) # - # When rtype is specified, the value type must be included by - # rtype array, or TypeError is raised. + # When _rtype_ is specified, the value type must be included by + # _rtype_ array, or +TypeError+ is raised. def read(name, *rtype) type, data = API.QueryValue(@hkey, name) unless rtype.empty? or rtype.include?(type) @@ -687,9 +703,9 @@ def read(name, *rtype) # If the value type is REG_EXPAND_SZ, returns value data whose environment # variables are replaced. # If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD, - # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised. + # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, +TypeError+ is raised. # - # The meaning of rtype is the same as for the #read method. + # The meaning of _rtype_ is the same as for the #read method. # def [](name, *rtype) type, data = read(name, *rtype) @@ -706,7 +722,7 @@ def [](name, *rtype) # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) # registry value named name. # - # If the values type does not match, TypeError is raised. + # If the values type does not match, +TypeError+ is raised. def read_s(name) read(name, REG_SZ)[1] end @@ -715,7 +731,7 @@ def read_s(name) # Read a REG_SZ or REG_EXPAND_SZ registry value named name. # # If the value type is REG_EXPAND_SZ, environment variables are replaced. - # Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised. + # Unless the value type is REG_SZ or REG_EXPAND_SZ, +TypeError+ is raised. # def read_s_expand(name) type, data = read(name, REG_SZ, REG_EXPAND_SZ) @@ -730,7 +746,7 @@ def read_s_expand(name) # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) # registry value named name. # - # If the values type does not match, TypeError is raised. + # If the values type does not match, +TypeError+ is raised. # def read_i(name) read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1] @@ -740,7 +756,7 @@ def read_i(name) # Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin) # registry value named name. # - # If the values type does not match, TypeError is raised. + # If the values type does not match, +TypeError+ is raised. # def read_bin(name) read(name, REG_BINARY)[1] @@ -750,7 +766,7 @@ def read_bin(name) # Write data to a registry value named name. # When name is nil, write to the `default' value. # - # type is type value. (see Registry::Constants module) + # +type+ is {value type}[rdoc-ref:Win32::Registry@Value+types]. # Class of data must be same as which #read # method returns. # @@ -779,11 +795,12 @@ def write(name, type, data) # # If wtype is specified, the value type is it. # Otherwise, the value type is depend on class of value: - # :Integer + # + # Integer:: # REG_DWORD - # :String + # String:: # REG_SZ - # :Array + # Array:: # REG_MULTI_SZ # def []=(name, rtype, value = nil) @@ -880,19 +897,19 @@ def flush # # Returns key information as Array of: - # :num_keys + # num_keys:: # The number of subkeys. - # :max_key_length + # max_key_length:: # Maximum length of name of subkeys. - # :num_values + # num_values:: # The number of values. - # :max_value_name_length + # max_value_name_length:: # Maximum length of name of values. - # :max_value_length + # max_value_length:: # Maximum length of value of values. - # :descriptor_length + # descriptor_length:: # Length of security descriptor. - # :wtime + # wtime:: # Last write time as FILETIME(64-bit integer) # # For detail, see RegQueryInfoKey[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API.