source: trunk/python/pyregfi/structures.py @ 220

Last change on this file since 220 was 220, checked in by tim, 13 years ago

reorganized code
added remaining methods to iterator
added test case for new methods

File size: 11.5 KB
RevLine 
[204]1#!/usr/bin/env python
2
3import sys
4import os
5import traceback
6import ctypes
7import ctypes.util
[205]8from ctypes import *
[204]9
[205]10# XXX: can we always be sure enums are this size?
11REGFI_ENCODING = c_uint32
[213]12REGFI_ENCODING_UTF8 = 1
13
[205]14REGFI_DATA_TYPE = c_uint32
[215]15REGFI_REGF_SIZE = 0x1000 
[204]16
[209]17# Registry value data types
18REG_NONE                       =  0
19REG_SZ                         =  1
20REG_EXPAND_SZ                  =  2
21REG_BINARY                     =  3
22REG_DWORD                      =  4
23REG_DWORD_LE                   =  4 # DWORD, little endian
24REG_DWORD_BE                   =  5 # DWORD, big endian
25REG_LINK                       =  6
26REG_MULTI_SZ                   =  7
27REG_RESOURCE_LIST              =  8
28REG_FULL_RESOURCE_DESCRIPTOR   =  9
29REG_RESOURCE_REQUIREMENTS_LIST = 10
30REG_QWORD                      = 11 # 64-bit little endian
[205]31
[209]32
[205]33# Prototype everything first so we don't have to worry about reference order
34class REGFI_NTTIME(Structure):
35    pass
36
37class REGFI_VK(Structure):
38    pass
39
40class REGFI_SK(Structure):
41    pass
42
43class REGFI_SUBKEY_LIST(Structure):
44    pass
45
46class REGFI_VALUE_LIST(Structure):
47    pass
48
49class REGFI_CLASSNAME(Structure):
50    pass
51
52class REGFI_DATA(Structure):
53    pass
54
55class REGFI_NK(Structure):
56    pass
57
58class REGFI_ITERATOR(Structure):
59    pass
60
61class REGFI_FILE(Structure):
62    pass
63
64class REGFI_RAW_FILE(Structure):
[204]65    fh = None
66   
67    def cb_seek(self, raw_file, offset, whence):
68        try:
69            self.fh.seek(offset, whence)
70        except Exception:
71            traceback.print_exc()
72            # XXX: os.EX_IOERR may not be available on Windoze
[205]73            set_errno(os.EX_IOERR)
[204]74            return -1
75
76        return self.fh.tell()
77
78
79    def cb_read(self, raw_file, buf, count):
80        try:
81            # XXX: anyway to do a readinto() here?
82            tmp = self.fh.read(count)
[205]83            memmove(buf,tmp,len(tmp))
[204]84
85        except Exception:
86            traceback.print_exc()
87            # XXX: os.EX_IOERR may not be available on Windoze
[205]88            set_errno(os.EX_IOERR)
[204]89            return -1
90        return len(tmp)
91
92
93# XXX: how can we know for sure the size of off_t and size_t?
[205]94seek_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
95read_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_uint64, use_errno=True)
[204]96
97
[205]98REGFI_NTTIME._fields_ = [('low', c_uint32),
99                         ('high', c_uint32)]
100
101REGFI_VK._fields_ = [('offset', c_uint32),
102                     ('cell_size', c_uint32),
[206]103                     ('name', c_char_p),
104                     ('name_raw', POINTER(c_char)),
[205]105                     ('name_length', c_uint16),
106                     ('hbin_off', c_uint32),
107                     ('data_size', c_uint32),
108                     ('data_off', c_uint32),
109                     ('type', REGFI_DATA_TYPE),
110                     ('magic', c_char * 2),
111                     ('flags', c_uint16),
112                     ('unknown1', c_uint16),
113                     ('data_in_offset', c_bool),
114                     ]
115
116
117REGFI_SK._fields_ = [('offset', c_uint32),
118                     ('cell_size', c_uint32),
119                     ('sec_desc', c_void_p), #XXX
120                     ('hbin_off', c_uint32),
121                     ('prev_sk_off', c_uint32),
122                     ('next_sk_off', c_uint32),
123                     ('ref_count', c_uint32),
124                     ('desc_size', c_uint32),
125                     ('unknown_tag', c_uint16),
126                     ('magic', c_char * 2),
127                     ]
128
129
130REGFI_NK._fields_ = [('offset', c_uint32),
131                     ('cell_size', c_uint32),
132                     ('values', POINTER(REGFI_VALUE_LIST)),
133                     ('subkeys', POINTER(REGFI_SUBKEY_LIST)),
134                     ('flags', c_uint16),
135                     ('magic', c_char * 2),
136                     ('mtime', REGFI_NTTIME),
137                     ('name_length', c_uint16),
138                     ('classname_length', c_uint16),
[206]139                     ('name', c_char_p),
140                     ('name_raw', POINTER(c_char)),
[205]141                     ('parent_off', c_uint32),
142                     ('classname_off', c_uint32),
143                     ('max_bytes_subkeyname', c_uint32),
144                     ('max_bytes_subkeyclassname', c_uint32),
145                     ('max_bytes_valuename', c_uint32),
146                     ('max_bytes_value', c_uint32),
147                     ('unknown1', c_uint32),
148                     ('unknown2', c_uint32),
149                     ('unknown3', c_uint32),
150                     ('unk_index', c_uint32),
151                     ('num_subkeys', c_uint32),
152                     ('subkeys_off', c_uint32),
153                     ('num_values', c_uint32),
154                     ('values_off', c_uint32),
155                     ('sk_off', c_uint32),
156                     ]
157
158
159REGFI_SUBKEY_LIST._fields_ = [('offset', c_uint32),
160                              ('cell_size', c_uint32),
161                              ('num_children', c_uint32),
162                              ('num_keys', c_uint32),
163                              ('elements', c_void_p),
164                              ('magic', c_char * 2),
165                              ('recursive_type', c_bool),
166                              ]
167
168
169REGFI_VALUE_LIST._fields_ = [('offset', c_uint32),
170                             ('cell_size', c_uint32),
171                             ('num_children', c_uint32),
172                             ('num_values', c_uint32),
173                             ('elements', c_void_p),
174                             ]
175
176REGFI_CLASSNAME._fields_ = [('offset', c_uint32),
177                            ('interpreted', c_char_p),
178                            ('raw', POINTER(c_char)),
179                            ('size', c_uint16),
180                            ]
181
182
183class REGFI_DATA__interpreted(Union):
184    _fields_ = [('none',POINTER(c_char)),
185                ('string', c_char_p),
186                ('expand_string', c_char_p),
187                ('binary',POINTER(c_char)),
188                ('dword', c_uint32),
189                ('dword_be', c_uint32),
190                ('link', c_char_p),
191                ('multiple_string', POINTER(c_char_p)),
192                ('qword', c_uint64),
193                ('resource_list',POINTER(c_char)),
194                ('full_resource_descriptor',POINTER(c_char)),
195                ('resource_requirements_list',POINTER(c_char)),
[209]196                ]
[205]197REGFI_DATA._fields_ = [('offset', c_uint32),
198                       ('type', REGFI_DATA_TYPE),
199                       ('size', c_uint32),
200                       ('raw', POINTER(c_char)),
201                       ('interpreted_size', c_uint32),
202                       ('interpreted', REGFI_DATA__interpreted),
203                       ]
204
[209]205
[205]206REGFI_FILE._fields_ = [('magic', c_char * 4),
207                       ('sequence1', c_uint32),
208                       ('sequence2', c_uint32),
209                       ('mtime', REGFI_NTTIME),
210                       ('major_version', c_uint32),
211                       ('minor_version', c_uint32),
212                       ('type', c_uint32),
213                       ('format', c_uint32),
214                       ('root_cell', c_uint32),
215                       ('last_block', c_uint32),
216                       ('cluster', c_uint32),
217                       ]
218
219
[204]220REGFI_RAW_FILE._fields_ = [('seek', seek_cb_type),
221                           ('read', read_cb_type),
222                           ('cur_off', c_uint64),
223                           ('size', c_uint64),
224                           ('state', c_void_p),
225                           ]
[220]226
227
228# Load libregfi and define function prototypes
229regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
230
231regfi.regfi_alloc.argtypes = [c_int, REGFI_ENCODING]
232regfi.regfi_alloc.restype = POINTER(REGFI_FILE)
233
234regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE), REGFI_ENCODING]
235regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
236
237regfi.regfi_free.argtypes = [POINTER(REGFI_FILE)]
238regfi.regfi_free.restype = None
239
240regfi.regfi_log_get_str.argtypes = []
241regfi.regfi_log_get_str.restype = c_char_p
242
243regfi.regfi_log_set_mask.argtypes = [c_uint16]
244regfi.regfi_log_set_mask.restype = c_bool
245
246regfi.regfi_get_rootkey.argtypes = [POINTER(REGFI_FILE)]
247regfi.regfi_get_rootkey.restype = POINTER(REGFI_NK)
248
249regfi.regfi_free_record.argtypes = [c_void_p]
250regfi.regfi_free_record.restype = None
251
252regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
253regfi.regfi_fetch_num_subkeys.restype = c_uint32
254
255regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
256regfi.regfi_fetch_num_values.restype = c_uint32
257
258regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
259regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
260
261regfi.regfi_fetch_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
262regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
263
264regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
265regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
266
267regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
268                                    c_char_p, POINTER(c_uint32)]
269regfi.regfi_find_subkey.restype = c_bool
270
271regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
272                                    c_char_p, POINTER(c_uint32)]
273regfi.regfi_find_value.restype = c_bool
274
275regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
276                                   c_uint32]
277regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
278
279regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
280                                   c_uint32]
281regfi.regfi_get_value.restype = POINTER(REGFI_VK)
282
283regfi.regfi_get_parentkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
284regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
285
286regfi.regfi_nt2unix_time.argtypes = [POINTER(REGFI_NTTIME)]
287regfi.regfi_nt2unix_time.restype = c_double
288
289regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
290regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
291
292regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
293regfi.regfi_iterator_free.restype = None
294
295regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
296regfi.regfi_iterator_down.restype = c_bool
297
298regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
299regfi.regfi_iterator_up.restype = c_bool
300
301regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
302regfi.regfi_iterator_to_root.restype = c_bool
303
304regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR)]
305regfi.regfi_iterator_walk_path.restype = c_bool
306
307regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
308regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
309
310regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
311regfi.regfi_iterator_first_subkey.restype = c_bool
312
313regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
314regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
315
316regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
317regfi.regfi_iterator_next_subkey.restype = c_bool
318
319regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
320regfi.regfi_iterator_find_subkey.restype = c_bool
321
322regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
323regfi.regfi_iterator_first_value.restype = c_bool
324
325regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
326regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
327
328regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
329regfi.regfi_iterator_next_value.restype = c_bool
330
331regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
332regfi.regfi_iterator_find_value.restype = c_bool
333
334
335regfi.regfi_init.argtypes = []
336regfi.regfi_init.restype = None
337regfi.regfi_init()
Note: See TracBrowser for help on using the repository browser.