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

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

added a test case for pyregfi multithreaded use
updated the regfi multithreaded test case
fixed several ctypes interface problems in pyregfi
added locking to pyregfi iterators for thread safety
fixed regfi talloc race conditions with an additional lock

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