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
RevLine 
[196]1/*
[202]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 */
[196]22
23#include "pyregfi.h"
24
[202]25static int RegistryFile_dest(void *self) 
26{
[196]27  RegistryFile this = (RegistryFile)self;
28
29  regfi_free(this->reg);
30  close(this->fd);
31
32  return 0;
[198]33}
[196]34
[202]35static RegistryFile RegistryFile_Con(RegistryFile self, char *filename) 
36{
[196]37  self->fd = open(filename, O_RDONLY);
[202]38  if(self->fd < 0) 
39  {
[196]40    RaiseError(EIOError, "Unable to open %s", filename);
41    goto error;
[198]42  }
[196]43
44  self->reg = regfi_alloc(self->fd);
45
[202]46  if(!self->reg) 
47  {
[200]48    RaiseError(ERuntimeError, "REGFI Error: %s", regfi_log_get_str());
[198]49    /*char* e = regfi_log_get_str();*/
50    /*fprintf(stderr, "%p\n", e);*/
[196]51    goto error;
[198]52  }
[196]53
54  talloc_set_destructor((void *)self, RegistryFile_dest);
55  return self;
56
57 error:
58  talloc_free(self);
59  return NULL;
[198]60}
[196]61
[202]62static TreeIterator RegistryFile_TreeIterator(RegistryFile self, char **path, REGFI_ENCODING encoding) 
63{
64  return CONSTRUCT(TreeIterator, TreeIterator, Con, NULL, self, path, encoding);
[198]65}
[196]66
67
68VIRTUAL(RegistryFile, Object) {
69  VMETHOD(Con) = RegistryFile_Con;
[202]70  VMETHOD(TreeIterator) = RegistryFile_TreeIterator;
[196]71} END_VIRTUAL
72
73
[202]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
[196]127  regfi_iterator_free(this->iter);
128  return 0;
[198]129}
[196]130
[202]131static TreeIterator TreeIterator_Con(TreeIterator self, 
132                                     RegistryFile file, 
133                                     char **path,
134                                     REGFI_ENCODING encoding)
[200]135{
[196]136  self->iter = regfi_iterator_new(file->reg, encoding);
[202]137  self->file = file;
[196]138
[202]139  if(!self->iter) 
140  {
[196]141    RaiseError(ERuntimeError, "Error: %s", regfi_log_get_str());
142    goto error;
[198]143  }
[196]144
[202]145  talloc_set_destructor((void*)self, TreeIterator_dest);
[196]146
[199]147  /* Traverse to the path */
[202]148  if(path[0]) 
149  {
150    if(!regfi_iterator_walk_path(self->iter, (const char **)path)) 
151    {
[196]152      RaiseError(ERuntimeError, "Unable to walk down key path");
153      goto error;
[198]154    }
155  }
[196]156
[200]157  self->root_traversed = false;
[196]158
159  return self;
160 error:
161  return NULL;
[198]162}
[196]163
[202]164static void TreeIterator__iter__(TreeIterator self) 
[200]165{
166  return;
[198]167}
[196]168
[199]169
[202]170static RegistryKey TreeIterator_next(TreeIterator self)
[200]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));
[196]181
[200]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  }
[196]187
[200]188  regfi_iterator_first_subkey(self->iter);
[202]189  return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file,
190                   regfi_iterator_cur_key(self->iter));
[199]191}
[196]192
193
[202]194static int TreeIterator_down(TreeIterator self) 
195{
[199]196  int result = regfi_iterator_down(self->iter);
197  regfi_iterator_first_subkey(self->iter);
198  regfi_iterator_first_value(self->iter);
[196]199  return result;
[198]200}
[196]201
[202]202static int TreeIterator_up(TreeIterator self) 
203{
[199]204  return regfi_iterator_up(self->iter);
205}
206
[202]207/*
208static ValueIterator TreeIterator_list_values(TreeIterator self)
209{
[196]210  return CONSTRUCT(ValueIterator, ValueIterator, Con, NULL, self);
[198]211}
[202]212*/
[196]213
[202]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;*/
[196]221} END_VIRTUAL
222
[202]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{
[196]283  ValueIterator this = (ValueIterator)self;
284
[202]285  if(this->list != NULL)
286    talloc_unlink(this, (void*)this->list);
[196]287
288  return 0;
[198]289}
[196]290
[202]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;
[196]298
[202]299  /* Add a reference to the list */
300  self->list = key->values;
301  if(self->list != NULL)
302    talloc_reference(self, self->list);
303
[196]304  talloc_set_destructor((void *)self, ValueIterator_dest);
305
306  return self;
[198]307}
[196]308
[202]309static void ValueIterator__iter__(ValueIterator self)
310{
[200]311  return;
[198]312}
[196]313
[202]314static REGFI_VK_REC* ValueIterator_iternext(ValueIterator self)
315{
316  const REGFI_VK_REC* vk;
[196]317
[202]318  if(self->list != NULL && self->cur < self->list->num_values)
[199]319  {
[202]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; 
[199]327  }
328
[202]329  return NULL;
[199]330
[200]331
[199]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   */
[200]335  /*
[196]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;
[198]340  }
[196]341
[199]342  switch(rec->type) {
[196]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;
[198]356  }
[196]357
358  return result;
359 error:
360  talloc_free(self);
361  return NULL;
[202]362  */
[198]363}
[196]364
365VIRTUAL(ValueIterator, Object) {
366  VMETHOD(Con) = ValueIterator_Con;
367  VMETHOD(__iter__) = ValueIterator__iter__;
368  VMETHOD(iternext) = ValueIterator_iternext;
369} END_VIRTUAL
370
[202]371
372
373static int RawData_dest(void *self)
374{
[196]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;
[198]386}
[196]387
[202]388static RawData RawData_Con(RawData self, REGFI_DATA *data, REGFI_VK_REC *record)
389{
[196]390  self->rec = record;
391  self->data = data;
392
393  talloc_set_destructor((void *)self, RawData_dest);
394
395  return self;
[198]396}
[196]397
[202]398static int RawData_get_value(RawData self, char *buff, int len)
399{
[196]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;
[198]405}
[196]406
407VIRTUAL(RawData, Object) {
408  VMETHOD(Con) = RawData_Con;
409  VMETHOD(get_value) = RawData_get_value;
410} END_VIRTUAL
411
[202]412static char* DataString_get_value(DataString self)
413{
[196]414  RawData this = (RawData)self;
415
[198]416  return (char*)this->data->interpreted.string;
417}
[196]418
419VIRTUAL(DataString, RawData) {
420  VMETHOD(get_value) = DataString_get_value;
421} END_VIRTUAL
422
[202]423static uint64_t DWORDData_get_value(DWORDData self)
424{
[196]425  RawData this = (RawData)self;
426
427  return this->data->interpreted.dword;
[198]428}
[196]429
430VIRTUAL(DWORDData, RawData) {
431  VMETHOD(get_value) = DWORDData_get_value;
432} END_VIRTUAL
433
[202]434void pyregfi_init()
435{
[196]436  INIT_CLASS(RegistryFile);
[198]437}
Note: See TracBrowser for help on using the repository browser.