Class: RAPI::Registry

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Win32::Registry::Constants
Defined in:
lib/rapi/registry.rb

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Registry) initialize(hkey, parent, keyname, disposition)



60
61
62
63
64
65
66
# File 'lib/rapi/registry.rb', line 60

def initialize(hkey, parent, keyname, disposition)
  @hkey = hkey
  @phkey = FFI::Pointer.new(@hkey)
  @parent = parent
  @keyname = keyname
  @disposition = disposition
end

Instance Attribute Details

- (Object) disposition

Returns the value of attribute disposition



11
12
13
# File 'lib/rapi/registry.rb', line 11

def disposition
  @disposition
end

- (Object) hkey

Returns the value of attribute hkey



8
9
10
# File 'lib/rapi/registry.rb', line 8

def hkey
  @hkey
end

- (Object) keyname

Returns the value of attribute keyname



10
11
12
# File 'lib/rapi/registry.rb', line 10

def keyname
  @keyname
end

- (Object) parent

Returns the value of attribute parent



9
10
11
# File 'lib/rapi/registry.rb', line 9

def parent
  @parent
end

Class Method Details

+ (Object) create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rapi/registry.rb', line 36

def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
  hkey_ptr = FFI::MemoryPointer.new(:pointer)
  disp_ptr = FFI::MemoryPointer.new(:uint)

  result = Native::Rapi.CeRegCreateKeyEx(FFI::Pointer.new(hkey.hkey), subkey, 0, nil, 0, 0, nil, hkey_ptr, disp_ptr)
  unless result == 0
	raise RAPIException, "Could not create registry key"
  end

  newkey = hkey_ptr.get_pointer(0).address
  disp = disp_ptr.get_uint(0)

  obj = new(newkey, hkey, subkey, disp)
  if block_given?
	begin
	  yield obj
	ensure
	  obj.close
	end
  else
	obj
  end
end

+ (Object) open(hkey, subkey, desired = KEY_READ)



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rapi/registry.rb', line 13

def self.open(hkey, subkey, desired=KEY_READ)
  subkey = subkey.chomp("\\")
  result_ptr = FFI::MemoryPointer.new(:pointer)
  success = Native::Rapi.CeRegOpenKeyEx(FFI::Pointer.new(hkey.hkey), Util.utf16le(subkey), 0, 0, result_ptr) == 0

  unless success
	raise RAPIException, "Could not open registry key"
  end

  newkey = result_ptr.read_pointer.address
  obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY)

  if block_given?
	begin
	  yield obj
	ensure
	  obj.close
	end
  else
	obj
  end
end

Instance Method Details

- (Object) [](name, *rtype)



102
103
104
105
106
107
108
109
110
# File 'lib/rapi/registry.rb', line 102

def [](name, *rtype)
  type, data = read(name, *rtype)
  case type
  when REG_SZ, REG_DWORD, REG_QWORD, REG_MULTI_SZ, REG_EXPAND_SZ
	data
  else
	raise TypeError, "Type #{type} is not supported."
  end
end

- (Object) []=(name, rtype, value = nil)



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/rapi/registry.rb', line 136

def []=(name, rtype, value = nil)
  if value
	write name, rtype, value
  else
	case value = rtype
	when Integer
	  write name, REG_DWORD, value
	when String
	  write name, REG_SZ, value
	when Array
	  write name, REG_MULTI_SZ, value
	else
	  raise TypeError, "Unexpected type #{value.class}"
	end
  end
  value
end

- (Object) close



76
77
78
# File 'lib/rapi/registry.rb', line 76

def close
  Native::Rapi.CeRegCloseKey(@phkey)
end

- (Object) create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)



68
69
70
# File 'lib/rapi/registry.rb', line 68

def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
  self.class.create(self, subkey, desired, opt, &blk)
end

- (Object) delete_key(name)



98
99
100
# File 'lib/rapi/registry.rb', line 98

def delete_key(name)
  Native::Rapi.CeRegDeleteKey(@phkey, Util.utf16le(name))
end

- (Object) delete_value(name) Also known as: delete



93
94
95
# File 'lib/rapi/registry.rb', line 93

def delete_value(name)
  Native::Rapi.CeRegDeleteValue(@phkey, Util.utf16le(name))
end

- (Object) each_key(&block)



232
233
234
# File 'lib/rapi/registry.rb', line 232

def each_key(&block)
  self.keys.each(&block)
end

- (Object) each_value Also known as: each



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/rapi/registry.rb', line 175

