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

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

fixed some problems interpreting key/value names

File size: 12.6 KB
Line 
1#!/usr/bin/env python
2
3# Copyright (C) 2010-2011 Timothy D. Morgan
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; version 3 of the License.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17#
18# $Id: $
19
20## @package pyregfi.structures
21# Low-level data structures and C API mappings.
22#
23# Most users need not venture here.  For more information, see the source.
24
25import sys
26import os
27import traceback
28import ctypes
29import ctypes.util
30from ctypes import *
31
32is_win32 = hasattr(ctypes, 'windll')
33
34# XXX: can we always be sure enums are this size?
35REGFI_ENCODING = c_uint32
36REGFI_ENCODING_UTF8 = REGFI_ENCODING(1)
37
38REGFI_NK_FLAG_ASCIINAME = 0x0020
39REGFI_VK_FLAG_ASCIINAME = 0x0001
40
41REGFI_DATA_TYPE = c_uint32
42REGFI_NTTIME = c_uint64
43
44REGFI_REGF_SIZE = 0x1000
45
46# Prototype everything first so we don't have to worry about reference order
47class REGFI_VK(Structure):
48    pass
49
50class REGFI_SK(Structure):
51    pass
52
53class REGFI_SUBKEY_LIST(Structure):
54    pass
55
56class REGFI_VALUE_LIST(Structure):
57    pass
58
59class REGFI_CLASSNAME(Structure):
60    pass
61
62class REGFI_DATA(Structure):
63    pass
64
65class REGFI_NK(Structure):
66    pass
67
68class REGFI_ITERATOR(Structure):
69    pass
70
71class REGFI_FILE(Structure):
72    pass
73
74class REGFI_RAW_FILE(Structure):
75    fh = None
76   
77    def cb_seek(self, raw_file, offset, whence):
78        try:
79            self.fh.seek(offset, whence)
80        except Exception:
81            traceback.print_exc()
82            set_errno(74) # os.EX_IOERR
83            return -1
84
85        return self.fh.tell()
86
87
88    def cb_read(self, raw_file, buf, count):
89        try:
90            # XXX: anyway to do a readinto() here?
91            tmp = self.fh.read(count)
92            memmove(buf,tmp,len(tmp))
93
94        except Exception:
95            traceback.print_exc()
96            set_errno(74) # os.EX_IOERR
97            return -1
98        return len(tmp)
99
100
101# Load libregfi according to platform
102regfi = None
103if is_win32:
104    # XXX: Using C calling conventions on cross-compiled DLLs seems to work fine
105    #      on Windows, but I'm not sure if stdcall symbols are supported
106    #      correctly for native Windows binaries...
107    #regfi = ctypes.windll.libregfi
108    #CB_FACTORY = ctypes.WINFUNCTYPE
109    regfi = ctypes.CDLL('libregfi.dll', use_errno=True)
110    CB_FACTORY = ctypes.CFUNCTYPE
111else:
112    regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
113    CB_FACTORY = ctypes.CFUNCTYPE
114
115seek_cb_type = CB_FACTORY(c_int64, POINTER(REGFI_RAW_FILE), c_uint64, c_int, use_errno=True)
116read_cb_type = CB_FACTORY(c_int64, POINTER(REGFI_RAW_FILE), POINTER(c_char), c_size_t, use_errno=True)
117
118
119from .winsec import *
120
121REGFI_VK._fields_ = [('offset', c_uint32),
122                     ('cell_size', c_uint32),
123                     ('name', c_char_p),
124                     ('name_raw', POINTER(c_char)),
125                     ('name_length', c_uint16),
126                     ('hbin_off', c_uint32),
127                     ('data_size', c_uint32),
128                     ('data_off', c_uint32),
129                     ('type', REGFI_DATA_TYPE),
130                     ('magic', c_char * 2),
131                     ('flags', c_uint16),
132                     ('unknown1', c_uint16),
133                     ('data_in_offset', c_bool),
134                     ]
135
136
137REGFI_SK._fields_ = [('offset', c_uint32),
138                     ('cell_size', c_uint32),
139                     ('sec_desc', POINTER(WINSEC_DESC)),
140                     ('hbin_off', c_uint32),
141                     ('prev_sk_off', c_uint32),
142                     ('next_sk_off', c_uint32),
143                     ('ref_count', c_uint32),
144                     ('desc_size', c_uint32),
145                     ('unknown_tag', c_uint16),
146                     ('magic', c_char * 2),
147                     ]
148
149
150REGFI_NK._fields_ = [('offset', c_uint32),
151                     ('cell_size', c_uint32),
152                     ('values', POINTER(REGFI_VALUE_LIST)),
153                     ('subkeys', POINTER(REGFI_SUBKEY_LIST)),
154                     ('flags', c_uint16),
155                     ('magic', c_char * 2),
156                     ('mtime', REGFI_NTTIME),
157                     ('name_length', c_uint16),
158                     ('classname_length', c_uint16),
159                     ('name', c_char_p),
160                     ('name_raw', POINTER(c_char)),
161                     ('parent_off', c_uint32),
162                     ('classname_off', c_uint32),
163                     ('max_bytes_subkeyname', c_uint32),
164                     ('max_bytes_subkeyclassname', c_uint32),
165                     ('max_bytes_valuename', c_uint32),
166                     ('max_bytes_value', c_uint32),
167                     ('unknown1', c_uint32),
168                     ('unknown2', c_uint32),
169                     ('unknown3', c_uint32),
170                     ('unk_index', c_uint32),
171                     ('num_subkeys', c_uint32),
172                     ('subkeys_off', c_uint32),
173                     ('num_values', c_uint32),
174                     ('values_off', c_uint32),
175                     ('sk_off', c_uint32),
176                     ]
177
178
179REGFI_SUBKEY_LIST._fields_ = [('offset', c_uint32),
180                              ('cell_size', c_uint32),
181                              ('num_children', c_uint32),
182                              ('num_keys', c_uint32),
183                              ('elements', c_void_p),
184                              ('magic', c_char * 2),
185                              ('recursive_type', c_bool),
186                              ]
187
188
189REGFI_VALUE_LIST._fields_ = [('offset', c_uint32),
190                             ('cell_size', c_uint32),
191                             ('num_values', c_uint32),
192                             ('elements', c_void_p),
193                             ]
194
195REGFI_CLASSNAME._fields_ = [('offset', c_uint32),
196                            ('interpreted', c_char_p),
197                            ('raw', POINTER(c_char)),
198                            ('size', c_uint16),
199                            ]
200
201
202class REGFI_DATA__interpreted(Union):
203    _fields_ = [('none',POINTER(c_char)),
204                ('string', c_char_p),
205                ('expand_string', c_char_p),
206                ('binary',POINTER(c_char)),
207                ('dword', c_uint32),
208                ('dword_be', c_uint32),
209                ('link', c_char_p),
210                ('multiple_string', POINTER(c_char_p)),
211                ('qword', c_uint64),
212                ('resource_list',POINTER(c_char)),
213                ('full_resource_descriptor',POINTER(c_char)),
214                ('resource_requirements_list',POINTER(c_char)),
215                ]
216REGFI_DATA._fields_ = [('offset', c_uint32),
217                       ('type', REGFI_DATA_TYPE),
218                       ('size', c_uint32),
219                       ('raw', POINTER(c_char)),
220                       ('interpreted_size', c_uint32),
221                       ('interpreted', REGFI_DATA__interpreted),
222                       ]
223
224
225REGFI_FILE._fields_ = [('magic', c_char * 4),
226                       ('sequence1', c_uint32),
227                       ('sequence2', c_uint32),
228                       ('mtime', REGFI_NTTIME),
229                       ('major_version', c_uint32),
230                       ('minor_version', c_uint32),
231                       ('type', c_uint32),
232                       ('format', c_uint32),
233                       ('root_cell', c_uint32),
234                       ('last_block', c_uint32),
235                       ('cluster', c_uint32),
236                       ]
237
238
239REGFI_RAW_FILE._fields_ = [('seek', seek_cb_type),
240                           ('read', read_cb_type),
241                           ('cur_off', c_uint64),
242                           ('size', c_uint64),
243                           ('state', c_void_p),
244                           ]
245
246
247# Define function prototypes
248regfi.regfi_version.argtypes = []
249regfi.regfi_version.restype = c_char_p
250
251regfi.regfi_alloc.argtypes = [c_int, REGFI_ENCODING]
252regfi.regfi_alloc.restype = POINTER(REGFI_FILE)
253
254regfi.regfi_alloc_cb.argtypes = [POINTER(REGFI_RAW_FILE), REGFI_ENCODING]
255regfi.regfi_alloc_cb.restype = POINTER(REGFI_FILE)
256
257regfi.regfi_free.argtypes = [POINTER(REGFI_FILE)]
258regfi.regfi_free.restype = None
259
260regfi.regfi_log_get_str.argtypes = []
261regfi.regfi_log_get_str.restype = c_char_p
262
263regfi.regfi_log_set_mask.argtypes = [c_uint16]
264regfi.regfi_log_set_mask.restype = c_bool
265
266regfi.regfi_get_rootkey.argtypes = [POINTER(REGFI_FILE)]
267regfi.regfi_get_rootkey.restype = POINTER(REGFI_NK)
268
269regfi.regfi_free_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
270regfi.regfi_free_record.restype = None
271
272regfi.regfi_reference_record.argtypes = [POINTER(REGFI_FILE), c_void_p]
273regfi.regfi_reference_record.restype = c_void_p
274
275regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
276regfi.regfi_fetch_num_subkeys.restype = c_uint32
277
278regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
279regfi.regfi_fetch_num_values.restype = c_uint32
280
281regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
282regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
283
284regfi.regfi_fetch_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
285regfi.regfi_fetch_sk.restype = POINTER(REGFI_SK)
286
287regfi.regfi_next_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
288regfi.regfi_next_sk.restype = POINTER(REGFI_SK)
289
290regfi.regfi_prev_sk.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_SK)]
291regfi.regfi_prev_sk.restype = POINTER(REGFI_SK)
292
293regfi.regfi_fetch_data.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_VK)]
294regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
295
296regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
297                                    c_char_p, POINTER(c_uint32)]
298regfi.regfi_find_subkey.restype = c_bool
299
300regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
301                                   c_char_p, POINTER(c_uint32)]
302regfi.regfi_find_value.restype = c_bool
303
304regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
305                                   c_uint32]
306regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
307
308regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
309                                  c_uint32]
310regfi.regfi_get_value.restype = POINTER(REGFI_VK)
311
312regfi.regfi_get_parentkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
313regfi.regfi_get_parentkey.restype = POINTER(REGFI_NK)
314
315regfi.regfi_nt2unix_time.argtypes = [REGFI_NTTIME]
316regfi.regfi_nt2unix_time.restype = c_double
317
318regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE)]
319regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
320
321regfi.regfi_iterator_free.argtypes = [POINTER(REGFI_ITERATOR)]
322regfi.regfi_iterator_free.restype = None
323
324regfi.regfi_iterator_down.argtypes = [POINTER(REGFI_ITERATOR)]
325regfi.regfi_iterator_down.restype = c_bool
326
327regfi.regfi_iterator_up.argtypes = [POINTER(REGFI_ITERATOR)]
328regfi.regfi_iterator_up.restype = c_bool
329
330regfi.regfi_iterator_to_root.argtypes = [POINTER(REGFI_ITERATOR)]
331regfi.regfi_iterator_to_root.restype = c_bool
332
333regfi.regfi_iterator_descend.argtypes = [POINTER(REGFI_ITERATOR), POINTER(c_char_p)]
334regfi.regfi_iterator_descend.restype = c_bool
335
336regfi.regfi_iterator_cur_key.argtypes = [POINTER(REGFI_ITERATOR)]
337regfi.regfi_iterator_cur_key.restype = POINTER(REGFI_NK)
338
339regfi.regfi_iterator_first_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
340regfi.regfi_iterator_first_subkey.restype = c_bool
341
342regfi.regfi_iterator_cur_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
343regfi.regfi_iterator_cur_subkey.restype = POINTER(REGFI_NK)
344
345regfi.regfi_iterator_next_subkey.argtypes = [POINTER(REGFI_ITERATOR)]
346regfi.regfi_iterator_next_subkey.restype = c_bool
347
348regfi.regfi_iterator_find_subkey.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
349regfi.regfi_iterator_find_subkey.restype = c_bool
350
351regfi.regfi_iterator_first_value.argtypes = [POINTER(REGFI_ITERATOR)]
352regfi.regfi_iterator_first_value.restype = c_bool
353
354regfi.regfi_iterator_cur_value.argtypes = [POINTER(REGFI_ITERATOR)]
355regfi.regfi_iterator_cur_value.restype = POINTER(REGFI_VK)
356
357regfi.regfi_iterator_next_value.argtypes = [POINTER(REGFI_ITERATOR)]
358regfi.regfi_iterator_next_value.restype = c_bool
359
360regfi.regfi_iterator_find_value.argtypes = [POINTER(REGFI_ITERATOR), c_char_p]
361regfi.regfi_iterator_find_value.restype = c_bool
362
363regfi.regfi_iterator_ancestry.argtypes = [POINTER(REGFI_ITERATOR)]
364regfi.regfi_iterator_ancestry.restype = POINTER(POINTER(REGFI_NK))
365
366regfi.regfi_init.argtypes = []
367regfi.regfi_init.restype = None
368regfi.regfi_init()
Note: See TracBrowser for help on using the repository browser.