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

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

reorganizing wrappers

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.