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

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

switched to %XX encoding in command line tool output

fixed limitation with NULL/None/(default) value name lookups

corrected an nttime bug

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.