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

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

several fixes for pyregfi Windows portability
better error handling within pyregfi

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