source: trunk/python/pyregfi/__init__.py @ 208

Last change on this file since 208 was 208, checked in by tim, 14 years ago

more additions to pyregfi: functional subkey and value lists

File size: 11.1 KB
Line 
1#!/usr/bin/env python
2
3import sys
4from pyregfi.structures import *
5
6import ctypes
7import ctypes.util
8from ctypes import c_char,c_char_p,c_int,c_uint16,c_uint32,c_bool,POINTER
9
10regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
11
12
13regfi.regfi_alloc.argtypes = [c_int]
14regfi.regfi_alloc.restype = POINTER(REGFI_FILE)
15
16regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE)]
17regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
18
19regfi.regfi_free.argtypes = [POINTER(REGFI_FILE)]
20regfi.regfi_free.restype = None
21
22regfi.regfi_log_get_str.argtypes = []
23regfi.regfi_log_get_str.restype = c_char_p
24
25regfi.regfi_log_set_mask.argtypes = [c_uint16]
26regfi.regfi_log_set_mask.restype = c_bool
27
28regfi.regfi_free_record.argtypes = [c_void_p]
29regfi.regfi_free_record.restype = None
30
31regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
32regfi.regfi_fetch_num_subkeys.restype = c_uint32
33
34regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
35regfi.regfi_fetch_num_values.restype = c_uint32
36
37regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
38regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
39
40regfi.regfi_fetch_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
41regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
42
43regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
44regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
45
46regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
47                                    c_char_p, POINTER(c_uint32)]
48regfi.regfi_find_subkey.restype = c_bool
49
50regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
51                                    c_char_p, POINTER(c_uint32)]
52regfi.regfi_find_value.restype = c_bool
53
54regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
55                                   c_uint32]
56regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
57
58regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
59                                   c_uint32]
60regfi.regfi_get_value.restype = POINTER(REGFI_VK)
61
62regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
63regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
64
65regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
66regfi.regfi_iterator_free.restype = None
67
68regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
69regfi.regfi_iterator_down.restype = c_bool
70
71regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
72regfi.regfi_iterator_up.restype = c_bool
73
74regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
75regfi.regfi_iterator_to_root.restype = c_bool
76
77regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR)]
78regfi.regfi_iterator_walk_path.restype = c_bool
79
80regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
81regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
82
83regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
84regfi.regfi_iterator_first_subkey.restype = c_bool
85
86regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
87regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
88
89regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
90regfi.regfi_iterator_next_subkey.restype = c_bool
91
92regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
93regfi.regfi_iterator_find_subkey.restype = c_bool
94
95regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
96regfi.regfi_iterator_first_value.restype = c_bool
97
98regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
99regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
100
101regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
102regfi.regfi_iterator_next_value.restype = c_bool
103
104regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
105regfi.regfi_iterator_find_value.restype = c_bool
106
107
108
109regfi.regfi_get_value
110
111regfi.regfi_init.argtypes = []
112regfi.regfi_init.restype = None
113regfi.regfi_init()
114
115
116def GetLogMessages():
117    msgs = regfi.regfi_log_get_str()
118    if msgs == None:
119        return ''
120    return msgs.decode('ascii')
121
122
123def _buffer2bytearray(char_pointer, length):
124    if length == 0 or char_pointer == None:
125        return None
126   
127    ret_val = bytearray(length)
128    for i in range(0,length):
129        ret_val[i] = char_pointer[i][0]
130
131    return ret_val
132
133
134
135
136class _StructureWrapper():
137    "Handles memory management and proxies attribute access to base structures"
138    hive = None
139    base = None
140
141    def __init__(self, hive, base):
142        self.hive = hive
143        # XXX: check for NULL here, throw an exception if so.
144        self.base = base
145
146    def __del__(self):
147        regfi.regfi_free_record(self.base)
148
149    def __getattr__(self, name):
150        return getattr(self.base.contents, name)
151
152    def __eq__(self, other):
153        return (type(self) == type(other)) and (self.offset == other.offset)
154
155    def __ne__(self, other):
156        return (not self.__eq__(other))
157
158
159class Key(_StructureWrapper):
160    pass
161
162class Value(_StructureWrapper):
163    pass
164
165class Data(_StructureWrapper):
166    pass
167
168class Security(_StructureWrapper):
169    pass
170
171
172class _GenericList():
173    hive = None
174    key = None
175    length = None
176    current = None
177
178    # implementation-specific functions
179    fetch_num = None
180    find_element = None
181    get_element = None
182    constructor = None
183
184    def __init__(self, key):
185        self.hive = key.hive
186        # XXX: check for NULL here, throw an exception if so.
187        self.key = key
188        self.length = self.fetch_num(key.base)
189   
190    def __len__(self):
191        return self.length
192
193    def __getitem__(self, name):
194        index = c_uint32()
195        if isinstance(name, str):
196            name = name.encode('utf-8')
197
198        if self.find_element(self.hive.file, self.key.base,
199                             create_string_buffer(name), byref(index)):
200            return self.constructor(self.hive, self.get_element(self.hive.file,
201                                                                self.key.base,
202                                                                index))
203        raise KeyError('')
204
205
206    def __iter__(self):
207        self.current = 0
208        return self
209   
210    def __next__(self):
211        if self.current >= self.length:
212            raise StopIteration('')
213
214        elem = self.get_element(self.hive.file, self.key.base,
215                                c_uint32(self.current))
216        self.current += 1
217        return elem.contents
218   
219
220class _SubkeyList(_GenericList):
221    fetch_num = regfi.regfi_fetch_num_subkeys
222    find_element = regfi.regfi_find_subkey
223    get_element = regfi.regfi_get_subkey
224
225
226class _ValueList(_GenericList):
227    fetch_num = regfi.regfi_fetch_num_values
228    find_element = regfi.regfi_find_value
229    get_element = regfi.regfi_get_value
230
231
232class Key(_StructureWrapper):
233    values = None
234    subkeys = None
235
236    def __init__(self, hive, base):
237        super(Key, self).__init__(hive, base)
238        self.values = _ValueList(self)
239        self.subkeys = _SubkeyList(self)
240
241    def __getattr__(self, name):
242        ret_val = super(Key, self).__getattr__(name)
243        if ret_val == None:
244            return None
245       
246        if name == "name":
247            ret_val = ret_val.decode('utf-8')
248        elif name == "name_raw":
249            length = super(Key, self).__getattr__('name_length')
250            ret_val = _buffer2bytearray(ret_val, length)
251       
252        return ret_val
253
254
255    def fetch_security(self):
256        return Security(self.hive,
257                        regfi.regfi_fetch_sk(self.hive.file, self.base))
258
259
260class Value(_StructureWrapper):
261    def __getattr__(self, name):
262        ret_val = super(Value, self).__getattr__(name)
263        if ret_val == None:
264            return None
265
266        if name == "name":
267            ret_val = ret_val.decode('utf-8')
268        elif name == "name_raw":
269            length = super(Value, self).__getattr__('name_length')
270            ret_val = _buffer2bytearray(ret_val, length)
271       
272        return ret_val
273
274
275# Avoids chicken/egg class definitions.
276# Also makes for convenient code reuse in these lists' parent classes.
277_SubkeyList.constructor = Key
278_ValueList.constructor = Value
279
280
281
282class Hive():   
283    file = None
284    raw_file = None
285   
286    def __init__(self, fh):
287        # The fileno method may not exist, or it may thrown an exception
288        # when called if the file isn't backed with a descriptor.
289        try:
290            if hasattr(fh, 'fileno'):
291                self.file = regfi.regfi_alloc(fh.fileno())
292                return
293        except:
294            pass
295       
296        self.raw_file = structures.REGFI_RAW_FILE()
297        self.raw_file.fh = fh
298        self.raw_file.seek = seek_cb_type(self.raw_file.cb_seek)
299        self.raw_file.read = read_cb_type(self.raw_file.cb_read)
300        self.file = regfi.regfi_alloc_cb(self.raw_file)
301
302    def __getattr__(self, name):
303        return getattr(self.file.contents, name)
304   
305    def __del__(self):   
306        regfi.regfi_free(self.file)
307        if self.raw_file != None:
308            regfi.regfi_free(self.file)
309           
310
311    def __iter__(self):
312        return HiveIterator(self)
313
314    def subtree(self, path):
315        hi = HiveIterator(self)
316        hi.descend(path)
317        return hi
318
319
320class HiveIterator():
321    hive = None
322    iter = None
323    iteration_root = None
324
325    def __init__(self, hive):
326        # REGFI_ENCODING_UTF8==1
327        self.iter = regfi.regfi_iterator_new(hive.file, 1)
328        if self.iter == None:
329            raise Exception("Could not create iterator.  Current log:\n"
330                            + GetLogMessages())
331        self.hive = hive
332       
333    def __getattr__(self, name):
334        return getattr(self.file.contents, name)
335
336    def __del__(self):   
337        regfi.regfi_iterator_free(self.iter)       
338
339    def __iter__(self):
340        self.iteration_root = None
341        return self
342
343    def __next__(self):
344        if self.iteration_root == None:
345            self.iteration_root = self.current_key()           
346        elif not regfi.regfi_iterator_down(self.iter):
347            up_ret = regfi.regfi_iterator_up(self.iter)
348            while (up_ret and
349                   not regfi.regfi_iterator_next_subkey(self.iter)):
350                if self.iteration_root == self.current_key():
351                    self.iteration_root = None
352                    raise StopIteration('')
353                up_ret = regfi.regfi_iterator_up(self.iter)
354
355            if not up_ret:
356                raise StopIteration('')
357           
358            if not regfi.regfi_iterator_down(self.iter):
359                raise Exception('Error traversing iterator downward.'+
360                                ' Current log:\n'+ GetLogMessages())
361
362        regfi.regfi_iterator_first_subkey(self.iter)
363        return self.current_key()
364
365    def down(self):
366        pass
367
368    def up(self):
369        pass
370
371    def descend(self, path):
372        #set up generator
373        cpath = (bytes(p,'ascii') for p in path) 
374
375        # evaluate generator and create char* array
376        apath = (c_char_p*len(path))(*cpath)
377
378        if not regfi.regfi_iterator_walk_path(self.iter,apath):
379            raise Exception('Could not locate path.\n'+GetLogMessages())
380
381    def current_key(self):
382        return Key(self.hive, regfi.regfi_iterator_cur_key(self.iter))
Note: See TracBrowser for help on using the repository browser.