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

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

fixed error condition deadlock in regfi
prevented early garbage collection of hive file handles
fixed module imports under python3

File size: 11.9 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
[252]22REGFI_NTTIME = c_uint64
[204]23
[253]24REGFI_REGF_SIZE = 0x1000
25
[205]26# Prototype everything first so we don't have to worry about reference order
27class REGFI_VK(Structure):
28    pass
29
30class REGFI_SK(Structure):
31    pass
32
33class REGFI_SUBKEY_LIST(Structure):
34    pass
35
36class REGFI_VALUE_LIST(Structure):
37    pass
38
39class REGFI_CLASSNAME(Structure):
40    pass
41
42class REGFI_DATA(Structure):
43    pass
44
45class REGFI_NK(Structure):
46    pass
47
48class REGFI_ITERATOR(Structure):
49    pass
50
51class REGFI_FILE(Structure):
52    pass
53
54class REGFI_RAW_FILE(Structure):
[204]55    fh = None
56   
57    def cb_seek(self, raw_file, offset, whence):
58        try:
59            self.fh.seek(offset, whence)
60        except Exception:
61            traceback.print_exc()
[226]62            set_errno(74) # os.EX_IOERR
[204]63            return -1
64
65        return self.fh.tell()
66
67
68    def cb_read(self, raw_file, buf, count):
69        try:
70            # XXX: anyway to do a readinto() here?
71            tmp = self.fh.read(count)
[205]72            memmove(buf,tmp,len(tmp))
[204]73
74        except Exception:
75            traceback.print_exc()
[226]76            set_errno(74) # os.EX_IOERR
[204]77            return -1
78        return len(tmp)
79
80
[225]81# Load libregfi according to platform
82regfi = None
[226]83if is_win32:
84    # XXX: Using C calling conventions on cross-compiled DLLs seems to work fine
85    #      on Windows, but I'm not sure if stdcall symbols are supported
86    #      correctly for native Windows binaries...
[225]87    #regfi = ctypes.windll.libregfi
[226]88    #CB_FACTORY = ctypes.WINFUNCTYPE
89    regfi = ctypes.CDLL('libregfi.dll', use_errno=True)
90    CB_FACTORY = ctypes.CFUNCTYPE
[225]91else:
92    regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
93    CB_FACTORY = ctypes.CFUNCTYPE
[204]94
[226]95seek_cb_type = CB_FACTORY(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
96read_cb_type = CB_FACTORY(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_size_t, use_errno=True)
[204]97
[225]98
[255]99from .winsec import *
[253]100
[205]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),
[253]119                     ('sec_desc', POINTER(WINSEC_DESC)),
[205]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_values', c_uint32),
172                             ('elements', c_void_p),
173                             ]
174
175REGFI_CLASSNAME._fields_ = [('offset', c_uint32),
176                            ('interpreted', c_char_p),
177                            ('raw', POINTER(c_char)),
178                            ('size', c_uint16),
179                            ]
180
181
182class REGFI_DATA__interpreted(Union):
183    _fields_ = [('none',POINTER(c_char)),
184                ('string', c_char_p),
185                ('expand_string', c_char_p),
186                ('binary',POINTER(c_char)),
187                ('dword', c_uint32),
188                ('dword_be', c_uint32),
189                ('link', c_char_p),
190                ('multiple_string', POINTER(c_char_p)),
191                ('qword', c_uint64),
192                ('resource_list',POINTER(c_char)),
193                ('full_resource_descriptor',POINTER(c_char)),
194                ('resource_requirements_list',POINTER(c_char)),
[209]195                ]
[205]196REGFI_DATA._fields_ = [('offset', c_uint32),
197                       ('type', REGFI_DATA_TYPE),
198                       ('size', c_uint32),
199                       ('raw', POINTER(c_char)),
200                       ('interpreted_size', c_uint32),
201                       ('interpreted', REGFI_DATA__interpreted),
202                       ]
203
[209]204
[205]205REGFI_FILE._fields_ = [('magic', c_char * 4),
206                       ('sequence1', c_uint32),
207                       ('sequence2', c_uint32),
208                       ('mtime', REGFI_NTTIME),
209                       ('major_version', c_uint32),
210                       ('minor_version', c_uint32),
211                       ('type', c_uint32),
212                       ('format', c_uint32),
213                       ('root_cell', c_uint32),
214                       ('last_block', c_uint32),
215                       ('cluster', c_uint32),
216                       ]
217
218
[204]219REGFI_RAW_FILE._fields_ = [('seek', seek_cb_type),
220                           ('read', read_cb_type),
221                           ('cur_off', c_uint64),
222                           ('size', c_uint64),
223                           ('state', c_void_p),
224                           ]
[220]225
226
[225]227# Define function prototypes
[233]228regfi.regfi_version.argtypes = []
229regfi.regfi_version.restype = c_char_p
230
[220]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
[228]249regfi.regfi_free_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
[220]250regfi.regfi_free_record.restype = None
251
[228]252regfi.regfi_reference_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
[252]253regfi.regfi_reference_record.restype = c_void_p
[224]254
[220]255regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
256regfi.regfi_fetch_num_subkeys.restype = c_uint32
257
258regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
259regfi.regfi_fetch_num_values.restype = c_uint32
260
261regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
262regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
263
264regfi.regfi_fetch_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
265regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
266
[253]267regfi.regfi_next_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
268regfi.regfi_next_sk.restype = POINTER(REGFI_SK)
269
270regfi.regfi_prev_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
271regfi.regfi_prev_sk.restype = POINTER(REGFI_SK)
272
[220]273regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
274regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
275
276regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
277                                    c_char_p, POINTER(c_uint32)]
278regfi.regfi_find_subkey.restype = c_bool
279
280regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
281                                    c_char_p, POINTER(c_uint32)]
282regfi.regfi_find_value.restype = c_bool
283
284regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
285                                   c_uint32]
286regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
287
288regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
289                                   c_uint32]
290regfi.regfi_get_value.restype = POINTER(REGFI_VK)
291
292regfi.regfi_get_parentkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
293regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
294
[253]295regfi.regfi_nt2unix_time.argtypes = [REGFI_NTTIME]
[220]296regfi.regfi_nt2unix_time.restype = c_double
297
[228]298regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE)]
[220]299regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
300
301regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
302regfi.regfi_iterator_free.restype = None
303
304regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
305regfi.regfi_iterator_down.restype = c_bool
306
307regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
308regfi.regfi_iterator_up.restype = c_bool
309
310regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
311regfi.regfi_iterator_to_root.restype = c_bool
312
[252]313regfi.regfi_iterator_descend.argtypes = [POINTER(REGFI_ITERATOR), POINTER(c_char_p)]
314regfi.regfi_iterator_descend.restype = c_bool
[220]315
316regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
317regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
318
319regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
320regfi.regfi_iterator_first_subkey.restype = c_bool
321
322regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
323regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
324
325regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
326regfi.regfi_iterator_next_subkey.restype = c_bool
327
328regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
329regfi.regfi_iterator_find_subkey.restype = c_bool
330
331regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
332regfi.regfi_iterator_first_value.restype = c_bool
333
334regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
335regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
336
337regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
338regfi.regfi_iterator_next_value.restype = c_bool
339
340regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
341regfi.regfi_iterator_find_value.restype = c_bool
342
[252]343regfi.regfi_iterator_ancestry.argtypes = [POINTER(REGFI_ITERATOR)]
344regfi.regfi_iterator_ancestry.restype = POINTER(POINTER(REGFI_NK))
[220]345
346regfi.regfi_init.argtypes = []
347regfi.regfi_init.restype = None
348regfi.regfi_init()
Note: See TracBrowser for help on using the repository browser.