source: trunk/python/experimental/regfi/regfi.c@ 245

Last change on this file since 245 was 204, checked in by tim, 15 years ago

reorganizing wrappers

File size: 9.9 KB
Line 
1/*
2 * pyregfi/libregfi glue code
3 *
4 * Copyright (C) 2010 Michael I. Cohen
5 * Copyright (C) 2010 Timothy D. Morgan
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * $Id: $
21 */
22
23#include "pyregfi.h"
24
25static int RegistryFile_dest(void *self)
26{
27 RegistryFile this = (RegistryFile)self;
28
29 regfi_free(this->reg);
30 close(this->fd);
31
32 return 0;
33}
34
35static RegistryFile RegistryFile_Con(RegistryFile self, char *filename)
36{
37 self->fd = open(filename, O_RDONLY);
38 if(self->fd < 0)
39 {
40 RaiseError(EIOError, "Unable to open %s", filename);
41 goto error;
42 }
43
44 self->reg = regfi_alloc(self->fd);
45
46 if(!self->reg)
47 {
48 RaiseError(ERuntimeError, "REGFI Error: %s", regfi_log_get_str());
49 /*char* e = regfi_log_get_str();*/
50 /*fprintf(stderr, "%p\n", e);*/
51 goto error;
52 }
53
54 talloc_set_destructor((void *)self, RegistryFile_dest);
55 return self;
56
57 error:
58 talloc_free(self);
59 return NULL;
60}
61
62static TreeIterator RegistryFile_TreeIterator(RegistryFile self, char **path, REGFI_ENCODING encoding)
63{
64 return CONSTRUCT(TreeIterator, TreeIterator, Con, NULL, self, path, encoding);
65}
66
67
68VIRTUAL(RegistryFile, Object) {
69 VMETHOD(Con) = RegistryFile_Con;
70 VMETHOD(TreeIterator) = RegistryFile_TreeIterator;
71} END_VIRTUAL
72
73
74static int RegistryKey_dest(void *self)
75{
76 RegistryKey this = (RegistryKey)self;
77
78 talloc_unlink(this, (void*)this->key);
79
80 return 0;
81}
82
83static RegistryKey RegistryKey_Con(RegistryKey self,
84 RegistryFile file, REGFI_NK* base_key)
85{
86 if(base_key == NULL)
87 goto error;
88
89 self->key = base_key;
90 self->file = file;
91 talloc_reference(self, self->key);
92 talloc_set_destructor((void *)self, RegistryKey_dest);
93
94 return self;
95
96 error:
97 talloc_free(self);
98 return NULL;
99}
100
101/* XXX: would be nice to change this into a property, rather than a function,
102 * but that would require a custom __getattr__. Can that be done? */
103static SubkeyIterator RegistryKey_subkeys(RegistryKey self)
104{
105 return CONSTRUCT(SubkeyIterator, SubkeyIterator, Con, NULL, self->file, self->key);
106}
107
108/* XXX: would be nice to change this into a property, rather than a function,
109 * but that would require a custom __getattr__. Can that be done? */
110static SubkeyIterator RegistryKey_values(RegistryKey self)
111{
112 return CONSTRUCT(ValueIterator, ValueIterator, Con, NULL, self->file, self->key);
113}
114
115
116VIRTUAL(RegistryKey, Object) {
117 VMETHOD(Con) = RegistryKey_Con;
118 VMETHOD(subkeys) = RegistryKey_subkeys;
119 VMETHOD(values) = RegistryKey_values;
120} END_VIRTUAL
121
122
123static int TreeIterator_dest(void *self)
124{
125 TreeIterator this = (TreeIterator)self;
126
127 regfi_iterator_free(this->iter);
128 return 0;
129}
130
131static TreeIterator TreeIterator_Con(TreeIterator self,
132 RegistryFile file,
133 char **path,
134 REGFI_ENCODING encoding)
135{
136 self->iter = regfi_iterator_new(file->reg, encoding);
137 self->file = file;
138
139 if(!self->iter)
140 {
141 RaiseError(ERuntimeError, "Error: %s", regfi_log_get_str());
142 goto error;
143 }
144
145 talloc_set_destructor((void*)self, TreeIterator_dest);
146
147 /* Traverse to the path */
148 if(path[0])
149 {
150 if(!regfi_iterator_walk_path(self->iter, (const char **)path))
151 {
152 RaiseError(ERuntimeError, "Unable to walk down key path");
153 goto error;
154 }
155 }
156
157 self->root_traversed = false;
158
159 return self;
160 error:
161 return NULL;
162}
163
164static void TreeIterator__iter__(TreeIterator self)
165{
166 return;
167}
168
169
170static RegistryKey TreeIterator_next(TreeIterator self)
171{
172 if(!self->root_traversed)
173 self->root_traversed = true;
174 else if(!regfi_iterator_down(self->iter))
175 {
176 do
177 {
178 if(!regfi_iterator_up(self->iter))
179 return NULL;
180 } while(!regfi_iterator_next_subkey(self->iter));
181
182 /* XXX: This is an error condition.
183 * Probably should throw an exception or something. */
184 if(!regfi_iterator_down(self->iter))
185 return NULL;
186 }
187
188 regfi_iterator_first_subkey(self->iter);
189 return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file,
190 regfi_iterator_cur_key(self->iter));
191}
192
193static int TreeIterator_down(TreeIterator self)
194{
195 int result = regfi_iterator_down(self->iter);
196 regfi_iterator_first_subkey(self->iter);
197 regfi_iterator_first_value(self->iter);
198 return result;
199}
200
201static int TreeIterator_up(TreeIterator self)
202{
203 return regfi_iterator_up(self->iter);
204}
205
206static RegistryKey TreeIterator_current(TreeIterator self)
207{
208 return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file,
209 regfi_iterator_cur_key(self->iter));
210}
211
212static int TreeIterator_to_root(TreeIterator self)
213{
214 return regfi_iterator_to_root(self->iter);
215}
216
217
218VIRTUAL(TreeIterator, Object) {
219 VMETHOD(Con) = TreeIterator_Con;
220 VMETHOD(iternext) = TreeIterator_next;
221 VMETHOD(down) = TreeIterator_down;
222 VMETHOD(up) = TreeIterator_up;
223 VMETHOD(current) = TreeIterator_current;
224 VMETHOD(to_root) = TreeIterator_to_root;
225 VMETHOD(__iter__) = TreeIterator__iter__;
226 /* VMETHOD(list_values) = TreeIterator_list_values;*/
227} END_VIRTUAL
228
229
230
231static int SubkeyIterator_dest(void *self)
232{
233 SubkeyIterator this = (SubkeyIterator)self;
234
235 talloc_unlink(this, (void*)this->list);
236
237 return 0;
238}
239
240static SubkeyIterator SubkeyIterator_Con(SubkeyIterator self,
241 struct RegistryFile_t* file,
242 REGFI_NK* key)
243{
244 /* XXX: add a talloc reference? */
245 self->file = file;
246
247 /* Add a reference to the list */
248 self->list = key->subkeys;
249 talloc_reference(self, self->list);
250
251 self->cur = 0;
252 talloc_set_destructor((void *)self, SubkeyIterator_dest);
253
254 return self;
255}
256
257static void SubkeyIterator__iter__(SubkeyIterator self)
258{
259 return;
260}
261
262static RegistryKey SubkeyIterator_iternext(SubkeyIterator self)
263{
264 const REGFI_NK* nk;
265
266 if(self->list != NULL && self->cur < self->list->num_keys)
267 {
268 /* XXX: can we switch to UTF-8 and have Python properly import that? */
269 nk = regfi_load_key(self->file->reg,
270 self->list->elements[self->cur].offset+REGFI_REGF_SIZE,
271 REGFI_ENCODING_ASCII, true);
272 self->cur++;
273 return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file, nk);
274 }
275
276 return NULL;
277}
278
279VIRTUAL(SubkeyIterator, Object) {
280 VMETHOD(Con) = SubkeyIterator_Con;
281 VMETHOD(__iter__) = SubkeyIterator__iter__;
282 VMETHOD(iternext) = SubkeyIterator_iternext;
283} END_VIRTUAL
284
285
286
287static int ValueIterator_dest(void *self)
288{
289 ValueIterator this = (ValueIterator)self;
290
291 if(this->list != NULL)
292 talloc_unlink(this, (void*)this->list);
293
294 return 0;
295}
296
297static ValueIterator ValueIterator_Con(ValueIterator self,
298 struct RegistryFile_t* file,
299 REGFI_NK* key)
300{
301 /* XXX: add a talloc reference? */
302 self->file = file;
303 self->cur = 0;
304
305 /* Add a reference to the list */
306 self->list = key->values;
307 if(self->list != NULL)
308 talloc_reference(self, self->list);
309
310 talloc_set_destructor((void *)self, ValueIterator_dest);
311
312 return self;
313}
314
315static void ValueIterator__iter__(ValueIterator self)
316{
317 return;
318}
319
320static REGFI_VK* ValueIterator_iternext(ValueIterator self)
321{
322 const REGFI_VK* vk;
323
324 if(self->list != NULL && self->cur < self->list->num_values)
325 {
326 /* XXX: can we switch to UTF-8 and have Python properly import that? */
327 vk = regfi_load_value(self->file->reg,
328 self->list->elements[self->cur]+REGFI_REGF_SIZE,
329 REGFI_ENCODING_ASCII, true);
330 self->cur++;
331 /*return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, vk); */
332 return vk;
333 }
334
335 return NULL;
336
337
338 /* XXX: shouldn't parse data here every time we walk over a value.
339 * Instead, make data fetching a method and parse it then.
340 */
341 /*
342 data = (REGFI_DATA *)regfi_iterator_fetch_data(self->iter, rec);
343 if(!data) {
344 RaiseError(ERuntimeError, "Unable to fetch data: %s", regfi_log_get_str());
345 goto error;
346 }
347
348 switch(rec->type) {
349 case REG_EXPAND_SZ:
350 case REG_SZ:
351 result = (RawData)CONSTRUCT(DataString, RawData, Con, NULL, data, rec);
352 break;
353
354 case REG_DWORD:
355 result = (RawData)CONSTRUCT(DWORDData, RawData, Con, NULL, data, rec);
356 break;
357
358 case REG_BINARY:
359 default:
360 result = (RawData)CONSTRUCT(RawData, RawData, Con, NULL, data, rec);
361 break;
362 }
363
364 return result;
365 error:
366 talloc_free(self);
367 return NULL;
368 */
369}
370
371VIRTUAL(ValueIterator, Object) {
372 VMETHOD(Con) = ValueIterator_Con;
373 VMETHOD(__iter__) = ValueIterator__iter__;
374 VMETHOD(iternext) = ValueIterator_iternext;
375} END_VIRTUAL
376
377
378
379static int RawData_dest(void *self)
380{
381 RawData this = (RawData)self;
382
383 if(this->data) {
384 regfi_free_record(this->data);
385 };
386
387 if(this->rec) {
388 regfi_free_record(this->rec);
389 };
390
391 return 0;
392}
393
394static RawData RawData_Con(RawData self, REGFI_DATA *data, REGFI_VK *record)
395{
396 self->rec = record;
397 self->data = data;
398
399 talloc_set_destructor((void *)self, RawData_dest);
400
401 return self;
402}
403
404static int RawData_get_value(RawData self, char *buff, int len)
405{
406 int available_to_read = min(len, self->data->interpreted_size);
407
408 memcpy(buff, self->data->raw, available_to_read);
409
410 return available_to_read;
411}
412
413VIRTUAL(RawData, Object) {
414 VMETHOD(Con) = RawData_Con;
415 VMETHOD(get_value) = RawData_get_value;
416} END_VIRTUAL
417
418static char* DataString_get_value(DataString self)
419{
420 RawData this = (RawData)self;
421
422 return (char*)this->data->interpreted.string;
423}
424
425VIRTUAL(DataString, RawData) {
426 VMETHOD(get_value) = DataString_get_value;
427} END_VIRTUAL
428
429static uint64_t DWORDData_get_value(DWORDData self)
430{
431 RawData this = (RawData)self;
432
433 return this->data->interpreted.dword;
434}
435
436VIRTUAL(DWORDData, RawData) {
437 VMETHOD(get_value) = DWORDData_get_value;
438} END_VIRTUAL
439
440void pyregfi_init()
441{
442 INIT_CLASS(RegistryFile);
443}
Note: See TracBrowser for help on using the repository browser.