vrvirtualdesktop 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/LICENSE +1 -0
- data/README +37 -0
- data/TODO +3 -0
- data/bin/vrdesk.rbw +55 -0
- data/lib/VRVirtualDesktopForm.rb +267 -0
- data/lib/Win32/APIMapper.rb +62 -0
- data/lib/Win32/Base-consts.rb +891 -0
- data/lib/Win32/Base.rb +275 -0
- data/lib/Win32/Encoding.rb +68 -0
- data/lib/Win32/GetSystemMetrics.rb +107 -0
- data/lib/Win32/NetResources.rb +160 -0
- data/lib/Win32/Process.rb +468 -0
- data/lib/Win32/Registry.rb +515 -0
- data/lib/Win32/User32.rb +142 -0
- data/lib/Win32/VirtualDesktop.rb +418 -0
- data/lib/Win32/WindowManager.rb +177 -0
- data/lib/resources/desktops.ico +0 -0
- data/lib/resources/five_down.ico +0 -0
- data/lib/resources/five_up.ico +0 -0
- data/lib/resources/four_down.ico +0 -0
- data/lib/resources/four_up.ico +0 -0
- data/lib/resources/obdb.ico +0 -0
- data/lib/resources/one_down.ico +0 -0
- data/lib/resources/one_up.ico +0 -0
- data/lib/resources/six_down.ico +0 -0
- data/lib/resources/six_up.ico +0 -0
- data/lib/resources/three_down.ico +0 -0
- data/lib/resources/three_up.ico +0 -0
- data/lib/resources/two_down.ico +0 -0
- data/lib/resources/two_up.ico +0 -0
- metadata +97 -0
@@ -0,0 +1,515 @@
|
|
1
|
+
##################################################################################################
|
2
|
+
#
|
3
|
+
# $Author: Steve $
|
4
|
+
# $Date: 2005/12/16 18:35:42 $
|
5
|
+
# $Version: 0.99 $
|
6
|
+
# $Change: $
|
7
|
+
#
|
8
|
+
##################################################################################################
|
9
|
+
|
10
|
+
module Win32
|
11
|
+
|
12
|
+
require 'Win32/Base'
|
13
|
+
require 'Win32/APIMapper'
|
14
|
+
require 'Win32/Encoding'
|
15
|
+
|
16
|
+
#---------------------------------------------------------------------------------------------
|
17
|
+
#---------------------------------------------------------------------------------------------
|
18
|
+
# Win32 Exceptions
|
19
|
+
class RegistryError < Win32::Error
|
20
|
+
end
|
21
|
+
|
22
|
+
#---------------------------------------------------------------------------------------------
|
23
|
+
#---------------------------------------------------------------------------------------------
|
24
|
+
# This class provides some low-level functionality for manipulating the Win32 registry
|
25
|
+
class RegKey
|
26
|
+
#-----------------------------------------------------------------------------------------
|
27
|
+
# constsFor: "Predefined Registry Keys"
|
28
|
+
# (from WinReg.h)
|
29
|
+
HKEY_CLASSES_ROOT = 0x80000000
|
30
|
+
HKEY_CURRENT_CONFIG = 0x80000005
|
31
|
+
HKEY_CURRENT_USER = 0x80000001
|
32
|
+
HKEY_DYN_DATA = 0x80000006 # Works only on Win95/98/Me
|
33
|
+
HKEY_LOCAL_MACHINE = 0x80000002
|
34
|
+
HKEY_PERFORMANCE_DATA = 0x80000004
|
35
|
+
HKEY_USERS = 0x80000003
|
36
|
+
|
37
|
+
#-----------------------------------------------------------------------------------------
|
38
|
+
# constsFor: "Security and Access Rights (Open, Create)"
|
39
|
+
# (from WinReg.h)
|
40
|
+
KEY_QUERY_VALUE = 1
|
41
|
+
KEY_SET_VALUE = 2
|
42
|
+
KEY_CREATE_SUB_KEY = 4
|
43
|
+
KEY_ENUMERATE_SUB_KEYS = 8
|
44
|
+
KEY_NOTIFY = 16
|
45
|
+
KEY_CREATE_LINK = 32
|
46
|
+
KEY_WRITE = 131078
|
47
|
+
KEY_EXECUTE = 131097
|
48
|
+
KEY_READ = 131097
|
49
|
+
KEY_ALL_ACCESS = 983103
|
50
|
+
|
51
|
+
#-----------------------------------------------------------------------------------------
|
52
|
+
# constsFor: "Registry Value Types"
|
53
|
+
# (from WinReg.h)
|
54
|
+
REG_NONE = 0
|
55
|
+
REG_SZ = 1
|
56
|
+
REG_EXPAND_SZ = 2
|
57
|
+
REG_BINARY = 3
|
58
|
+
REG_DWORD = 4
|
59
|
+
REG_DWORD_LITTLE_ENDIAN = 4
|
60
|
+
REG_DWORD_BIG_ENDIAN = 5
|
61
|
+
REG_LINK = 6
|
62
|
+
REG_MULTI_SZ = 7
|
63
|
+
|
64
|
+
#-----------------------------------------------------------------------------------------
|
65
|
+
# constsFor: "Registry Key Creation Options"
|
66
|
+
# (from WinReg.h)
|
67
|
+
REG_OPTION_RESERVED = 0
|
68
|
+
REG_OPTION_NON_VOLATILE = 0
|
69
|
+
REG_OPTION_VOLATILE = 1
|
70
|
+
REG_OPTION_CREATE_LINK = 2
|
71
|
+
REG_OPTION_BACKUP_RESTORE = 4
|
72
|
+
REG_OPTION_OPEN_LINK = 8
|
73
|
+
|
74
|
+
#-----------------------------------------------------------------------------------------
|
75
|
+
# constsFor: "Registry Key Disposition on Create"
|
76
|
+
# (from WinReg.h)
|
77
|
+
REG_CREATED_NEW_KEY = 1
|
78
|
+
REG_OPENED_EXISTING_KEY = 2
|
79
|
+
|
80
|
+
#-----------------------------------------------------------------------------------------
|
81
|
+
# constsFor: "Restore Options"
|
82
|
+
# (from WinReg.h)
|
83
|
+
REG_WHOLE_HIVE_VOLATILE = 1
|
84
|
+
REG_REFRESH_HIVE = 2
|
85
|
+
REG_NO_LAZY_FLUSH = 4
|
86
|
+
REG_FORCE_RESTORE = 1234 #TODO
|
87
|
+
|
88
|
+
#-----------------------------------------------------------------------------------------
|
89
|
+
# constsFor: "miscellaneous"
|
90
|
+
# (from WinReg.h)
|
91
|
+
REG_FULL_RESOURCE_DESCRIPTOR = 9
|
92
|
+
REG_LEGAL_CHANGE_FILTER = 15
|
93
|
+
REG_LEGAL_OPTION = 15
|
94
|
+
REG_NOTIFY_CHANGE_ATTRIBUTES = 2
|
95
|
+
REG_NOTIFY_CHANGE_LAST_SET = 4
|
96
|
+
REG_NOTIFY_CHANGE_NAME = 1
|
97
|
+
REG_NOTIFY_CHANGE_SECURITY = 8
|
98
|
+
|
99
|
+
REG_RESOURCE_LIST = 8
|
100
|
+
REG_RESOURCE_REQUIREMENTS_LIST = 10
|
101
|
+
|
102
|
+
#-----------------------------------------------------------------------------------------
|
103
|
+
# constsFor: "String buffer size"
|
104
|
+
MAXCHARS = 256 * 2 # We exchange UCS2 characters with Windows
|
105
|
+
|
106
|
+
#-----------------------------------------------------------------------------------------
|
107
|
+
include APIMapper
|
108
|
+
|
109
|
+
APIMapper.Initialize(
|
110
|
+
'OpenKey' => { DLL => 'advapi32', NAME => 'RegOpenKeyExW',
|
111
|
+
IN => ['L', 'P', 'L', 'L', 'P'], OUT => 'L'},
|
112
|
+
'ConnectRegistry' => { DLL => 'advapi32', NAME => 'RegConnectRegistryW',
|
113
|
+
IN => ['P', 'L', 'P'], OUT => 'L'},
|
114
|
+
'CreateKey' => { DLL => 'advapi32', NAME => 'RegCreateKeyExW',
|
115
|
+
IN => ['L', 'P']*2 + ['L']*2 + ['P']*3, OUT => 'L'},
|
116
|
+
'CloseKey' => { DLL => 'advapi32', NAME => 'RegCloseKey',
|
117
|
+
IN => ['L'], OUT => 'L'},
|
118
|
+
'DeleteKey' => { DLL => 'advapi32', NAME => 'RegDeleteKey',
|
119
|
+
IN => ['L', 'P'], OUT => 'L'},
|
120
|
+
'DeleteValue' => { DLL => 'advapi32', NAME => 'RegDeleteValue',
|
121
|
+
IN => ['L', 'P'], OUT => 'L'},
|
122
|
+
'DisablePredefinedCache' => { DLL => 'advapi32', NAME => 'RegDisablePredefinedCache',
|
123
|
+
IN => [], OUT => 'L'},
|
124
|
+
'EnumKey' => { DLL => 'advapi32', NAME => 'RegEnumKeyExW',
|
125
|
+
IN => ['L', 'L'] + ['P']*6, OUT => 'L'},
|
126
|
+
'EnumValue' => { DLL => 'advapi32', NAME => 'RegEnumValueW',
|
127
|
+
IN => ['L', 'L'] + ['P']*6, OUT => 'L'},
|
128
|
+
'FlushKey' => { DLL => 'advapi32', NAME => 'RegFlushKey',
|
129
|
+
IN => ['L'], OUT => 'L'},
|
130
|
+
'LoadKey' => { DLL => 'advapi32', NAME => 'RegLoadKeyW',
|
131
|
+
IN => ['L', 'P', 'P'], OUT => 'L'},
|
132
|
+
'OverridePredefKey' => { DLL => 'advapi32', NAME => 'RegOverridePredefKey',
|
133
|
+
IN => ['L', 'L'], OUT => 'L'},
|
134
|
+
'QueryInfoKey' => { DLL => 'advapi32', NAME => 'RegQueryInfoKeyW',
|
135
|
+
IN => ['L'] + ['P']*11, OUT => 'L'},
|
136
|
+
'QueryValue' => { DLL => 'advapi32', NAME => 'RegQueryValueExW',
|
137
|
+
IN => ['L'] + ['P']*5, OUT => 'L'},
|
138
|
+
'QueryMultipleValues' => { DLL => 'advapi32', NAME => 'RegQueryMultipleValuesW',
|
139
|
+
IN => ['L'] + ['P', 'L', 'P', 'P'] , OUT => 'L'},
|
140
|
+
'ReplaceKey' => { DLL => 'advapi32', NAME => 'RegReplaceKeyW',
|
141
|
+
IN => ['L', 'L', 'P', 'P'], OUT => 'L'},
|
142
|
+
'RestoreKey' => { DLL => 'advapi32', NAME => 'RegRestoreKeyW',
|
143
|
+
IN => ['L', 'P', 'L'], OUT => 'L'},
|
144
|
+
'SaveKey' => { DLL => 'advapi32', NAME => 'RegSaveKeyW',
|
145
|
+
IN => ['L', 'P', 'P'], OUT => 'L'},
|
146
|
+
'SetValue' => { DLL => 'advapi32', NAME => 'RegSetValueExW',
|
147
|
+
IN => ['L', 'P', 'L', 'L', 'P', 'L'], OUT => 'L'},
|
148
|
+
'UnLoadKey' => { DLL => 'advapi32', NAME => 'RegUnLoadKey',
|
149
|
+
IN => ['L', 'P'], OUT => 'L'}
|
150
|
+
)
|
151
|
+
|
152
|
+
#-----------------------------------------------------------------------------------------
|
153
|
+
# class methodsFor: "initialization"
|
154
|
+
def initialize()
|
155
|
+
@key = nil
|
156
|
+
end
|
157
|
+
|
158
|
+
#-----------------------------------------------------------------------------------------
|
159
|
+
# class methodsFor: "opening/creating/connecting"
|
160
|
+
def RegKey.open(p_key, p_strSubKey, p_samDesired = KEY_QUERY_VALUE)
|
161
|
+
key = RegKey.new
|
162
|
+
key.open(p_key, p_strSubKey, p_samDesired)
|
163
|
+
return key
|
164
|
+
end
|
165
|
+
|
166
|
+
def RegKey.create(
|
167
|
+
p_key,
|
168
|
+
p_strSubKey,
|
169
|
+
p_strClass = '',
|
170
|
+
p_nOptions = REG_OPTION_NON_VOLATILE,
|
171
|
+
p_samDesired = 0,
|
172
|
+
p_pSecurityAttributes = nil)
|
173
|
+
key = RegKey.new
|
174
|
+
key.create( p_key, p_strSubKey, p_strClass,
|
175
|
+
p_nOptions, p_samDesired, p_pSecurityAttributes)
|
176
|
+
return key
|
177
|
+
end
|
178
|
+
|
179
|
+
def RegKey.connect(p_strHost, p_key)
|
180
|
+
key = RegKey.new
|
181
|
+
key.connect(p_strHost, p_key)
|
182
|
+
return key
|
183
|
+
end
|
184
|
+
|
185
|
+
#-----------------------------------------------------------------------------------------
|
186
|
+
# methodsFor: "opening/creating/connecting"
|
187
|
+
def open(p_key, p_strSubKey, p_samDesired = KEY_QUERY_VALUE)
|
188
|
+
self.close if !@key.nil?
|
189
|
+
pKey = "\0" * 4 # pointer to long
|
190
|
+
ret = WCall('OpenKey', p_key.to_i, p_strSubKey.to_ucs2(true), 0, p_samDesired, pKey)
|
191
|
+
raise RegistryError.new(ret), "Cannot Open Key: #{p_strSubKey}", caller if 0 != ret
|
192
|
+
@key = pKey.unpack("L")[0]
|
193
|
+
end
|
194
|
+
|
195
|
+
def create(
|
196
|
+
p_key,
|
197
|
+
p_strSubKey,
|
198
|
+
p_strClass = '',
|
199
|
+
p_nOptions = REG_OPTION_NON_VOLATILE,
|
200
|
+
p_samDesired = 0,
|
201
|
+
p_pSecurityAttributes = nil)
|
202
|
+
self.close if !@key.nil?
|
203
|
+
pKey = "\0" * 4 # pointer to long
|
204
|
+
pDisposition = "\0" * 4 # pointer to long
|
205
|
+
ret = WCall('CreateKey',
|
206
|
+
p_key.to_i, p_strSubKey.to_ucs2(true), 0, p_strClass.to_ucs2(true),
|
207
|
+
p_nOptions, p_samDesired, 0, #p_SecurityAttributes.pack, let's ignore this...
|
208
|
+
pKey, pDisposition)
|
209
|
+
if 0 == ret or (ERROR_ACCESS_DENIED == ret and
|
210
|
+
REG_OPENED_EXISTING_KEY == pDisposition.unpack('L')[0])
|
211
|
+
@key = pKey.unpack("L")[0]
|
212
|
+
else
|
213
|
+
raise RegistryError.new(ret), "Cannot create: #{p_strSubKey}", caller
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def connect(p_strHost, p_key)
|
218
|
+
self.close if !@key.nil?
|
219
|
+
pKey = "\0" * 4 # pointer to long
|
220
|
+
ret = WCall('ConnectRegistry', p_strHost.to_ucs2(true), p_key.to_i, pKey)
|
221
|
+
raise RegistryError.new(ret), "Cannot connect to #{p_strHost}", caller if 0 != ret
|
222
|
+
@key = pKey.unpack("L")[0]
|
223
|
+
end
|
224
|
+
|
225
|
+
#-----------------------------------------------------------------------------------------
|
226
|
+
# methodsFor: "replacing"
|
227
|
+
def replace(p_subKey, p_strNewFilename, p_strOldFilename)
|
228
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
229
|
+
ret = WCall('ReplaceKey', @key, p_subKey,
|
230
|
+
p_strNewFilename.to_ucs2(true), p_strOldFilename.to_ucs2(true))
|
231
|
+
raise RegistryError.new(ret), "Cannot replace #{p_subKey}", caller if 0 != ret
|
232
|
+
end
|
233
|
+
|
234
|
+
#-----------------------------------------------------------------------------------------
|
235
|
+
# methodsFor: "closing"
|
236
|
+
def close(p_bFlush = false)
|
237
|
+
return 0 if @key.nil?
|
238
|
+
flush() if p_bFlush
|
239
|
+
ret = WCall('CloseKey', @key)
|
240
|
+
@key = nil
|
241
|
+
raise RegistryError.new(ret), "Cannot close key", caller if 0 != ret
|
242
|
+
end
|
243
|
+
|
244
|
+
#-----------------------------------------------------------------------------------------
|
245
|
+
# methodsFor: "flushing"
|
246
|
+
def flush
|
247
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
248
|
+
ret = WCall('FlushKey', @key)
|
249
|
+
raise RegistryError.new(ret), "Error while flushing", caller if 0 != ret
|
250
|
+
end
|
251
|
+
|
252
|
+
#-----------------------------------------------------------------------------------------
|
253
|
+
# class methodsFor: "deleting"
|
254
|
+
def RegKey.Delete(p_key, p_subKey)
|
255
|
+
ret = APIMapper.WCall('DeleteKey', p_key.to_i, p_subKey)
|
256
|
+
raise RegistryError.new(ret), "Error while deleting #{p_subkey}", caller if 0 != ret
|
257
|
+
end
|
258
|
+
|
259
|
+
#-----------------------------------------------------------------------------------------
|
260
|
+
# class methodsFor: "miscellaneous"
|
261
|
+
def RegKey.DisablePredefinedCache
|
262
|
+
ret = APIMapper.WCall('DisablePredefinedCache')
|
263
|
+
raise RegistryError.new(ret), "Error while disabling predefined cache", caller if 0 != ret
|
264
|
+
end
|
265
|
+
|
266
|
+
#-----------------------------------------------------------------------------------------
|
267
|
+
# methodsFor: "miscellaneous"
|
268
|
+
def overridePredefKey(p_key)
|
269
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
270
|
+
ret = WCall('OverridePredefKey', p_key, @key)
|
271
|
+
raise RegistryError.new(ret), "Error while overriding predefined key", caller if 0 != ret
|
272
|
+
end
|
273
|
+
|
274
|
+
def deleteValue(p_strName)
|
275
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
276
|
+
ret = WCall('DeleteValue', @key, p_strName.to_ucs2(true))
|
277
|
+
raise RegistryError.new(ret), "Error while deleting value #{p_strName}", caller if 0 != ret
|
278
|
+
end
|
279
|
+
|
280
|
+
#-----------------------------------------------------------------------------------------
|
281
|
+
# methodsFor: "loading/unloading"
|
282
|
+
def load(p_subKey, p_strFilename)
|
283
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
284
|
+
ret = WCall('LoadKey', @key, p_subKey, p_strFilename.to_ucs2(true))
|
285
|
+
raise RegistryError.new(ret), "Error while loading #{p_strFilename} into #{p_subkey}", caller if 0 != ret
|
286
|
+
end
|
287
|
+
|
288
|
+
def unLoad(p_subKey)
|
289
|
+
return -1 if @key.nil?
|
290
|
+
ret = WCall('UnLoadKey', @key, p_subKey)
|
291
|
+
raise RegistryError.new(ret), "Error while unloading #{p_subkey}", caller if 0 != ret
|
292
|
+
end
|
293
|
+
|
294
|
+
def save(p_strFilename, p_security = 0)
|
295
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
296
|
+
ret = WCall('SaveKey', @key, p_strFilename.to_ucs2(true), pSecurity)
|
297
|
+
raise RegistryError.new(ret), "Error while saving to #{p_strFilename}", caller if 0 != ret
|
298
|
+
end
|
299
|
+
|
300
|
+
def restore(p_strFilename, p_options)
|
301
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
302
|
+
ret = WCall('RestoreKey', @key, p_strFilename.to_ucs2(true), p_options)
|
303
|
+
raise RegistryError.new(ret), "Error while restoring from #{p_strFilename}", caller if 0 != ret
|
304
|
+
end
|
305
|
+
|
306
|
+
#-----------------------------------------------------------------------------------------
|
307
|
+
# methodsFor: "enumerating"
|
308
|
+
def eachKey
|
309
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
310
|
+
return 0 if !block_given?
|
311
|
+
n = 0
|
312
|
+
while true
|
313
|
+
strKey = "\0" * MAXCHARS # UCS2 String Buffer
|
314
|
+
pszKey = [MAXCHARS].pack('L') # pointer to long
|
315
|
+
strClass = "\0" * MAXCHARS # UCS2 String Buffer
|
316
|
+
pszClass = [MAXCHARS].pack("L") # pointer to long
|
317
|
+
pftLastWrite = "\0" * 4 # pointer to long
|
318
|
+
ret = WCall('EnumKey', @key, n, strKey, pszKey, 0, strClass, pszClass, pftLastWrite)
|
319
|
+
case ret
|
320
|
+
when 0
|
321
|
+
szKey = pszKey.unpack('L')[0] * 2 # UCS2 characters
|
322
|
+
szClass = pszClass.unpack('L')[0] * 2 # UCS2 characters
|
323
|
+
yield( strKey[0, szKey].to_utf8,
|
324
|
+
strClass[0, szClass].to_utf8,
|
325
|
+
pftLastWrite.unpack('L')[0])
|
326
|
+
n += 1
|
327
|
+
when ERROR_NO_MORE_ITEMS then break
|
328
|
+
else
|
329
|
+
raise RegistryError.new(ret), "Cannot access key ##{n} in enumeration", caller
|
330
|
+
end
|
331
|
+
end
|
332
|
+
return n
|
333
|
+
end
|
334
|
+
|
335
|
+
def eachValue
|
336
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
337
|
+
return 0 if !block_given?
|
338
|
+
n = 0
|
339
|
+
|
340
|
+
while true
|
341
|
+
strName = "\0" * MAXCHARS # UCS2 String Buffer
|
342
|
+
pszName = [MAXCHARS].pack('L') # pointer to long
|
343
|
+
pnType = " " * 4 # pointer to long
|
344
|
+
pszData = " " * 4 # pointer to long
|
345
|
+
|
346
|
+
# First call determines the size of data
|
347
|
+
ret = WCall('EnumValue', @key, n, strName, pszName, 0, pnType, 0, pszData)
|
348
|
+
case ret
|
349
|
+
when 0
|
350
|
+
szName = pszName.unpack('L')[0] * 2 # UCS2 characters
|
351
|
+
szData = pszData.unpack('L')[0]
|
352
|
+
nType = pnType.unpack('L')[0]
|
353
|
+
pData = nil
|
354
|
+
if szData > 0
|
355
|
+
pszName = [512].pack('L') # pointer to long
|
356
|
+
pData = "\0" * szData # pointer to data
|
357
|
+
# Second call retrieves the data
|
358
|
+
ret = WCall('EnumValue', @key, n, strName, pszName, 0, 0, pData, pszData)
|
359
|
+
raise RegistryError.new(ret), "Cannot access value ##{n} in enumeration", caller if 0 != ret
|
360
|
+
end
|
361
|
+
yield( strName[0, szName].to_utf8,
|
362
|
+
nType,
|
363
|
+
szData,
|
364
|
+
convertData(nType, pData, szData))
|
365
|
+
n += 1
|
366
|
+
when ERROR_NO_MORE_ITEMS then break
|
367
|
+
else
|
368
|
+
raise RegistryError.new(ret), "Cannot access value ##{n} in enumeration", caller
|
369
|
+
end
|
370
|
+
end
|
371
|
+
return n
|
372
|
+
end
|
373
|
+
|
374
|
+
#-----------------------------------------------------------------------------------------
|
375
|
+
# methodsFor: "querying"
|
376
|
+
def queryInfo
|
377
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
378
|
+
pszClass = "\0" * 4 # pointer to long
|
379
|
+
pnSubKeys = "\0" * 4 # pointer to long
|
380
|
+
pnMaxSubKeyLen = "\0" * 4 # pointer to long
|
381
|
+
pnMaxClassLen = "\0" * 4 # pointer to long
|
382
|
+
pnValues = "\0" * 4 # pointer to long
|
383
|
+
pnMaxValueNameLen = "\0" * 4 # pointer to long
|
384
|
+
pnMaxValueLen = "\0" * 4 # pointer to long
|
385
|
+
pnSecurityDescriptor = "\0" * 4 # pointer to long
|
386
|
+
pftLastWriteTime = "\0" * 4 # pointer to long
|
387
|
+
ret = WCall('QueryInfoKey',
|
388
|
+
@key,
|
389
|
+
0, pszClass,
|
390
|
+
0,
|
391
|
+
pnSubKeys, pnMaxSubKeyLen,
|
392
|
+
pnMaxClassLen,
|
393
|
+
pnValues, pnMaxValueNameLen, pnMaxValueLen,
|
394
|
+
pnSecurityDescriptor,
|
395
|
+
pftLastWriteTime)
|
396
|
+
raise RegistryError.new(ret), "Cannot query info", caller if 0 != ret
|
397
|
+
|
398
|
+
mRet = {}
|
399
|
+
szClass = pszClass.unpack('L')[0] * 2 # UCS2 characters
|
400
|
+
mRet['SubKeys'] = pnSubKeys.unpack('L')[0]
|
401
|
+
mRet['MaxSubKeyLen'] = pnMaxSubKeyLen.unpack('L')[0]
|
402
|
+
mRet['MaxClassLen'] = pnMaxClassLen.unpack('L')[0]
|
403
|
+
mRet['Values'] = pnValues.unpack('L')[0]
|
404
|
+
mRet['MaxValueNameLen'] = pnMaxValueNameLen.unpack('L')[0]
|
405
|
+
mRet['MaxValueLen'] = pnMaxValueLen.unpack('L')[0]
|
406
|
+
mRet['SecurityDescriptor'] = pnSecurityDescriptor.unpack('L')[0]
|
407
|
+
mRet['LastWriteTime'] = pftLastWriteTime.unpack('L')[0]
|
408
|
+
|
409
|
+
if szClass > 0
|
410
|
+
szClass += 2
|
411
|
+
strClass = " " * szClass
|
412
|
+
pszClass = [szClass].pack('L')
|
413
|
+
ret = WCall('QueryInfoKey', @key, strClass, pszClass, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
414
|
+
raise RegistryError.new(ret), "Cannot query info", caller if 0 != ret
|
415
|
+
mRet['Class'] = strClass.to_utf8
|
416
|
+
print "class: ", strClass.inspect, "->", strClass, "\n"
|
417
|
+
end
|
418
|
+
return mRet
|
419
|
+
end
|
420
|
+
|
421
|
+
def queryValue(p_strName)
|
422
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
423
|
+
strName = p_strName.to_ucs2(true)
|
424
|
+
pnType = " " * 4 # pointer to long
|
425
|
+
pszData = " " * 4 # pointer to long
|
426
|
+
ret = WCall('QueryValue', @key, strName, 0, pnType, 0, pszData)
|
427
|
+
raise RegistryError.new(ret), "Cannot query value #{p_strName}", caller if 0 != ret
|
428
|
+
|
429
|
+
mRet = {}
|
430
|
+
mRet['Type'] = nType = pnType.unpack('L')[0]
|
431
|
+
szData = pszData.unpack('L')[0]
|
432
|
+
if szData > 0
|
433
|
+
pData = "\0" * szData # pointer to long
|
434
|
+
ret = WCall('QueryValue', @key, strName, 0, 0, pData, pszData)
|
435
|
+
raise RegistryError.new(ret), "Cannot query value #{p_strName}", caller if 0 != ret
|
436
|
+
mRet['Value'] = convertData(nType, pData, szData)
|
437
|
+
end
|
438
|
+
return mRet
|
439
|
+
end
|
440
|
+
|
441
|
+
def queryMultipleValues(p_vstrNames)
|
442
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
443
|
+
pszData = "\0" * 4 # pointer to long
|
444
|
+
pvValues = Array.new()
|
445
|
+
p_vstrNames.each {|str| pvValues << str.to_ucs2(true) }
|
446
|
+
ret = WCall('QueryMultipleValues', @key, pvValues, pvValues.size, 0, pszData)
|
447
|
+
raise RegistryError.new(ret), "Cannot query values #{p_vstrNames}", caller if 0 != ret and ERROR_MORE_DATA != ret
|
448
|
+
|
449
|
+
mRet = {}
|
450
|
+
szData = pszData.unpack('L')[0]
|
451
|
+
if szData > 0
|
452
|
+
pData = "\0" * szData # pointer to long
|
453
|
+
ret = WCall('QueryMultipleValues', @key, pvValues, pvValues.size, pData, pszData)
|
454
|
+
raise RegistryError.new(ret), "Cannot query values #{p_vstrNames}", caller if 0 != ret
|
455
|
+
mRet['Value'] = convertData(nType, pData, szData)
|
456
|
+
end
|
457
|
+
return mRet
|
458
|
+
end
|
459
|
+
|
460
|
+
def setValue(p_strName, p_nType, p_pData)
|
461
|
+
raise Registry, "Key was not initialized properly", caller if @key.nil?
|
462
|
+
case p_nType
|
463
|
+
when REG_BINARY then pData = [p_pData].pack('C*')
|
464
|
+
when REG_DWORD then pData = [p_pData].pack('L')
|
465
|
+
when REG_DWORD_BIG_ENDIAN then pData = [p_pData].pack('L')
|
466
|
+
when REG_DWORD_LITTLE_ENDIAN then pData = [p_pData].pack('V')
|
467
|
+
when REG_EXPAND_SZ then pData = p_pData.to_ucs2(true)
|
468
|
+
when REG_LINK then pData = p_pData
|
469
|
+
when REG_NONE then pData = p_pData
|
470
|
+
when REG_SZ then pData = p_pData.to_ucs2(true)
|
471
|
+
when REG_MULTI_SZ
|
472
|
+
pData = []
|
473
|
+
p_pData.each {|str| pData << str.to_ucs2(true) }
|
474
|
+
pData << "\000\000"
|
475
|
+
else return -2
|
476
|
+
end
|
477
|
+
strName = p_strName.to_ucs2(true)
|
478
|
+
ret = WCall('SetValue', @key, strName, 0, p_nType, pData, pData.size)
|
479
|
+
raise RegistryError.new(ret), "Cannot set value #{p_strName}", caller if 0 != ret
|
480
|
+
end
|
481
|
+
|
482
|
+
#-----------------------------------------------------------------------------------------
|
483
|
+
# methodsFor: "accessing"
|
484
|
+
def to_i
|
485
|
+
return @key
|
486
|
+
end
|
487
|
+
|
488
|
+
#-----------------------------------------------------------------------------------------
|
489
|
+
# methodsFor: "printing"
|
490
|
+
def to_s
|
491
|
+
return super + " Key: #{@key}"
|
492
|
+
end
|
493
|
+
|
494
|
+
#-----------------------------------------------------------------------------------------
|
495
|
+
private
|
496
|
+
|
497
|
+
#-----------------------------------------------------------------------------------------
|
498
|
+
# methodsFor: "data conversion"
|
499
|
+
def convertData(p_nType, p_pData, p_szData)
|
500
|
+
return nil if p_pData.nil?
|
501
|
+
case p_nType
|
502
|
+
when REG_BINARY then return p_pData.unpack('C*')
|
503
|
+
when REG_DWORD then return p_pData.unpack('L')[0]
|
504
|
+
when REG_DWORD_BIG_ENDIAN then return p_pData.unpack('L')[0]
|
505
|
+
when REG_DWORD_LITTLE_ENDIAN then return p_pData.unpack('V')[0]
|
506
|
+
when REG_EXPAND_SZ then return p_pData[0, p_szData - 2].to_utf8
|
507
|
+
when REG_LINK then return p_pData
|
508
|
+
when REG_NONE then return p_pData
|
509
|
+
when REG_SZ then return p_pData[0, p_szData - 2].to_utf8
|
510
|
+
when REG_MULTI_SZ then return p_pData.to_utf8.unpack('Z*')
|
511
|
+
else return nil
|
512
|
+
end
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|