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

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

misc fixes

stripped _REC from some data type names

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.