source: trunk/python2/regfi/regfi.c @ 202

Last change on this file since 202 was 202, checked in by tim, 14 years ago

began implementing independent python subkey and value iterators

File size: 9.7 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_REC* 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
193
194static int TreeIterator_down(TreeIterator self) 
195{
196  int result = regfi_iterator_down(self->iter);
197  regfi_iterator_first_subkey(self->iter);
198  regfi_iterator_first_value(self->iter);
199  return result;
200}
201
202static int TreeIterator_up(TreeIterator self) 
203{
204  return regfi_iterator_up(self->iter);
205}
206
207/*
208static ValueIterator TreeIterator_list_values(TreeIterator self)
209{
210  return CONSTRUCT(ValueIterator, ValueIterator, Con, NULL, self);
211}
212*/
213
214VIRTUAL(TreeIterator, Object) {
215  VMETHOD(Con) = TreeIterator_Con;
216  VMETHOD(iternext) = TreeIterator_next;
217  VMETHOD(down) = TreeIterator_down;
218  VMETHOD(up) = TreeIterator_up;
219  VMETHOD(__iter__) = TreeIterator__iter__;
220  /*  VMETHOD(list_values) = TreeIterator_list_values;*/
221} END_VIRTUAL
222
223
224
225static int SubkeyIterator_dest(void *self) 
226{
227  SubkeyIterator this = (SubkeyIterator)self;
228
229  talloc_unlink(this, (void*)this->list);
230
231  return 0;
232}
233
234static SubkeyIterator SubkeyIterator_Con(SubkeyIterator self, 
235                                         struct RegistryFile_t* file, 
236                                         REGFI_NK_REC* key)
237{
238  /* XXX: add a talloc reference? */
239  self->file = file;
240
241  /* Add a reference to the list */
242  self->list = key->subkeys;
243  talloc_reference(self, self->list);
244
245  self->cur = 0;
246  talloc_set_destructor((void *)self, SubkeyIterator_dest);
247
248  return self;
249}
250
251static void SubkeyIterator__iter__(SubkeyIterator self)
252{
253  return;
254}
255
256static RegistryKey SubkeyIterator_iternext(SubkeyIterator self)
257{
258  const REGFI_NK_REC* nk;
259
260  if(self->cur < self->list->num_keys)
261  {
262    /* XXX: can we switch to UTF-8 and have Python properly import that? */
263    nk = regfi_load_key(self->file->reg, 
264                        self->list->elements[self->cur].offset+REGFI_REGF_SIZE,
265                        REGFI_ENCODING_ASCII, true);
266    self->cur++;
267    return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file, nk);
268  }
269
270  return NULL;
271}
272
273VIRTUAL(SubkeyIterator, Object) {
274  VMETHOD(Con) = SubkeyIterator_Con;
275  VMETHOD(__iter__) = SubkeyIterator__iter__;
276  VMETHOD(iternext) = SubkeyIterator_iternext;
277} END_VIRTUAL
278
279
280
281static int ValueIterator_dest(void *self) 
282{
283  ValueIterator this = (ValueIterator)self;
284
285  if(this->list != NULL)
286    talloc_unlink(this, (void*)this->list);
287
288  return 0;
289}
290
291static ValueIterator ValueIterator_Con(ValueIterator self,
292                                       struct RegistryFile_t* file, 
293                                       REGFI_NK_REC* key)
294{
295  /* XXX: add a talloc reference? */
296  self->file = file;
297  self->cur = 0;
298
299  /* Add a reference to the list */
300  self->list = key->values;
301  if(self->list != NULL)
302    talloc_reference(self, self->list);
303
304  talloc_set_destructor((void *)self, ValueIterator_dest);
305
306  return self;
307}
308
309static void ValueIterator__iter__(ValueIterator self)
310{
311  return;
312}
313
314static REGFI_VK_REC* ValueIterator_iternext(ValueIterator self)
315{
316  const REGFI_VK_REC* vk;
317
318  if(self->list != NULL && self->cur < self->list->num_values)
319  {
320    /* XXX: can we switch to UTF-8 and have Python properly import that? */
321    vk = regfi_load_value(self->file->reg, 
322                          self->list->elements[self->cur]+REGFI_REGF_SIZE,
323                          REGFI_ENCODING_ASCII, true);
324    self->cur++;
325    /*return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, vk);    */
326    return vk; 
327  }
328
329  return NULL;
330
331
332  /* XXX: shouldn't parse data here every time we walk over a value. 
333   *      Instead, make data fetching a method and parse it then.
334   */
335  /*
336  data = (REGFI_DATA *)regfi_iterator_fetch_data(self->iter, rec);
337  if(!data) {
338    RaiseError(ERuntimeError, "Unable to fetch data: %s", regfi_log_get_str());
339    goto error;
340  }
341
342  switch(rec->type) {
343  case REG_EXPAND_SZ:
344  case REG_SZ:
345    result = (RawData)CONSTRUCT(DataString, RawData, Con, NULL, data, rec);
346    break;
347
348  case REG_DWORD:
349    result = (RawData)CONSTRUCT(DWORDData, RawData, Con, NULL, data, rec);
350    break;
351
352  case REG_BINARY:
353  default:
354    result = (RawData)CONSTRUCT(RawData, RawData, Con, NULL, data, rec);
355    break;
356  }
357
358  return result;
359 error:
360  talloc_free(self);
361  return NULL;
362  */
363}
364
365VIRTUAL(ValueIterator, Object) {
366  VMETHOD(Con) = ValueIterator_Con;
367  VMETHOD(__iter__) = ValueIterator__iter__;
368  VMETHOD(iternext) = ValueIterator_iternext;
369} END_VIRTUAL
370
371
372
373static int RawData_dest(void *self)
374{
375  RawData this = (RawData)self;
376
377  if(this->data) {
378    regfi_free_record(this->data);
379  };
380
381  if(this->rec) {
382    regfi_free_record(this->rec);
383  };
384
385  return 0;
386}
387
388static RawData RawData_Con(RawData self, REGFI_DATA *data, REGFI_VK_REC *record)
389{
390  self->rec = record;
391  self->data = data;
392
393  talloc_set_destructor((void *)self, RawData_dest);
394
395  return self;
396}
397
398static int RawData_get_value(RawData self, char *buff, int len)
399{
400  int available_to_read = min(len, self->data->interpreted_size);
401
402  memcpy(buff, self->data->raw, available_to_read);
403
404  return available_to_read;
405}
406
407VIRTUAL(RawData, Object) {
408  VMETHOD(Con) = RawData_Con;
409  VMETHOD(get_value) = RawData_get_value;
410} END_VIRTUAL
411
412static char* DataString_get_value(DataString self)
413{
414  RawData this = (RawData)self;
415
416  return (char*)this->data->interpreted.string;
417}
418
419VIRTUAL(DataString, RawData) {
420  VMETHOD(get_value) = DataString_get_value;
421} END_VIRTUAL
422
423static uint64_t DWORDData_get_value(DWORDData self)
424{
425  RawData this = (RawData)self;
426
427  return this->data->interpreted.dword;
428}
429
430VIRTUAL(DWORDData, RawData) {
431  VMETHOD(get_value) = DWORDData_get_value;
432} END_VIRTUAL
433
434void pyregfi_init()
435{
436  INIT_CLASS(RegistryFile);
437}
Note: See TracBrowser for help on using the repository browser.