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

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

reworked regfi API to accomodate more convenient subkey/value searches without an iterator.

continued implementation on pyregfi

File size: 9.2 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
123class _StructureWrapper():
124    "Handles memory management and proxies attribute access to base structures"
125    hive = None
126    base = None
127
128    def __init__(self, hive, base):
129        self.hive = hive
130        # XXX: check for NULL here, throw an exception if so.
131        self.base = base
132
133    def __del__(self):
134        regfi.regfi_free_record(self.base)
135
136    def __getattr__(self, name):
137        return getattr(self.base.contents, name)
138
139    def __eq__(self, other):
140        return (type(self) == type(other)) and (self.offset == other.offset)
141
142    def __ne__(self, other):
143        return (not self.__eq__(other))
144
145
146class Value(_StructureWrapper):
147    pass
148
149
150class Data(_StructureWrapper):
151    pass
152
153
154class Security(_StructureWrapper):
155    pass
156
157
158class _ValueList():
159    hive = None
160    key = None
161    length = None
162    current = None
163
164    def __init__(self, key):
165        self.hive = key.hive
166        # XXX: check for NULL here, throw an exception if so.
167        self.key = key
168        self.length = regfi.regfi_fetch_num_values(key.base)
169   
170    def __len__(self):
171        return self.length
172
173    def __getitem__(self, name):
174        index = c_uint32()
175        # XXX: need to do any funky unicode conversions on name?
176        if regfi.regfi_find_value(self.hive.file, self.key.base,
177                                  create_string_buffer(name), byref(index)):
178            return Value(hive,
179                         regfi.regfi_get_value(hive.file, key.base, index))
180        raise KeyError('')
181
182    def __iter__(self):
183        self.current = 0
184        return self
185   
186    def __next__(self):
187        if self.current >= self.length:
188            raise StopIteration('')
189
190        vk = regfi.regfi_get_value(self.hive.file, self.key.base,
191                                   c_uint32(self.current))
192        self.current += 1
193        return vk.contents
194   
195
196class Key(_StructureWrapper):
197    values = None
198
199    def __init__(self, hive, base):
200        super(Key, self).__init__(hive, base)
201        self.values = _ValueList(self)
202
203    def fetch_security(self):
204        return Security(self.hive,
205                        regfi.regfi_fetch_sk(self.hive.file, self.base))
206
207
208class Hive():   
209    file = None
210    raw_file = None
211   
212    def __init__(self, fh):
213        # The fileno method may not exist, or it may thrown an exception
214        # when called if the file isn't backed with a descriptor.
215        try:
216            if hasattr(fh, 'fileno'):
217                self.file = regfi.regfi_alloc(fh.fileno())
218                return
219        except:
220            pass
221       
222        self.raw_file = structures.REGFI_RAW_FILE()
223        self.raw_file.fh = fh
224        self.raw_file.seek = seek_cb_type(self.raw_file.cb_seek)
225        self.raw_file.read = read_cb_type(self.raw_file.cb_read)
226        self.file = regfi.regfi_alloc_cb(self.raw_file)
227
228    def __getattr__(self, name):
229        return getattr(self.file.contents, name)
230   
231    def __del__(self):   
232        regfi.regfi_free(self.file)
233        if self.raw_file != None:
234            regfi.regfi_free(self.file)
235           
236
237    def __iter__(self):
238        return HiveIterator(self)
239
240    def subtree(self, path):
241        hi = HiveIterator(self)
242        hi.descend(path)
243        return hi
244
245
246class HiveIterator():
247    hive = None
248    iter = None
249    iteration_root = None
250
251    def __init__(self, hive):
252        # REGFI_ENCODING_UTF8==1
253        self.iter = regfi.regfi_iterator_new(hive.file, 1)
254        if self.iter == None:
255            raise Exception("Could not create iterator.  Current log:\n"
256                            + GetLogMessages())
257        self.hive = hive
258       
259    def __getattr__(self, name):
260        return getattr(self.file.contents, name)
261
262    def __del__(self):   
263        regfi.regfi_iterator_free(self.iter)       
264
265    def __iter__(self):
266        self.iteration_root = None
267        return self
268
269    def __next__(self):
270        if self.iteration_root == None:
271            self.iteration_root = self.current_key()           
272        elif not regfi.regfi_iterator_down(self.iter):
273            up_ret = regfi.regfi_iterator_up(self.iter)
274            while (up_ret and
275                   not regfi.regfi_iterator_next_subkey(self.iter)):
276                if self.iteration_root == self.current_key():
277                    self.iteration_root = None
278                    raise StopIteration('')
279                up_ret = regfi.regfi_iterator_up(self.iter)
280
281            if not up_ret:
282                raise StopIteration('')
283           
284            if not regfi.regfi_iterator_down(self.iter):
285                raise Exception('Error traversing iterator downward.'+
286                                ' Current log:\n'+ GetLogMessages())
287
288        regfi.regfi_iterator_first_subkey(self.iter)
289        return self.current_key()
290
291    def down(self):
292        pass
293
294    def up(self):
295        pass
296
297    def descend(self, path):
298        #set up generator
299        cpath = (bytes(p,'ascii') for p in path) 
300
301        # evaluate generator and create char* array
302        apath = (c_char_p*len(path))(*cpath)
303
304        if not regfi.regfi_iterator_walk_path(self.iter,apath):
305            raise Exception('Could not locate path.\n'+GetLogMessages())
306
307    def current_key(self):
308        return Key(self.hive, regfi.regfi_iterator_cur_key(self.iter))
Note: See TracBrowser for help on using the repository browser.