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
Line 
1#!/usr/bin/env python
2
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
8import sys
9import os
10import traceback
11import ctypes
12import ctypes.util
13from ctypes import *
14
15is_win32 = hasattr(ctypes, 'windll')
16
17# XXX: can we always be sure enums are this size?
18REGFI_ENCODING = c_uint32
19REGFI_ENCODING_UTF8 = REGFI_ENCODING(1)
20
21REGFI_DATA_TYPE = c_uint32
22REGFI_NTTIME = c_uint64
23
24REGFI_REGF_SIZE = 0x1000
25
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):
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()
62            set_errno(74) # os.EX_IOERR
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)
72            memmove(buf,tmp,len(tmp))
73
74        except Exception:
75            traceback.print_exc()
76            set_errno(74) # os.EX_IOERR
77            return -1
78        return len(tmp)
79
80
81# Load libregfi according to platform
82regfi = None
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...
87    #regfi = ctypes.windll.libregfi
88    #CB_FACTORY = ctypes.WINFUNCTYPE
89    regfi = ctypes.CDLL('libregfi.dll', use_errno=True)
90    CB_FACTORY = ctypes.CFUNCTYPE
91else:
92    regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
93    CB_FACTORY = ctypes.CFUNCTYPE
94
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)
97
98
99from .winsec import *
100
101REGFI_VK._fields_ = [('offset', c_uint32),
102                     ('cell_size', c_uint32),
103                     ('name', c_char_p),
104                     ('name_raw', POINTER(c_char)),
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', POINTER(WINSEC_DESC)),
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),
139                     ('name', c_char_p),
140                     ('name_raw', POINTER(c_char)),
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)),
195                ]
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
204
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
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                           ]
225
226
227# Define function prototypes
228regfi.regfi_version.argtypes = []
229regfi.regfi_version.restype = c_char_p
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 = [POINTER(REGFI_FILE), c_void_p]
250regfi.regfi_free_record.restype = None
251
252regfi.regfi_reference_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
253regfi.regfi_reference_record.restype = c_void_p
254
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
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
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
295regfi.regfi_nt2unix_time.argtypes = [REGFI_NTTIME]
296regfi.regfi_nt2unix_time.restype = c_double
297
298regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE)]
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
313regfi.regfi_iterator_descend.argtypes = [POINTER(REGFI_ITERATOR), POINTER(c_char_p)]
314regfi.regfi_iterator_descend.restype = c_bool
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
343regfi.regfi_iterator_ancestry.argtypes = [POINTER(REGFI_ITERATOR)]
344regfi.regfi_iterator_ancestry.restype = POINTER(POINTER(REGFI_NK))
345
346regfi.regfi_init.argtypes = []
347regfi.regfi_init.restype = None
348regfi.regfi_init()
Note: See TracBrowser for help on using the repository browser.