win32-registry 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/BSDL +22 -0
- data/COPYING +56 -0
- data/README.md +54 -0
- data/Rakefile +8 -0
- data/lib/win32/registry.rb +922 -0
- data/sig/win32/registry.rbs +6 -0
- data.tar.gz.sig +1 -0
- metadata +86 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 300922f392fc25dc6072a6defedf385b9757a05900b595e82966297d6be615a0
|
|
4
|
+
data.tar.gz: 7409a8e0bb983c5af10e3513703e62166f4cbf237b2203d1b5a2c7d1efe6800f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 876fa2b8d41cb9d9d12ba0f436ac422a9d8addd948b561d8d0835a22d819a2e2197cfccf1b720a3c573ae81e31488fd519eef9d57dad74852e24314599c8a387
|
|
7
|
+
data.tar.gz: 68a207b64b243d513ef4e1c3474fe98f14628dad41574cbc77c739fff1806410cf1835194a3af601fb1ff675ca8eb2ee74b99194466cf6d1d32193392aea2d88
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data/BSDL
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions
|
|
5
|
+
are met:
|
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
|
10
|
+
documentation and/or other materials provided with the distribution.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
22
|
+
SUCH DAMAGE.
|
data/COPYING
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
|
|
2
|
+
You can redistribute it and/or modify it under either the terms of the
|
|
3
|
+
2-clause BSDL (see the file BSDL), or the conditions below:
|
|
4
|
+
|
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
|
6
|
+
software without restriction, provided that you duplicate all of the
|
|
7
|
+
original copyright notices and associated disclaimers.
|
|
8
|
+
|
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
|
10
|
+
you do at least ONE of the following:
|
|
11
|
+
|
|
12
|
+
a. place your modifications in the Public Domain or otherwise
|
|
13
|
+
make them Freely Available, such as by posting said
|
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
|
15
|
+
the author to include your modifications in the software.
|
|
16
|
+
|
|
17
|
+
b. use the modified software only within your corporation or
|
|
18
|
+
organization.
|
|
19
|
+
|
|
20
|
+
c. give non-standard binaries non-standard names, with
|
|
21
|
+
instructions on where to get the original software distribution.
|
|
22
|
+
|
|
23
|
+
d. make other distribution arrangements with the author.
|
|
24
|
+
|
|
25
|
+
3. You may distribute the software in object code or binary form,
|
|
26
|
+
provided that you do at least ONE of the following:
|
|
27
|
+
|
|
28
|
+
a. distribute the binaries and library files of the software,
|
|
29
|
+
together with instructions (in the manual page or equivalent)
|
|
30
|
+
on where to get the original distribution.
|
|
31
|
+
|
|
32
|
+
b. accompany the distribution with the machine-readable source of
|
|
33
|
+
the software.
|
|
34
|
+
|
|
35
|
+
c. give non-standard binaries non-standard names, with
|
|
36
|
+
instructions on where to get the original software distribution.
|
|
37
|
+
|
|
38
|
+
d. make other distribution arrangements with the author.
|
|
39
|
+
|
|
40
|
+
4. You may modify and include the part of the software into any other
|
|
41
|
+
software (possibly commercial). But some files in the distribution
|
|
42
|
+
are not written by the author, so that they are not under these terms.
|
|
43
|
+
|
|
44
|
+
For the list of those files and their copying conditions, see the
|
|
45
|
+
file LEGAL.
|
|
46
|
+
|
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
|
48
|
+
output from the software do not automatically fall under the
|
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
|
51
|
+
software.
|
|
52
|
+
|
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
56
|
+
PURPOSE.
|
data/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Win32::Registry
|
|
2
|
+
|
|
3
|
+
win32-registry is registry accessor library for the Windows platform.
|
|
4
|
+
It uses Fiddle to call Windows Registry APIs.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
win32-registry is a bundled gem of the ruby standard library, so that the latest version on the ruby release date is preinstalled on Windows.
|
|
9
|
+
Other versions of the gem can be installed in addition like so:
|
|
10
|
+
|
|
11
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
12
|
+
|
|
13
|
+
$ bundle add win32-registry
|
|
14
|
+
|
|
15
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
16
|
+
|
|
17
|
+
$ gem install win32-registry
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
require "win32/registry"
|
|
23
|
+
|
|
24
|
+
Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
|
|
25
|
+
value = reg['foo'] # read a value
|
|
26
|
+
value = reg['foo', Win32::Registry::REG_SZ] # read a value with type
|
|
27
|
+
type, value = reg.read('foo') # read a value
|
|
28
|
+
reg['foo'] = 'bar' # write a value
|
|
29
|
+
reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type
|
|
30
|
+
reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
|
|
31
|
+
|
|
32
|
+
reg.each_value { |name, type, data| ... } # Enumerate values
|
|
33
|
+
reg.each_key { |key, wtime| ... } # Enumerate subkeys
|
|
34
|
+
|
|
35
|
+
reg.delete_value(name) # Delete a value
|
|
36
|
+
reg.delete_key(name) # Delete a subkey
|
|
37
|
+
reg.delete_key(name, true) # Delete a subkey recursively
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Be sure to use backslashs "\\" as path separator.
|
|
42
|
+
Forward slashs "/" will not work.
|
|
43
|
+
This is in contrast to file paths, which accept forward and backward slashs at will on Windows.
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
49
|
+
|
|
50
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
51
|
+
|
|
52
|
+
## Contributing
|
|
53
|
+
|
|
54
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/win32-registry.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,922 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'fiddle/import'
|
|
3
|
+
|
|
4
|
+
module Win32
|
|
5
|
+
|
|
6
|
+
=begin rdoc
|
|
7
|
+
= Win32 Registry
|
|
8
|
+
|
|
9
|
+
win32/registry is registry accessor library for Win32 platform.
|
|
10
|
+
It uses importer to call Win32 Registry APIs.
|
|
11
|
+
|
|
12
|
+
== example
|
|
13
|
+
Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
|
|
14
|
+
value = reg['foo'] # read a value
|
|
15
|
+
value = reg['foo', Win32::Registry::REG_SZ] # read a value with type
|
|
16
|
+
type, value = reg.read('foo') # read a value
|
|
17
|
+
reg['foo'] = 'bar' # write a value
|
|
18
|
+
reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type
|
|
19
|
+
reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
|
|
20
|
+
|
|
21
|
+
reg.each_value { |name, type, data| ... } # Enumerate values
|
|
22
|
+
reg.each_key { |key, wtime| ... } # Enumerate subkeys
|
|
23
|
+
|
|
24
|
+
reg.delete_value(name) # Delete a value
|
|
25
|
+
reg.delete_key(name) # Delete a subkey
|
|
26
|
+
reg.delete_key(name, true) # Delete a subkey recursively
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
= Reference
|
|
30
|
+
|
|
31
|
+
== Win32::Registry class
|
|
32
|
+
|
|
33
|
+
--- info
|
|
34
|
+
|
|
35
|
+
--- num_keys
|
|
36
|
+
|
|
37
|
+
--- max_key_length
|
|
38
|
+
|
|
39
|
+
--- num_values
|
|
40
|
+
|
|
41
|
+
--- max_value_name_length
|
|
42
|
+
|
|
43
|
+
--- max_value_length
|
|
44
|
+
|
|
45
|
+
--- descriptor_length
|
|
46
|
+
|
|
47
|
+
--- wtime
|
|
48
|
+
Returns an item of key information.
|
|
49
|
+
|
|
50
|
+
=== constants
|
|
51
|
+
--- HKEY_CLASSES_ROOT
|
|
52
|
+
|
|
53
|
+
--- HKEY_CURRENT_USER
|
|
54
|
+
|
|
55
|
+
--- HKEY_LOCAL_MACHINE
|
|
56
|
+
|
|
57
|
+
--- HKEY_PERFORMANCE_DATA
|
|
58
|
+
|
|
59
|
+
--- HKEY_CURRENT_CONFIG
|
|
60
|
+
|
|
61
|
+
--- HKEY_DYN_DATA
|
|
62
|
+
|
|
63
|
+
Win32::Registry object whose key is predefined key.
|
|
64
|
+
For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article.
|
|
65
|
+
|
|
66
|
+
=end rdoc
|
|
67
|
+
|
|
68
|
+
WCHAR = Encoding::UTF_16LE
|
|
69
|
+
WCHAR_NUL = "\0".encode(WCHAR).freeze
|
|
70
|
+
WCHAR_CR = "\r".encode(WCHAR).freeze
|
|
71
|
+
WCHAR_SIZE = WCHAR_NUL.bytesize
|
|
72
|
+
LOCALE = Encoding::UTF_8
|
|
73
|
+
|
|
74
|
+
class Registry
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp].
|
|
78
|
+
#
|
|
79
|
+
# --- HKEY_*
|
|
80
|
+
#
|
|
81
|
+
# Predefined key ((*handle*)).
|
|
82
|
+
# These are Integer, not Win32::Registry.
|
|
83
|
+
#
|
|
84
|
+
# --- REG_*
|
|
85
|
+
#
|
|
86
|
+
# Registry value type.
|
|
87
|
+
#
|
|
88
|
+
# --- KEY_*
|
|
89
|
+
#
|
|
90
|
+
# Security access mask.
|
|
91
|
+
#
|
|
92
|
+
# --- KEY_OPTIONS_*
|
|
93
|
+
#
|
|
94
|
+
# Key options.
|
|
95
|
+
#
|
|
96
|
+
# --- REG_CREATED_NEW_KEY
|
|
97
|
+
#
|
|
98
|
+
# --- REG_OPENED_EXISTING_KEY
|
|
99
|
+
#
|
|
100
|
+
# If the key is created newly or opened existing key.
|
|
101
|
+
# See also Registry#disposition method.
|
|
102
|
+
module Constants
|
|
103
|
+
HKEY_CLASSES_ROOT = 0x80000000
|
|
104
|
+
HKEY_CURRENT_USER = 0x80000001
|
|
105
|
+
HKEY_LOCAL_MACHINE = 0x80000002
|
|
106
|
+
HKEY_USERS = 0x80000003
|
|
107
|
+
HKEY_PERFORMANCE_DATA = 0x80000004
|
|
108
|
+
HKEY_PERFORMANCE_TEXT = 0x80000050
|
|
109
|
+
HKEY_PERFORMANCE_NLSTEXT = 0x80000060
|
|
110
|
+
HKEY_CURRENT_CONFIG = 0x80000005
|
|
111
|
+
HKEY_DYN_DATA = 0x80000006
|
|
112
|
+
|
|
113
|
+
REG_NONE = 0
|
|
114
|
+
REG_SZ = 1
|
|
115
|
+
REG_EXPAND_SZ = 2
|
|
116
|
+
REG_BINARY = 3
|
|
117
|
+
REG_DWORD = 4
|
|
118
|
+
REG_DWORD_LITTLE_ENDIAN = 4
|
|
119
|
+
REG_DWORD_BIG_ENDIAN = 5
|
|
120
|
+
REG_LINK = 6
|
|
121
|
+
REG_MULTI_SZ = 7
|
|
122
|
+
REG_RESOURCE_LIST = 8
|
|
123
|
+
REG_FULL_RESOURCE_DESCRIPTOR = 9
|
|
124
|
+
REG_RESOURCE_REQUIREMENTS_LIST = 10
|
|
125
|
+
REG_QWORD = 11
|
|
126
|
+
REG_QWORD_LITTLE_ENDIAN = 11
|
|
127
|
+
|
|
128
|
+
STANDARD_RIGHTS_READ = 0x00020000
|
|
129
|
+
STANDARD_RIGHTS_WRITE = 0x00020000
|
|
130
|
+
KEY_QUERY_VALUE = 0x0001
|
|
131
|
+
KEY_SET_VALUE = 0x0002
|
|
132
|
+
KEY_CREATE_SUB_KEY = 0x0004
|
|
133
|
+
KEY_ENUMERATE_SUB_KEYS = 0x0008
|
|
134
|
+
KEY_NOTIFY = 0x0010
|
|
135
|
+
KEY_CREATE_LINK = 0x0020
|
|
136
|
+
KEY_READ = STANDARD_RIGHTS_READ |
|
|
137
|
+
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY
|
|
138
|
+
KEY_WRITE = STANDARD_RIGHTS_WRITE |
|
|
139
|
+
KEY_SET_VALUE | KEY_CREATE_SUB_KEY
|
|
140
|
+
KEY_EXECUTE = KEY_READ
|
|
141
|
+
KEY_ALL_ACCESS = KEY_READ | KEY_WRITE | KEY_CREATE_LINK
|
|
142
|
+
|
|
143
|
+
REG_OPTION_RESERVED = 0x0000
|
|
144
|
+
REG_OPTION_NON_VOLATILE = 0x0000
|
|
145
|
+
REG_OPTION_VOLATILE = 0x0001
|
|
146
|
+
REG_OPTION_CREATE_LINK = 0x0002
|
|
147
|
+
REG_OPTION_BACKUP_RESTORE = 0x0004
|
|
148
|
+
REG_OPTION_OPEN_LINK = 0x0008
|
|
149
|
+
REG_LEGAL_OPTION = REG_OPTION_RESERVED |
|
|
150
|
+
REG_OPTION_NON_VOLATILE | REG_OPTION_CREATE_LINK |
|
|
151
|
+
REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK
|
|
152
|
+
|
|
153
|
+
REG_CREATED_NEW_KEY = 1
|
|
154
|
+
REG_OPENED_EXISTING_KEY = 2
|
|
155
|
+
|
|
156
|
+
REG_WHOLE_HIVE_VOLATILE = 0x0001
|
|
157
|
+
REG_REFRESH_HIVE = 0x0002
|
|
158
|
+
REG_NO_LAZY_FLUSH = 0x0004
|
|
159
|
+
REG_FORCE_RESTORE = 0x0008
|
|
160
|
+
|
|
161
|
+
MAX_KEY_LENGTH = 514
|
|
162
|
+
MAX_VALUE_LENGTH = 32768
|
|
163
|
+
end
|
|
164
|
+
include Constants
|
|
165
|
+
include Enumerable
|
|
166
|
+
|
|
167
|
+
#
|
|
168
|
+
# Error
|
|
169
|
+
#
|
|
170
|
+
class Error < ::StandardError
|
|
171
|
+
module Kernel32
|
|
172
|
+
extend Fiddle::Importer
|
|
173
|
+
dlload "kernel32.dll"
|
|
174
|
+
end
|
|
175
|
+
FormatMessageW = Kernel32.extern "int FormatMessageW(int, void *, int, int, void *, int, void *)", :stdcall
|
|
176
|
+
def initialize(code)
|
|
177
|
+
@code = code
|
|
178
|
+
buff = WCHAR_NUL * 1024
|
|
179
|
+
lang = 0
|
|
180
|
+
begin
|
|
181
|
+
len = FormatMessageW.call(0x1200, 0, code, lang, buff, 1024, 0)
|
|
182
|
+
msg = buff.byteslice(0, len * WCHAR_SIZE)
|
|
183
|
+
msg.delete!(WCHAR_CR)
|
|
184
|
+
msg.chomp!
|
|
185
|
+
msg.encode!(LOCALE)
|
|
186
|
+
rescue EncodingError
|
|
187
|
+
raise unless lang == 0
|
|
188
|
+
lang = 0x0409 # en_US
|
|
189
|
+
retry
|
|
190
|
+
end
|
|
191
|
+
super msg
|
|
192
|
+
end
|
|
193
|
+
attr_reader :code
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
#
|
|
197
|
+
# Predefined Keys
|
|
198
|
+
#
|
|
199
|
+
class PredefinedKey < Registry
|
|
200
|
+
def initialize(hkey, keyname)
|
|
201
|
+
@hkey = hkey
|
|
202
|
+
@parent = nil
|
|
203
|
+
@keyname = keyname
|
|
204
|
+
@disposition = REG_OPENED_EXISTING_KEY
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Predefined keys cannot be closed
|
|
208
|
+
def close
|
|
209
|
+
raise Error.new(5) ## ERROR_ACCESS_DENIED
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Fake #class method for Registry#open, Registry#create
|
|
213
|
+
def class
|
|
214
|
+
Registry
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Make all
|
|
218
|
+
Constants.constants.grep(/^HKEY_/) do |c|
|
|
219
|
+
Registry.const_set c, new(Constants.const_get(c), c.to_s)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
#
|
|
224
|
+
# Win32 APIs
|
|
225
|
+
#
|
|
226
|
+
module API
|
|
227
|
+
include Constants
|
|
228
|
+
extend Fiddle::Importer
|
|
229
|
+
dlload "advapi32.dll"
|
|
230
|
+
[
|
|
231
|
+
"long RegOpenKeyExW(void *, void *, long, long, void *)",
|
|
232
|
+
"long RegCreateKeyExW(void *, void *, long, long, long, long, void *, void *, void *)",
|
|
233
|
+
"long RegEnumValueW(void *, long, void *, void *, void *, void *, void *, void *)",
|
|
234
|
+
"long RegEnumKeyExW(void *, long, void *, void *, void *, void *, void *, void *)",
|
|
235
|
+
"long RegQueryValueExW(void *, void *, void *, void *, void *, void *)",
|
|
236
|
+
"long RegSetValueExW(void *, void *, long, long, void *, long)",
|
|
237
|
+
"long RegDeleteValueW(void *, void *)",
|
|
238
|
+
"long RegDeleteKeyW(void *, void *)",
|
|
239
|
+
"long RegFlushKey(void *)",
|
|
240
|
+
"long RegCloseKey(void *)",
|
|
241
|
+
"long RegQueryInfoKey(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)",
|
|
242
|
+
].each do |fn|
|
|
243
|
+
cfunc = extern fn, :stdcall
|
|
244
|
+
const_set cfunc.name.intern, cfunc
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
module_function
|
|
248
|
+
|
|
249
|
+
def check(result)
|
|
250
|
+
raise Error, result, caller(1) if result != 0
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def win64?
|
|
254
|
+
/^(?:x64|x86_64)/ =~ RUBY_PLATFORM
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
TEMPLATE_HANDLE = 'J<'
|
|
258
|
+
|
|
259
|
+
def packhandle(h)
|
|
260
|
+
[h].pack(TEMPLATE_HANDLE)
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def unpackhandle(h)
|
|
264
|
+
(h + [0].pack(TEMPLATE_HANDLE)).unpack1(TEMPLATE_HANDLE)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
TEMPLATE_DWORD = 'V'
|
|
268
|
+
|
|
269
|
+
def packdw(dw)
|
|
270
|
+
[dw].pack(TEMPLATE_DWORD)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def unpackdw(dw)
|
|
274
|
+
(dw + [0].pack(TEMPLATE_DWORD)).unpack1(TEMPLATE_DWORD)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
TEMPLATE_QWORD = 'Q<'
|
|
278
|
+
|
|
279
|
+
def packqw(qw)
|
|
280
|
+
[qw].pack(TEMPLATE_QWORD)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def unpackqw(qw)
|
|
284
|
+
(qw + [0].pack(TEMPLATE_QWORD)).unpack1(TEMPLATE_QWORD)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def make_wstr(str)
|
|
288
|
+
str.encode(WCHAR)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def OpenKey(hkey, name, opt, desired)
|
|
292
|
+
result = packhandle(0)
|
|
293
|
+
check RegOpenKeyExW.call(hkey, make_wstr(name), opt, desired, result)
|
|
294
|
+
unpackhandle(result)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def CreateKey(hkey, name, opt, desired)
|
|
298
|
+
result = packhandle(0)
|
|
299
|
+
disp = packdw(0)
|
|
300
|
+
check RegCreateKeyExW.call(hkey, make_wstr(name), 0, 0, opt, desired,
|
|
301
|
+
0, result, disp)
|
|
302
|
+
[ unpackhandle(result), unpackdw(disp) ]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def EnumValue(hkey, index)
|
|
306
|
+
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
|
|
307
|
+
size = packdw(Constants::MAX_KEY_LENGTH)
|
|
308
|
+
check RegEnumValueW.call(hkey, index, name, size, 0, 0, 0, 0)
|
|
309
|
+
name.byteslice(0, unpackdw(size) * WCHAR_SIZE)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def EnumKey(hkey, index)
|
|
313
|
+
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
|
|
314
|
+
size = packdw(Constants::MAX_KEY_LENGTH)
|
|
315
|
+
wtime = ' ' * 8
|
|
316
|
+
check RegEnumKeyExW.call(hkey, index, name, size, 0, 0, 0, wtime)
|
|
317
|
+
[ name.byteslice(0, unpackdw(size) * WCHAR_SIZE), unpackqw(wtime) ]
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def QueryValue(hkey, name)
|
|
321
|
+
type = packdw(0)
|
|
322
|
+
size = packdw(0)
|
|
323
|
+
name = make_wstr(name)
|
|
324
|
+
check RegQueryValueExW.call(hkey, name, 0, type, 0, size)
|
|
325
|
+
data = "\0".b * unpackdw(size)
|
|
326
|
+
check RegQueryValueExW.call(hkey, name, 0, type, data, size)
|
|
327
|
+
[ unpackdw(type), data[0, unpackdw(size)] ]
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def SetValue(hkey, name, type, data, size)
|
|
331
|
+
case type
|
|
332
|
+
when REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ
|
|
333
|
+
data = data.encode(WCHAR)
|
|
334
|
+
size ||= data.bytesize + WCHAR_SIZE
|
|
335
|
+
end
|
|
336
|
+
check RegSetValueExW.call(hkey, make_wstr(name), 0, type, data, size)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def DeleteValue(hkey, name)
|
|
340
|
+
check RegDeleteValueW.call(hkey, make_wstr(name))
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def DeleteKey(hkey, name)
|
|
344
|
+
check RegDeleteKeyW.call(hkey, make_wstr(name))
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def FlushKey(hkey)
|
|
348
|
+
check RegFlushKey.call(hkey)
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def CloseKey(hkey)
|
|
352
|
+
check RegCloseKey.call(hkey)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def QueryInfoKey(hkey)
|
|
356
|
+
subkeys = packdw(0)
|
|
357
|
+
maxsubkeylen = packdw(0)
|
|
358
|
+
values = packdw(0)
|
|
359
|
+
maxvaluenamelen = packdw(0)
|
|
360
|
+
maxvaluelen = packdw(0)
|
|
361
|
+
secdescs = packdw(0)
|
|
362
|
+
wtime = ' ' * 8
|
|
363
|
+
check RegQueryInfoKey.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0,
|
|
364
|
+
values, maxvaluenamelen, maxvaluelen, secdescs, wtime)
|
|
365
|
+
[ unpackdw(subkeys), unpackdw(maxsubkeylen), unpackdw(values),
|
|
366
|
+
unpackdw(maxvaluenamelen), unpackdw(maxvaluelen),
|
|
367
|
+
unpackdw(secdescs), unpackqw(wtime) ]
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
#
|
|
372
|
+
# Replace %\w+% into the environment value of what is contained between the %'s
|
|
373
|
+
# This method is used for REG_EXPAND_SZ.
|
|
374
|
+
#
|
|
375
|
+
# For detail, see expandEnvironmentStrings[http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp] \Win32 \API.
|
|
376
|
+
#
|
|
377
|
+
def self.expand_environ(str)
|
|
378
|
+
str.gsub(Regexp.compile("%([^%]+)%".encode(str.encoding))) {
|
|
379
|
+
v = $1.encode(LOCALE)
|
|
380
|
+
(ENV[v] || ENV[v.upcase])&.encode(str.encoding) || $&
|
|
381
|
+
}
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
@@type2name = %w[
|
|
385
|
+
REG_NONE REG_SZ REG_EXPAND_SZ REG_BINARY REG_DWORD
|
|
386
|
+
REG_DWORD_BIG_ENDIAN REG_LINK REG_MULTI_SZ
|
|
387
|
+
REG_RESOURCE_LIST REG_FULL_RESOURCE_DESCRIPTOR
|
|
388
|
+
REG_RESOURCE_REQUIREMENTS_LIST REG_QWORD
|
|
389
|
+
].inject([]) do |ary, type|
|
|
390
|
+
ary[Constants.const_get(type)] = type
|
|
391
|
+
ary
|
|
392
|
+
end.freeze
|
|
393
|
+
|
|
394
|
+
#
|
|
395
|
+
# Convert registry type value to readable string.
|
|
396
|
+
#
|
|
397
|
+
def self.type2name(type)
|
|
398
|
+
@@type2name[type] || type.to_s
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
#
|
|
402
|
+
# Convert 64-bit FILETIME integer into Time object.
|
|
403
|
+
#
|
|
404
|
+
def self.wtime2time(wtime)
|
|
405
|
+
Time.at((wtime - 116444736000000000) / 10000000)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
#
|
|
409
|
+
# Convert Time object or Integer object into 64-bit FILETIME.
|
|
410
|
+
#
|
|
411
|
+
def self.time2wtime(time)
|
|
412
|
+
time.to_i * 10000000 + 116444736000000000
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
#
|
|
416
|
+
# constructor
|
|
417
|
+
#
|
|
418
|
+
private_class_method :new
|
|
419
|
+
|
|
420
|
+
#
|
|
421
|
+
# --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
|
|
422
|
+
#
|
|
423
|
+
# --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... }
|
|
424
|
+
#
|
|
425
|
+
# Open the registry key subkey under key.
|
|
426
|
+
# key is Win32::Registry object of parent key.
|
|
427
|
+
# You can use predefined key HKEY_* (see Constants)
|
|
428
|
+
# desired and opt is access mask and key option.
|
|
429
|
+
# For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp].
|
|
430
|
+
# If block is given, the key is closed automatically.
|
|
431
|
+
def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
|
|
432
|
+
subkey = subkey.chomp('\\')
|
|
433
|
+
newkey = API.OpenKey(hkey.hkey, subkey, opt, desired)
|
|
434
|
+
obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY)
|
|
435
|
+
if block_given?
|
|
436
|
+
begin
|
|
437
|
+
yield obj
|
|
438
|
+
ensure
|
|
439
|
+
obj.close
|
|
440
|
+
end
|
|
441
|
+
else
|
|
442
|
+
obj
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
#
|
|
447
|
+
# --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
|
|
448
|
+
#
|
|
449
|
+
# --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... }
|
|
450
|
+
#
|
|
451
|
+
# Create or open the registry key subkey under key.
|
|
452
|
+
# You can use predefined key HKEY_* (see Constants)
|
|
453
|
+
#
|
|
454
|
+
# If subkey is already exists, key is opened and Registry#created?
|
|
455
|
+
# method will return false.
|
|
456
|
+
#
|
|
457
|
+
# If block is given, the key is closed automatically.
|
|
458
|
+
#
|
|
459
|
+
def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
|
|
460
|
+
newkey, disp = API.CreateKey(hkey.hkey, subkey, opt, desired)
|
|
461
|
+
obj = new(newkey, hkey, subkey, disp)
|
|
462
|
+
if block_given?
|
|
463
|
+
begin
|
|
464
|
+
yield obj
|
|
465
|
+
ensure
|
|
466
|
+
obj.close
|
|
467
|
+
end
|
|
468
|
+
else
|
|
469
|
+
obj
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
#
|
|
474
|
+
# finalizer
|
|
475
|
+
#
|
|
476
|
+
@@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } }
|
|
477
|
+
|
|
478
|
+
#
|
|
479
|
+
# initialize
|
|
480
|
+
#
|
|
481
|
+
def initialize(hkey, parent, keyname, disposition)
|
|
482
|
+
@hkey = hkey
|
|
483
|
+
@parent = parent
|
|
484
|
+
@keyname = keyname
|
|
485
|
+
@disposition = disposition
|
|
486
|
+
@hkeyfinal = [ hkey ]
|
|
487
|
+
ObjectSpace.define_finalizer self, @@final.call(@hkeyfinal)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
# Returns key handle value.
|
|
491
|
+
attr_reader :hkey
|
|
492
|
+
# Win32::Registry object of parent key, or nil if predefeined key.
|
|
493
|
+
attr_reader :parent
|
|
494
|
+
# Same as subkey value of Registry.open or
|
|
495
|
+
# Registry.create method.
|
|
496
|
+
attr_reader :keyname
|
|
497
|
+
# Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY).
|
|
498
|
+
attr_reader :disposition
|
|
499
|
+
|
|
500
|
+
#
|
|
501
|
+
# Returns if key is created ((*newly*)).
|
|
502
|
+
# (see Registry.create) -- basically you call create
|
|
503
|
+
# then when you call created? on the instance returned
|
|
504
|
+
# it will tell if it was successful or not
|
|
505
|
+
#
|
|
506
|
+
def created?
|
|
507
|
+
@disposition == REG_CREATED_NEW_KEY
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
#
|
|
511
|
+
# Returns if key is not closed.
|
|
512
|
+
#
|
|
513
|
+
def open?
|
|
514
|
+
!@hkey.nil?
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
#
|
|
518
|
+
# Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'.
|
|
519
|
+
#
|
|
520
|
+
def name
|
|
521
|
+
parent = self
|
|
522
|
+
name = @keyname
|
|
523
|
+
while parent = parent.parent
|
|
524
|
+
name = parent.keyname + '\\' + name
|
|
525
|
+
end
|
|
526
|
+
name
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def inspect
|
|
530
|
+
"\#<Win32::Registry key=#{name.inspect}>"
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
#
|
|
534
|
+
# marshalling is not allowed
|
|
535
|
+
#
|
|
536
|
+
def _dump(depth)
|
|
537
|
+
raise TypeError, "can't dump Win32::Registry"
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
#
|
|
541
|
+
# Same as Win32::Registry.open (self, subkey, desired, opt)
|
|
542
|
+
#
|
|
543
|
+
def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk)
|
|
544
|
+
self.class.open(self, subkey, desired, opt, &blk)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
#
|
|
548
|
+
# Same as Win32::Registry.create (self, subkey, desired, opt)
|
|
549
|
+
#
|
|
550
|
+
def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
|
|
551
|
+
self.class.create(self, subkey, desired, opt, &blk)
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
#
|
|
555
|
+
# Close key.
|
|
556
|
+
#
|
|
557
|
+
# After close, most method raise an error.
|
|
558
|
+
#
|
|
559
|
+
def close
|
|
560
|
+
API.CloseKey(@hkey)
|
|
561
|
+
@hkey = @parent = @keyname = nil
|
|
562
|
+
@hkeyfinal[0] = nil
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
#
|
|
566
|
+
# Enumerate all values in this registry path.
|
|
567
|
+
#
|
|
568
|
+
# For each value it yields key, type and data.
|
|
569
|
+
#
|
|
570
|
+
# key is a String which contains name of key.
|
|
571
|
+
# type is a type contant kind of Win32::Registry::REG_*
|
|
572
|
+
# data is the value of this key.
|
|
573
|
+
#
|
|
574
|
+
def each_value
|
|
575
|
+
return enum_for(:each_value) unless block_given?
|
|
576
|
+
index = 0
|
|
577
|
+
while true
|
|
578
|
+
begin
|
|
579
|
+
subkey = API.EnumValue(@hkey, index)
|
|
580
|
+
rescue Error
|
|
581
|
+
break
|
|
582
|
+
end
|
|
583
|
+
subkey = export_string(subkey)
|
|
584
|
+
begin
|
|
585
|
+
type, data = read(subkey)
|
|
586
|
+
rescue Error
|
|
587
|
+
else
|
|
588
|
+
yield subkey, type, data
|
|
589
|
+
end
|
|
590
|
+
index += 1
|
|
591
|
+
end
|
|
592
|
+
index
|
|
593
|
+
end
|
|
594
|
+
alias each each_value
|
|
595
|
+
|
|
596
|
+
#
|
|
597
|
+
# return values as an array
|
|
598
|
+
#
|
|
599
|
+
def values
|
|
600
|
+
vals_ary = []
|
|
601
|
+
each_value { |*, val| vals_ary << val }
|
|
602
|
+
vals_ary
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
#
|
|
606
|
+
# Enumerate all subkeys.
|
|
607
|
+
#
|
|
608
|
+
# For each subkey it yields subkey and wtime.
|
|
609
|
+
#
|
|
610
|
+
# subkey is String which contains name of subkey.
|
|
611
|
+
# wtime is last write time as FILETIME (64-bit integer).
|
|
612
|
+
# (see Registry.wtime2time)
|
|
613
|
+
#
|
|
614
|
+
def each_key
|
|
615
|
+
return enum_for(:each_key) unless block_given?
|
|
616
|
+
index = 0
|
|
617
|
+
while true
|
|
618
|
+
begin
|
|
619
|
+
subkey, wtime = API.EnumKey(@hkey, index)
|
|
620
|
+
rescue Error
|
|
621
|
+
break
|
|
622
|
+
end
|
|
623
|
+
subkey = export_string(subkey)
|
|
624
|
+
yield subkey, wtime
|
|
625
|
+
index += 1
|
|
626
|
+
end
|
|
627
|
+
index
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
#
|
|
631
|
+
# return keys as an array
|
|
632
|
+
#
|
|
633
|
+
def keys
|
|
634
|
+
keys_ary = []
|
|
635
|
+
each_key { |key,| keys_ary << key }
|
|
636
|
+
keys_ary
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
# Read a registry value named name and return array of
|
|
640
|
+
# [ type, data ].
|
|
641
|
+
# When name is nil, the `default' value is read.
|
|
642
|
+
# type is value type. (see Win32::Registry::Constants module)
|
|
643
|
+
# data is value data, its class is:
|
|
644
|
+
# :REG_SZ, REG_EXPAND_SZ
|
|
645
|
+
# String
|
|
646
|
+
# :REG_MULTI_SZ
|
|
647
|
+
# Array of String
|
|
648
|
+
# :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
|
|
649
|
+
# Integer
|
|
650
|
+
# :REG_BINARY, REG_NONE
|
|
651
|
+
# String (contains binary data)
|
|
652
|
+
#
|
|
653
|
+
# When rtype is specified, the value type must be included by
|
|
654
|
+
# rtype array, or TypeError is raised.
|
|
655
|
+
def read(name, *rtype)
|
|
656
|
+
type, data = API.QueryValue(@hkey, name)
|
|
657
|
+
unless rtype.empty? or rtype.include?(type)
|
|
658
|
+
raise TypeError, "Type mismatch (expect [#{
|
|
659
|
+
rtype.map{|t|Registry.type2name(t)}.join(', ')}] but #{
|
|
660
|
+
Registry.type2name(type)} present)"
|
|
661
|
+
end
|
|
662
|
+
case type
|
|
663
|
+
when REG_SZ, REG_EXPAND_SZ
|
|
664
|
+
[ type, data.encode(name.encoding, WCHAR).chop ]
|
|
665
|
+
when REG_MULTI_SZ
|
|
666
|
+
[ type, data.encode(name.encoding, WCHAR).split(/\0/) ]
|
|
667
|
+
when REG_BINARY, REG_NONE
|
|
668
|
+
[ type, data ]
|
|
669
|
+
when REG_DWORD
|
|
670
|
+
[ type, API.unpackdw(data) ]
|
|
671
|
+
when REG_DWORD_BIG_ENDIAN
|
|
672
|
+
[ type, data.unpack1('N') ]
|
|
673
|
+
when REG_QWORD
|
|
674
|
+
[ type, API.unpackqw(data) ]
|
|
675
|
+
else
|
|
676
|
+
raise TypeError, "Type #{Registry.type2name(type)} is not supported."
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
#
|
|
681
|
+
# Read a registry value named name and return its value data.
|
|
682
|
+
# The class of the value is the same as the #read method returns.
|
|
683
|
+
#
|
|
684
|
+
# If the value type is REG_EXPAND_SZ, returns value data whose environment
|
|
685
|
+
# variables are replaced.
|
|
686
|
+
# If the value type is neither REG_SZ, REG_MULTI_SZ, REG_DWORD,
|
|
687
|
+
# REG_DWORD_BIG_ENDIAN, nor REG_QWORD, TypeError is raised.
|
|
688
|
+
#
|
|
689
|
+
# The meaning of rtype is the same as for the #read method.
|
|
690
|
+
#
|
|
691
|
+
def [](name, *rtype)
|
|
692
|
+
type, data = read(name, *rtype)
|
|
693
|
+
case type
|
|
694
|
+
when REG_SZ, REG_DWORD, REG_QWORD, REG_MULTI_SZ
|
|
695
|
+
data
|
|
696
|
+
when REG_EXPAND_SZ
|
|
697
|
+
Registry.expand_environ(data)
|
|
698
|
+
else
|
|
699
|
+
raise TypeError, "Type #{Registry.type2name(type)} is not supported."
|
|
700
|
+
end
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
|
|
704
|
+
# registry value named name.
|
|
705
|
+
#
|
|
706
|
+
# If the values type does not match, TypeError is raised.
|
|
707
|
+
def read_s(name)
|
|
708
|
+
read(name, REG_SZ)[1]
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
#
|
|
712
|
+
# Read a REG_SZ or REG_EXPAND_SZ registry value named name.
|
|
713
|
+
#
|
|
714
|
+
# If the value type is REG_EXPAND_SZ, environment variables are replaced.
|
|
715
|
+
# Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised.
|
|
716
|
+
#
|
|
717
|
+
def read_s_expand(name)
|
|
718
|
+
type, data = read(name, REG_SZ, REG_EXPAND_SZ)
|
|
719
|
+
if type == REG_EXPAND_SZ
|
|
720
|
+
Registry.expand_environ(data)
|
|
721
|
+
else
|
|
722
|
+
data
|
|
723
|
+
end
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
#
|
|
727
|
+
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
|
|
728
|
+
# registry value named name.
|
|
729
|
+
#
|
|
730
|
+
# If the values type does not match, TypeError is raised.
|
|
731
|
+
#
|
|
732
|
+
def read_i(name)
|
|
733
|
+
read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1]
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
#
|
|
737
|
+
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
|
|
738
|
+
# registry value named name.
|
|
739
|
+
#
|
|
740
|
+
# If the values type does not match, TypeError is raised.
|
|
741
|
+
#
|
|
742
|
+
def read_bin(name)
|
|
743
|
+
read(name, REG_BINARY)[1]
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
#
|
|
747
|
+
# Write data to a registry value named name.
|
|
748
|
+
# When name is nil, write to the `default' value.
|
|
749
|
+
#
|
|
750
|
+
# type is type value. (see Registry::Constants module)
|
|
751
|
+
# Class of data must be same as which #read
|
|
752
|
+
# method returns.
|
|
753
|
+
#
|
|
754
|
+
def write(name, type, data)
|
|
755
|
+
case type
|
|
756
|
+
when REG_SZ, REG_EXPAND_SZ
|
|
757
|
+
data = data.encode(WCHAR) << WCHAR_NUL
|
|
758
|
+
when REG_MULTI_SZ
|
|
759
|
+
data = data.to_a.map {|s| s.encode(WCHAR)}.join(WCHAR_NUL) << WCHAR_NUL
|
|
760
|
+
when REG_BINARY, REG_NONE
|
|
761
|
+
data = data.to_s
|
|
762
|
+
when REG_DWORD
|
|
763
|
+
data = API.packdw(data.to_i)
|
|
764
|
+
when REG_DWORD_BIG_ENDIAN
|
|
765
|
+
data = [data.to_i].pack('N')
|
|
766
|
+
when REG_QWORD
|
|
767
|
+
data = API.packqw(data.to_i)
|
|
768
|
+
else
|
|
769
|
+
raise TypeError, "Unsupported type #{Registry.type2name(type)}"
|
|
770
|
+
end
|
|
771
|
+
API.SetValue(@hkey, name, type, data, data.bytesize)
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
#
|
|
775
|
+
# Write value to a registry value named name.
|
|
776
|
+
#
|
|
777
|
+
# If wtype is specified, the value type is it.
|
|
778
|
+
# Otherwise, the value type is depend on class of value:
|
|
779
|
+
# :Integer
|
|
780
|
+
# REG_DWORD
|
|
781
|
+
# :String
|
|
782
|
+
# REG_SZ
|
|
783
|
+
# :Array
|
|
784
|
+
# REG_MULTI_SZ
|
|
785
|
+
#
|
|
786
|
+
def []=(name, rtype, value = nil)
|
|
787
|
+
if value
|
|
788
|
+
write name, rtype, value
|
|
789
|
+
else
|
|
790
|
+
case value = rtype
|
|
791
|
+
when Integer
|
|
792
|
+
write name, REG_DWORD, value
|
|
793
|
+
when String
|
|
794
|
+
write name, REG_SZ, value
|
|
795
|
+
when Array
|
|
796
|
+
write name, REG_MULTI_SZ, value
|
|
797
|
+
else
|
|
798
|
+
raise TypeError, "Unexpected type #{value.class}"
|
|
799
|
+
end
|
|
800
|
+
end
|
|
801
|
+
value
|
|
802
|
+
end
|
|
803
|
+
|
|
804
|
+
#
|
|
805
|
+
# Write value to a registry value named name.
|
|
806
|
+
#
|
|
807
|
+
# The value type is REG_SZ(write_s), REG_DWORD(write_i), or
|
|
808
|
+
# REG_BINARY(write_bin).
|
|
809
|
+
#
|
|
810
|
+
def write_s(name, value)
|
|
811
|
+
write name, REG_SZ, value.to_s
|
|
812
|
+
end
|
|
813
|
+
|
|
814
|
+
#
|
|
815
|
+
# Write value to a registry value named name.
|
|
816
|
+
#
|
|
817
|
+
# The value type is REG_SZ(write_s), REG_DWORD(write_i), or
|
|
818
|
+
# REG_BINARY(write_bin).
|
|
819
|
+
#
|
|
820
|
+
def write_i(name, value)
|
|
821
|
+
write name, REG_DWORD, value.to_i
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
#
|
|
825
|
+
# Write value to a registry value named name.
|
|
826
|
+
#
|
|
827
|
+
# The value type is REG_SZ(write_s), REG_DWORD(write_i), or
|
|
828
|
+
# REG_BINARY(write_bin).
|
|
829
|
+
#
|
|
830
|
+
def write_bin(name, value)
|
|
831
|
+
write name, REG_BINARY, value.to_s
|
|
832
|
+
end
|
|
833
|
+
|
|
834
|
+
#
|
|
835
|
+
# Delete a registry value named name.
|
|
836
|
+
# We can not delete the `default' value.
|
|
837
|
+
#
|
|
838
|
+
def delete_value(name)
|
|
839
|
+
API.DeleteValue(@hkey, name)
|
|
840
|
+
end
|
|
841
|
+
alias delete delete_value
|
|
842
|
+
|
|
843
|
+
#
|
|
844
|
+
# Delete a subkey named name and all its values.
|
|
845
|
+
#
|
|
846
|
+
# If recursive is false, the subkey must not have subkeys.
|
|
847
|
+
# Otherwise, this method deletes all subkeys and values recursively.
|
|
848
|
+
#
|
|
849
|
+
def delete_key(name, recursive = false)
|
|
850
|
+
if recursive
|
|
851
|
+
open(name, KEY_ALL_ACCESS) do |reg|
|
|
852
|
+
reg.keys.each do |key|
|
|
853
|
+
begin
|
|
854
|
+
reg.delete_key(key, true)
|
|
855
|
+
rescue Error
|
|
856
|
+
#
|
|
857
|
+
end
|
|
858
|
+
end
|
|
859
|
+
end
|
|
860
|
+
API.DeleteKey(@hkey, name)
|
|
861
|
+
else
|
|
862
|
+
begin
|
|
863
|
+
API.EnumKey @hkey, 0
|
|
864
|
+
rescue Error
|
|
865
|
+
return API.DeleteKey(@hkey, name)
|
|
866
|
+
end
|
|
867
|
+
raise Error.new(5) ## ERROR_ACCESS_DENIED
|
|
868
|
+
end
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
#
|
|
872
|
+
# Write all the attributes into the registry file.
|
|
873
|
+
#
|
|
874
|
+
def flush
|
|
875
|
+
API.FlushKey @hkey
|
|
876
|
+
end
|
|
877
|
+
|
|
878
|
+
#
|
|
879
|
+
# Returns key information as Array of:
|
|
880
|
+
# :num_keys
|
|
881
|
+
# The number of subkeys.
|
|
882
|
+
# :max_key_length
|
|
883
|
+
# Maximum length of name of subkeys.
|
|
884
|
+
# :num_values
|
|
885
|
+
# The number of values.
|
|
886
|
+
# :max_value_name_length
|
|
887
|
+
# Maximum length of name of values.
|
|
888
|
+
# :max_value_length
|
|
889
|
+
# Maximum length of value of values.
|
|
890
|
+
# :descriptor_length
|
|
891
|
+
# Length of security descriptor.
|
|
892
|
+
# :wtime
|
|
893
|
+
# Last write time as FILETIME(64-bit integer)
|
|
894
|
+
#
|
|
895
|
+
# For detail, see RegQueryInfoKey[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API.
|
|
896
|
+
#
|
|
897
|
+
def info
|
|
898
|
+
API.QueryInfoKey(@hkey)
|
|
899
|
+
end
|
|
900
|
+
|
|
901
|
+
#
|
|
902
|
+
# Returns an item of key information.
|
|
903
|
+
#
|
|
904
|
+
%w[
|
|
905
|
+
num_keys max_key_length
|
|
906
|
+
num_values max_value_name_length max_value_length
|
|
907
|
+
descriptor_length wtime
|
|
908
|
+
].each_with_index do |s, i|
|
|
909
|
+
eval <<-__END__
|
|
910
|
+
def #{s}
|
|
911
|
+
info[#{i}]
|
|
912
|
+
end
|
|
913
|
+
__END__
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
private
|
|
917
|
+
|
|
918
|
+
def export_string(str, enc = Encoding.default_internal || LOCALE) # :nodoc:
|
|
919
|
+
str.encode(enc)
|
|
920
|
+
end
|
|
921
|
+
end
|
|
922
|
+
end
|
data.tar.gz.sig
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
C���Cg |N�bN��U��%����#䖟W�̕��싙zͻY#�IѪ�7��n��/�P6[,6�K�Q�^�ENb�sdky���zި�st4�O�&P�������%�ΓCR��Q�Nj���u�URIc�2,Jhb+Na37��WAx<�����+����h��`�hJ�.,����$*�ad������]��ds�&�S��aۤ2/4�s��U�m��������X�sc���|>����%�m��A�gcl�m�W$)f� �+���z�y��T�o��a��>%oA�pBښ��:!�n|�����gg������3\�^d��.dJx�JCk�K�=��v�%�����x�MZ=�#!ȶq�p���k��o܅
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: win32-registry
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- U.Nakamura
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain:
|
|
10
|
+
- |
|
|
11
|
+
-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIEBDCCAmygAwIBAgIBAzANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1sYXJz
|
|
13
|
+
L0RDPWdyZWl6LXJlaW5zZG9yZi9EQz1kZTAeFw0yNDAyMjgxOTMxNDdaFw0yNTAy
|
|
14
|
+
MjcxOTMxNDdaMCgxJjAkBgNVBAMMHWxhcnMvREM9Z3JlaXotcmVpbnNkb3JmL0RD
|
|
15
|
+
PWRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwum6Y1KznfpzXOT/
|
|
16
|
+
mZgJTBbxZuuZF49Fq3K0WA67YBzNlDv95qzSp7V/7Ek3NCcnT7G+2kSuhNo1FhdN
|
|
17
|
+
eSDO/moYebZNAcu3iqLsuzuULXPLuoU0GsMnVMqV9DZPh7cQHE5EBZ7hlzDBK7k/
|
|
18
|
+
8nBMvR0mHo77kIkapHc26UzVq/G0nKLfDsIHXVylto3PjzOumjG6GhmFN4r3cP6e
|
|
19
|
+
SDfl1FSeRYVpt4kmQULz/zdSaOH3AjAq7PM2Z91iGwQvoUXMANH2v89OWjQO/NHe
|
|
20
|
+
JMNDFsmHK/6Ji4Kk48Z3TyscHQnipAID5GhS1oD21/WePdj7GhmbF5gBzkV5uepd
|
|
21
|
+
eJQPgWGwrQW/Z2oPjRuJrRofzWfrMWqbOahj9uth6WSxhNexUtbjk6P8emmXOJi5
|
|
22
|
+
chQPnWX+N3Gj+jjYxqTFdwT7Mj3pv1VHa+aNUbqSPpvJeDyxRIuo9hvzDaBHb/Cg
|
|
23
|
+
9qRVcm8a96n4t7y2lrX1oookY6bkBaxWOMtWlqIprq8JZXM9AgMBAAGjOTA3MAkG
|
|
24
|
+
A1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQ4h1tIyvdUWtMI739xMzTR
|
|
25
|
+
7EfMFzANBgkqhkiG9w0BAQsFAAOCAYEArBmHSfnUyNWf3R1Fx0mMHloWGdcKn2D2
|
|
26
|
+
BsqTApXU2nADiyppIqRq4b9e7hw342uzadSLkoQcEFOxThLRhAcijoWfQVBcsbV/
|
|
27
|
+
ZsCY1qlUTIJuSWxaSyS4efUX+N4eMNyPM9oW/sphlWFo0DgI34Y9WB6HDzH+O71y
|
|
28
|
+
R7PARke3f4kYnRJf5yRQLPDrH9UYt9KlBQm6l7XMtr5EMnQt0EfcmZEi9H4t/vS2
|
|
29
|
+
haxvpFMdAKo4H46GBYNO96r6b74t++vgQSBTg/AFVwvRZwNSrPPcBfb4xxeEAhRR
|
|
30
|
+
x+LU7feIH7lZ//3buiyD03gLAEtHXai0Y+/VfuWIpwYJAl2BO/tU7FS/dtbJq9oc
|
|
31
|
+
dI36Yyzy+BrCM0WT4oCsagePNb97FaNhl4F6sM5JEPT0ZPxRx0i3G4TNNIYziVos
|
|
32
|
+
5wFER6XhvvLDFAMh/jMg+s7Wd5SbSHgHNSUaUGVtdWkVPOer6oF0aLdZUR3CETkn
|
|
33
|
+
5nWXZma/BUd3YgYA/Xumc6QQqIS4p7mr
|
|
34
|
+
-----END CERTIFICATE-----
|
|
35
|
+
date: 2024-10-03 00:00:00.000000000 Z
|
|
36
|
+
dependencies:
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: fiddle
|
|
39
|
+
requirement: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - "~>"
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '1.0'
|
|
44
|
+
type: :runtime
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - "~>"
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '1.0'
|
|
51
|
+
description: Provides an interface to the Windows Registry in Ruby
|
|
52
|
+
email:
|
|
53
|
+
- usa@garbagecollect.jp
|
|
54
|
+
executables: []
|
|
55
|
+
extensions: []
|
|
56
|
+
extra_rdoc_files: []
|
|
57
|
+
files:
|
|
58
|
+
- BSDL
|
|
59
|
+
- COPYING
|
|
60
|
+
- README.md
|
|
61
|
+
- Rakefile
|
|
62
|
+
- lib/win32/registry.rb
|
|
63
|
+
- sig/win32/registry.rbs
|
|
64
|
+
homepage: https://github.com/ruby/win32-registry
|
|
65
|
+
licenses: []
|
|
66
|
+
metadata:
|
|
67
|
+
homepage_uri: https://github.com/ruby/win32-registry
|
|
68
|
+
source_code_uri: https://github.com/ruby/win32-registry
|
|
69
|
+
rdoc_options: []
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: 2.6.0
|
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
requirements: []
|
|
83
|
+
rubygems_version: 3.6.0.dev
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: Provides an interface to the Windows Registry in Ruby
|
|
86
|
+
test_files: []
|
metadata.gz.sig
ADDED
|
Binary file
|