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

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

misc fixes

stripped _REC from some data type names

File size: 9.9 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, 
[203]84                                   RegistryFile file, REGFI_NK* base_key)
[202]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
[202]193static int TreeIterator_down(TreeIterator self) 
194{
[199]195  int result = regfi_iterator_down(self->iter);
196  regfi_iterator_first_subkey(self->iter);
197  regfi_iterator_first_value(self->iter);
[196]198  return result;
[198]199}
[196]200
[202]201static int TreeIterator_up(TreeIterator self) 
202{
[199]203  return regfi_iterator_up(self->iter);
204}
205
[203]206static RegistryKey TreeIterator_current(TreeIterator self)
[202]207{
[203]208  return CONSTRUCT(RegistryKey, RegistryKey, Con, NULL, self->file,
209                   regfi_iterator_cur_key(self->iter));
[198]210}
[196]211
[203]212static int TreeIterator_to_root(TreeIterator self)
213{
214  return regfi_iterator_to_root(self->iter);
215}
216
217
[202]218VIRTUAL(TreeIterator, Object) {
219  VMETHOD(Con) = TreeIterator_Con;
220  VMETHOD(iternext) = TreeIterator_next;
221  VMETHOD(down) = TreeIterator_down;
222  VMETHOD(up) = TreeIterator_up;
[203]223  VMETHOD(current) = TreeIterator_current;
224  VMETHOD(to_root) = TreeIterator_to_root;
[202]225  VMETHOD(__iter__) = TreeIterator__iter__;
226  /*  VMETHOD(list_values) = TreeIterator_list_values;*/
[196]227} END_VIRTUAL
228
[202]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, 
[203]242                                         REGFI_NK* key)
[202]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{
[203]264  const REGFI_NK* nk;
[202]265
[203]266  if(self->list != NULL && self->cur < self->list->num_keys)
[202]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{
[196]289  ValueIterator this = (ValueIterator)self;
290
[202]291  if(this->list != NULL)
292    talloc_unlink(this, (void*)this->list);
[196]293
294  return 0;
[198]295}
[196]296
[202]297static ValueIterator ValueIterator_Con(ValueIterator self,
298                                       struct RegistryFile_t* file, 
[203]299                                       REGFI_NK* key)
[202]300{
301  /* XXX: add a talloc reference? */
302  self->file = file;
303  self->cur = 0;
[196]304
[202]305  /* Add a reference to the list */
306  self->list = key->values;
307  if(self->list != NULL)
308    talloc_reference(self, self->list);
309
[196]310  talloc_set_destructor((void *)self, ValueIterator_dest);
311
312  return self;
[198]313}
[196]314
[202]315static void ValueIterator__iter__(ValueIterator self)
316{
[200]317  return;
[198]318}
[196]319
[203]320static REGFI_VK* ValueIterator_iternext(ValueIterator self)
[202]321{
[203]322  const REGFI_VK* vk;
[196]323
[202]324  if(self->list != NULL && self->cur < self->list->num_values)
[199]325  {
[202]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; 
[199]333  }
334
[202]335  return NULL;
[199]336
[200]337
[199]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   */
[200]341  /*
[196]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;
[198]346  }
[196]347
[199]348  switch(rec->type) {
[196]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;
[198]362  }
[196]363
364  return result;
365 error:
366  talloc_free(self);
367  return NULL;
[202]368  */
[198]369}
[196]370
371VIRTUAL(ValueIterator, Object) {
372  VMETHOD(Con) = ValueIterator_Con;
373  VMETHOD(__iter__) = ValueIterator__iter__;
374  VMETHOD(iternext) = ValueIterator_iternext;
375} END_VIRTUAL
376
[202]377
378
379static int RawData_dest(void *self)
380{
[196]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;
[198]392}
[196]393
[203]394static RawData RawData_Con(RawData self, REGFI_DATA *data, REGFI_VK *record)
[202]395{
[196]396  self->rec = record;
397  self->data = data;
398
399  talloc_set_destructor((void *)self, RawData_dest);
400
401  return self;
[198]402}
[196]403
[202]404static int RawData_get_value(RawData self, char *buff, int len)
405{
[196]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;
[198]411}
[196]412
413VIRTUAL(RawData, Object) {
414  VMETHOD(Con) = RawData_Con;
415  VMETHOD(get_value) = RawData_get_value;
416} END_VIRTUAL
417
[202]418static char* DataString_get_value(DataString self)
419{
[196]420  RawData this = (RawData)self;
421
[198]422  return (char*)this->data->interpreted.string;
423}
[196]424
425VIRTUAL(DataString, RawData) {
426  VMETHOD(get_value) = DataString_get_value;
427} END_VIRTUAL
428
[202]429static uint64_t DWORDData_get_value(DWORDData self)
430{
[196]431  RawData this = (RawData)self;
432
433  return this->data->interpreted.dword;
[198]434}
[196]435
436VIRTUAL(DWORDData, RawData) {
437  VMETHOD(get_value) = DWORDData_get_value;
438} END_VIRTUAL
439
[202]440void pyregfi_init()
441{
[196]442  INIT_CLASS(RegistryFile);
[198]443}
Note: See TracBrowser for help on using the repository browser.