def each_value
  name_ptr = FFI::MemoryPointer.new(:uint16, 256)
  name_size_ptr = FFI::MemoryPointer.new(:uint)
  name_size_ptr.put_uint(0, 256)

  type_ptr = FFI::MemoryPointer.new(:uint)

  data_ptr = FFI::MemoryPointer.new(:uint16, 0x1000)
  data_size_ptr = FFI::MemoryPointer.new(:uint)

  index = 0
  while true
	result = Native::Rapi.CeRegEnumValue(@phkey, index, name_ptr, name_size_ptr, nil, type_ptr, data_ptr, data_size_ptr)

    if result == Native::ERROR_NO_MORE_ITEMS
	  break
	elsif result != 0
	  raise RAPIException, "Could not enumerate keys"
	end

	index += 1

	name_size = name_size_ptr.get_uint(0)
	name = Util.utf8(name_ptr.get_bytes(0, name_size * 2))
	type = type_ptr.get_uint(0)
	data_size = data_size_ptr.get_uint(0)
	data = data_ptr.get_bytes(0, data_size)

	case type
	when REG_SZ, REG_EXPAND_SZ
	  data = Util.utf8(data)
	when REG_MULTI_SZ
	  data.split(/\00/).map {|str| Util.utf8(str)}
	when REG_BINARY
	  data = data
	when REG_DWORD
	  data = Win32::Registry::API.unpackdw(data)
	when REG_DWORD_BIG_ENDIAN
	  data.unpack('N')[0]
	when REG_QWORD
	  data = Win32::Registry::API.unpackqw(data)
	else
	  raise TypeError, "Type #{type} is not supported."
	end

	name_size_ptr.put_uint(0, 256)
	data_size_ptr.put_uint(0, 0x1000)
	data_ptr.clear
	name_ptr.clear

	yield name, type, data
  end

  index
end

- (Object) inspect



80
81
82
# File 'lib/rapi/registry.rb', line 80

def inspect
  "#<RAPI::Registry key=#{name.inspect}>"
end

- (Object) keys



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rapi/registry.rb', line 236

def keys
  name_ptr = FFI::MemoryPointer.new(:uint16, 256)
  name_size_ptr = FFI::MemoryPointer.new(:uint)
  name_size_ptr.put_uint(0, 256)

  index = 0
  keys = []
  while true
	result = Native::Rapi.CeRegEnumKeyEx(@phkey, index, name_ptr, name_size_ptr, nil, nil, nil, nil)

    if result == Native::ERROR_NO_MORE_ITEMS
	  break
	elsif result != 0
	  raise RAPIException, "Could not enumerate keys"
	end

	index += 1

	name_size = name_size_ptr.get_uint(0)
	name = Util.utf8(name_ptr.get_bytes(0, name_size * 2))
	name_size_ptr.put_uint(0, 256)

	keys << name
  end

  keys
end

- (Object) name



84
85
86
87
88
89
90
91
# File 'lib/rapi/registry.rb', line 84

def name
  parent = self
  name = @keyname
  while parent = parent.parent
	name = parent.keyname + "\\" + name
  end
  name
end

- (Object) open(subkey, desired = KEY_READ, &block)



72
73
74
# File 'lib/rapi/registry.rb', line 72

def open(subkey, desired=KEY_READ, &block)
  self.class.open(self, subkey, desired, &block)
end

- (Object) read(name, *rtype)



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/rapi/registry.rb', line 112

def read(name, *rtype)
  # For whatever reason, I can't seem to get CeRegQueryValueEx to work...
  # It always returns HRESULT 87 - "The parameter is incorrect".
  type = nil
  data = nil

  each_value do |n, t, d|
	if name.downcase == n.downcase
	  type, data = t, d
	  break
	end
  end

  unless type && data
	raise RAPIException, "Could not find value #{name}"
  end

  unless rtype.empty? or rtype.include?(type)
	raise TypeError, "Type mismatch (expect #{rtype.inspect} but #{type} present)"
  end

  [ type, data ]
end

- (Object) write(name, type, data)



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/rapi/registry.rb', line 154

def write(name, type, data)
  case type
  when REG_SZ, REG_EXPAND_SZ
	data = Util.utf16le(data.to_s)
  when REG_MULTI_SZ
	data = data.to_a.map {|d| Util.utf16le(d.to_s)}.join + Util::UTF16LE_NULL
  when REG_BINARY
	data = data.to_s
  when REG_DWORD
	data = Win32::Registry::API.packdw(data.to_i)
  when REG_DWORD_BIG_ENDIAN
	data = [data.to_i].pack('N')
  when REG_QWORD
	data = Win32::Registry::API.packqw(data.to_i)
  else
	raise TypeError, "Unsupported type #{type}"
  end

  Native::Rapi.CeRegSetValueEx(@phkey, Util.utf16le(name), 0, type, data, data.bytesize)
end