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

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

added new regfi API function to help manage memory better
fixed reference loop problems in pyregfi

File size: 11.2 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
15
16# XXX: can we always be sure enums are this size?
17REGFI_ENCODING = c_uint32
18REGFI_ENCODING_UTF8 = 1
19
20REGFI_DATA_TYPE = c_uint32
21REGFI_REGF_SIZE = 0x1000
22
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):
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()
63            # XXX: os.EX_IOERR may not be available on Windoze
64            set_errno(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            # XXX: os.EX_IOERR may not be available on Windoze
79            set_errno(os.EX_IOERR)
80            return -1
81        return len(tmp)
82
83
84# XXX: how can we know for sure the size of off_t and size_t?
85seek_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
86read_cb_type = CFUNCTYPE(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_uint64, use_errno=True)
87
88
89REGFI_NTTIME._fields_ = [('low', c_uint32),
90                         ('high', c_uint32)]
91
92REGFI_VK._fields_ = [('offset', c_uint32),
93                     ('cell_size', c_uint32),
94                     ('name', c_char_p),
95                     ('name_raw', POINTER(c_char)),
96                     ('name_length', c_uint16),
97                     ('hbin_off', c_uint32),
98                     ('data_size', c_uint32),
99                     ('data_off', c_uint32),
100                     ('type', REGFI_DATA_TYPE),
101                     ('magic', c_char * 2),
102                     ('flags', c_uint16),
103                     ('unknown1', c_uint16),
104                     ('data_in_offset', c_bool),
105                     ]
106
107
108REGFI_SK._fields_ = [('offset', c_uint32),
109                     ('cell_size', c_uint32),
110                     ('sec_desc', c_void_p), #XXX
111                     ('hbin_off', c_uint32),
112                     ('prev_sk_off', c_uint32),
113                     ('next_sk_off', c_uint32),
114                     ('ref_count', c_uint32),
115                     ('desc_size', c_uint32),
116                     ('unknown_tag', c_uint16),
117                     ('magic', c_char * 2),
118                     ]
119
120
121REGFI_NK._fields_ = [('offset', c_uint32),
122                     ('cell_size', c_uint32),
123                     ('values', POINTER(REGFI_VALUE_LIST)),
124                     ('subkeys', POINTER(REGFI_SUBKEY_LIST)),
125                     ('flags', c_uint16),
126                     ('magic', c_char * 2),
127                     ('mtime', REGFI_NTTIME),
128                     ('name_length', c_uint16),
129                     ('classname_length', c_uint16),
130                     ('name', c_char_p),
131                     ('name_raw', POINTER(c_char)),
132                     ('parent_off', c_uint32),
133                     ('classname_off', c_uint32),
134                     ('max_bytes_subkeyname', c_uint32),
135                     ('max_bytes_subkeyclassname', c_uint32),
136                     ('max_bytes_valuename', c_uint32),
137                     ('max_bytes_value', c_uint32),
138                     ('unknown1', c_uint32),
139                     ('unknown2', c_uint32),
140                     ('unknown3', c_uint32),
141                     ('unk_index', c_uint32),
142                     ('num_subkeys', c_uint32),
143                     ('subkeys_off', c_uint32),
144                     ('num_values', c_uint32),
145                     ('values_off', c_uint32),
146                     ('sk_off', c_uint32),
147                     ]
148
149
150REGFI_SUBKEY_LIST._fields_ = [('offset', c_uint32),
151                              ('cell_size', c_uint32),
152                              ('num_children', c_uint32),
153                              ('num_keys', c_uint32),
154                              ('elements', c_void_p),
155                              ('magic', c_char * 2),
156                              ('recursive_type', c_bool),
157                              ]
158
159
160REGFI_VALUE_LIST._fields_ = [('offset', c_uint32),
161                             ('cell_size', c_uint32),
162                             ('num_children', c_uint32),
163                             ('num_values', c_uint32),
164                             ('elements', c_void_p),
165                             ]
166
167REGFI_CLASSNAME._fields_ = [('offset', c_uint32),
168                            ('interpreted', c_char_p),
169                            ('raw', POINTER(c_char)),
170                            ('size', c_uint16),
171                            ]
172
173
174class REGFI_DATA__interpreted(Union):
175    _fields_ = [('none',POINTER(c_char)),
176                ('string', c_char_p),
177                ('expand_string', c_char_p),
178                ('binary',POINTER(c_char)),
179                ('dword', c_uint32),
180                ('dword_be', c_uint32),
181                ('link', c_char_p),
182                ('multiple_string', POINTER(c_char_p)),
183                ('qword', c_uint64),
184                ('resource_list',POINTER(c_char)),
185                ('full_resource_descriptor',POINTER(c_char)),
186                ('resource_requirements_list',POINTER(c_char)),
187                ]
188REGFI_DATA._fields_ = [('offset', c_uint32),
189                       ('type', REGFI_DATA_TYPE),
190                       ('size', c_uint32),
191                       ('raw', POINTER(c_char)),
192                       ('interpreted_size', c_uint32),
193                       ('interpreted', REGFI_DATA__interpreted),
194                       ]
195
196
197REGFI_FILE._fields_ = [('magic', c_char * 4),
198                       ('sequence1', c_uint32),
199                       ('sequence2', c_uint32),
200                       ('mtime', REGFI_NTTIME),
201                       ('major_version', c_uint32),
202                       ('minor_version', c_uint32),
203                       ('type', c_uint32),
204                       ('format', c_uint32),
205                       ('root_cell', c_uint32),
206                       ('last_block', c_uint32),
207                       ('cluster', c_uint32),
208                       ]
209
210
211REGFI_RAW_FILE._fields_ = [('seek', seek_cb_type),
212                           ('read', read_cb_type),
213                           ('cur_off', c_uint64),
214                           ('size', c_uint64),
215                           ('state', c_void_p),
216                           ]
217
218
219# Load libregfi and define function prototypes
220regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
221
222regfi.regfi_alloc.argtypes = [c_int, REGFI_ENCODING]
223regfi.regfi_alloc.restype = POINTER(REGFI_FILE)
224
225regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE), REGFI_ENCODING]
226regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
227
228regfi.regfi_free.argtypes = [POINTER(REGFI_FILE)]
229regfi.regfi_free.restype = None
230
231regfi.regfi_log_get_str.argtypes = []
232regfi.regfi_log_get_str.restype = c_char_p
233
234regfi.regfi_log_set_mask.argtypes = [c_uint16]
235regfi.regfi_log_set_mask.restype = c_bool
236
237regfi.regfi_get_rootkey.argtypes = [POINTER(REGFI_FILE)]
238regfi.regfi_get_rootkey.restype = POINTER(REGFI_NK)
239
240regfi.regfi_free_record.argtypes = [c_void_p]
241regfi.regfi_free_record.restype = None
242
243regfi.regfi_reference_record.argtypes = [c_void_p]
244regfi.regfi_reference_record.restype = c_bool
245
246regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
247regfi.regfi_fetch_num_subkeys.restype = c_uint32
248
249regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
250regfi.regfi_fetch_num_values.restype = c_uint32
251
252regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
253regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
254
255regfi.regfi_fetch_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
256regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
257
258regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
259regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
260
261regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
262                                    c_char_p, POINTER(c_uint32)]
263regfi.regfi_find_subkey.restype = c_bool
264
265regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
266                                    c_char_p, POINTER(c_uint32)]
267regfi.regfi_find_value.restype = c_bool
268
269regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
270                                   c_uint32]
271regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
272
273regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
274                                   c_uint32]
275regfi.regfi_get_value.restype = POINTER(REGFI_VK)
276
277regfi.regfi_get_parentkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
278regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
279
280regfi.regfi_nt2unix_time.argtypes = [POINTER(REGFI_NTTIME)]
281regfi.regfi_nt2unix_time.restype = c_double
282
283regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
284regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
285
286regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
287regfi.regfi_iterator_free.restype = None
288
289regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
290regfi.regfi_iterator_down.restype = c_bool
291
292regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
293regfi.regfi_iterator_up.restype = c_bool
294
295regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
296regfi.regfi_iterator_to_root.restype = c_bool
297
298regfi.regfi_iterator_walk_path.argtypes = [POINTER(REGFI_ITERATOR)]
299regfi.regfi_iterator_walk_path.restype = c_bool
300
301regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
302regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
303
304regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
305regfi.regfi_iterator_first_subkey.restype = c_bool
306
307regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
308regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
309
310regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
311regfi.regfi_iterator_next_subkey.restype = c_bool
312
313regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
314regfi.regfi_iterator_find_subkey.restype = c_bool
315
316regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
317regfi.regfi_iterator_first_value.restype = c_bool
318
319regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
320regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
321
322regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
323regfi.regfi_iterator_next_value.restype = c_bool
324
325regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
326regfi.regfi_iterator_find_value.restype = c_bool
327
328
329regfi.regfi_init.argtypes = []
330regfi.regfi_init.restype = None
331regfi.regfi_init()
Note: See TracBrowser for help on using the repository browser.