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 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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ task default: :test
@@ -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
@@ -0,0 +1,6 @@
1
+ module Win32
2
+ module Registry
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ 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��W Ax<�����+����h��`�hJ�.,����$*�ad������]��ds�&�S��aۤ2/4�s��U�m��������X�sc���|>����%�m�� A�gcl�m�W$)f� �+���z�y��T�o��a�򻁽�>%o A�pBښ��:!�n|�����gg������3\�^d��.d Jx�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