Ignore:
Timestamp:
04/18/11 16:25:46 (13 years ago)
Author:
tim
Message:

added a test case for pyregfi multithreaded use
updated the regfi multithreaded test case
fixed several ctypes interface problems in pyregfi
added locking to pyregfi iterators for thread safety
fixed regfi talloc race conditions with an additional lock

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/python/pyregfi/__init__.py

    r227 r228  
    9595import sys
    9696import time
    97 from pyregfi.structures import *
    98 
    9997import ctypes
    10098import ctypes.util
     99import threading
     100from pyregfi.structures import *
     101
    101102
    102103## An enumeration of registry Value data types
     
    218219
    219220
    220 
    221221## Abstract class for most objects returned by the library
    222222class _StructureWrapper(object):
     
    239239    # Memory management for most regfi structures is taken care of here
    240240    def __del__(self):
    241         regfi.regfi_free_record(self._base)
     241        regfi.regfi_free_record(self._hive.file, self._base)
    242242
    243243
     
    299299                            + "Current log:\n" + GetLogMessages())
    300300       
    301         if not regfi.regfi_reference_record(key._base):
     301        if not regfi.regfi_reference_record(key._hive.file, key._base):
    302302            raise Exception("Could not create _GenericList; memory error."
    303303                            + "Current log:\n" + GetLogMessages())
     
    308308   
    309309    def __del__(self):
    310         regfi.regfi_free_record(self._key_base)
    311    
     310        regfi.regfi_free_record(self._hive.file, self._key_base)
     311
    312312
    313313    ## Length of list
     
    486486                ret_val = _buffer2bytearray(cn_struct.raw,
    487487                                            cn_struct.size)
    488             regfi.regfi_free_record(cn_p)
     488            regfi.regfi_free_record(self._hive.file, cn_p)
    489489
    490490        return ret_val
     
    581581                                        data_struct.interpreted_size)
    582582
    583         regfi.regfi_free_record(data_p)
     583        regfi.regfi_free_record(self._hive.file, data_p)
    584584        return ret_val
    585585   
     
    599599        ret_val = _buffer2bytearray(data_struct.raw,
    600600                                    data_struct.size)
    601         regfi.regfi_free_record(data_p)
     601        regfi.regfi_free_record(self._hive.file, data_p)
    602602        return ret_val
    603603
     
    747747    _iter = None
    748748    _iteration_root = None
     749    _lock = None
    749750
    750751    def __init__(self, hive):
    751         self._iter = regfi.regfi_iterator_new(hive.file, REGFI_ENCODING_UTF8)
     752        self._iter = regfi.regfi_iterator_new(hive.file)
    752753        if not self._iter:
    753754            raise Exception("Could not create iterator.  Current log:\n"
    754755                            + GetLogMessages())
    755756        self._hive = hive
    756        
     757        self._lock = threading.RLock()
     758   
    757759    def __getattr__(self, name):
    758         return getattr(self.file.contents, name)
    759 
    760     def __del__(self):   
     760        self._lock.acquire()
     761        ret_val = getattr(self._iter.contents, name)
     762        self._lock.release()
     763        return ret_val
     764
     765    def __del__(self):
     766        self._lock.acquire()
    761767        regfi.regfi_iterator_free(self._iter)
     768        self._lock.release()
    762769
    763770    def __iter__(self):
     771        self._lock.acquire()
    764772        self._iteration_root = None
     773        self._lock.release()
    765774        return self
    766775
    767776    def __next__(self):
     777        self._lock.acquire()
    768778        if self._iteration_root == None:
    769             self._iteration_root = self.current_key()
     779            self._iteration_root = self.current_key().offset
    770780        elif not regfi.regfi_iterator_down(self._iter):
    771781            up_ret = regfi.regfi_iterator_up(self._iter)
    772782            while (up_ret and
    773783                   not regfi.regfi_iterator_next_subkey(self._iter)):
    774                 if self._iteration_root == self.current_key():
     784                if self._iteration_root == self.current_key().offset:
    775785                    self._iteration_root = None
     786                    self._lock.release()
    776787                    raise StopIteration('')
    777788                up_ret = regfi.regfi_iterator_up(self._iter)
     
    779790            if not up_ret:
    780791                self._iteration_root = None
     792                self._lock.release()
    781793                raise StopIteration('')
    782794           
    783795            # XXX: Use non-generic exception
    784796            if not regfi.regfi_iterator_down(self._iter):
     797                self._lock.release()
    785798                raise Exception('Error traversing iterator downward.'+
    786799                                ' Current log:\n'+ GetLogMessages())
    787800
    788801        regfi.regfi_iterator_first_subkey(self._iter)
    789         return self.current_key()
     802        ret_val = self.current_key()
     803        self._lock.release()
     804
     805        return ret_val
     806
    790807
    791808    # For Python 2.x
     
    806823    # @return True if successful, False otherwise
    807824    def down(self, subkey_name=None):
     825        ret_val = None
    808826        if subkey_name == None:
    809             return regfi.regfi_iterator_down(self._iter)
     827            self._lock.acquire()
     828            ret_val = regfi.regfi_iterator_down(self._iter)
    810829        else:
    811830            if name != None:
    812831                name = name.encode('utf-8')
    813             return (regfi.regfi_iterator_find_subkey(self._iter, name)
    814                     and regfi.regfi_iterator_down(self._iter))
     832            self._lock.acquire()
     833            ret_val = (regfi.regfi_iterator_find_subkey(self._iter, name)
     834                       and regfi.regfi_iterator_down(self._iter))
     835       
     836        self._lock.release()
     837        return ret_val
    815838
    816839
     
    824847    #       default selections.
    825848    def up(self):
    826         return regfi.regfi_iterator_up(self._iter)
     849        self._lock.acquire()
     850        ret_val = regfi.regfi_iterator_up(self._iter)
     851        self._lock.release()
     852        return ret_val
    827853
    828854
     
    832858    #         None on error or if the current key has no subkeys.
    833859    def first_subkey(self):
     860        ret_val = None
     861        self._lock.acquire()
    834862        if regfi.regfi_iterator_first_subkey(self._iter):
    835             return self.current_subkey()
    836         return None
     863            ret_val = self.current_subkey()
     864        self._lock.release()
     865        return ret_val
    837866
    838867
     
    842871    #         None on error or if the current key has no values.
    843872    def first_value(self):
     873        ret_val = None
     874        self._lock.acquire()
    844875        if regfi.regfi_iterator_first_value(self._iter):
    845             return self.current_value()
    846         return None
     876            ret_val = self.current_value()
     877        self._lock.release()
     878        return ret_val
    847879
    848880
     
    852884    #         None if there are no remaining subkeys or an error occurred.
    853885    def next_subkey(self):
     886        ret_val = None
     887        self._lock.acquire()
    854888        if regfi.regfi_iterator_next_subkey(self._iter):
    855             return self.current_subkey()
    856         return None
     889            ret_val = self.current_subkey()
     890        self._lock.release()
     891        return ret_val
    857892
    858893
     
    862897    #         None if there are no remaining values or an error occurred.
    863898    def next_value(self):
     899        ret_val = None
     900        self._lock.acquire()
    864901        if regfi.regfi_iterator_next_value(self._iter):
    865             return self.current_value()
    866         return None
     902            ret_val = self.current_value()
     903        self._lock.release()
     904        return ret_val
    867905
    868906
     
    874912        if name != None:
    875913            name = name.encode('utf-8')
     914        ret_val = None
     915        self._lock.acquire()
    876916        if regfi.regfi_iterator_find_subkey(self._iter, name):
    877             return self.current_subkey()
    878         return None
     917            ret_val = self.current_subkey()
     918        self._lock.release()
     919        return ret_val
    879920
    880921
     
    886927        if name != None:
    887928            name = name.encode('utf-8')
     929        ret_val = None
     930        self._lock.acquire()
    888931        if regfi.regfi_iterator_find_value(self._iter, name):
    889             return self.current_value()
    890         return None
     932            ret_val = self.current_value()
     933        self._lock.release()
     934        return ret_val
    891935
    892936    ## Retrieves the currently selected subkey
     
    894938    # @return A Key instance of the current subkey
    895939    def current_subkey(self):
    896         return Key(self._hive, regfi.regfi_iterator_cur_subkey(self._iter))
     940        self._lock.acquire()
     941        ret_val = Key(self._hive, regfi.regfi_iterator_cur_subkey(self._iter))
     942        self._lock.release()
     943        return ret_val
    897944
    898945    ## Retrieves the currently selected value
     
    900947    # @return A Value instance of the current value
    901948    def current_value(self):
    902         return Value(self._hive, regfi.regfi_iterator_cur_value(self._iter))
     949        self._lock.acquire()
     950        ret_val = Value(self._hive, regfi.regfi_iterator_cur_value(self._iter))
     951        self._lock.release()
     952        return ret_val
    903953
    904954    ## Retrieves the current key
     
    906956    # @return A Key instance of the current position of the iterator
    907957    def current_key(self):
    908         return Key(self._hive, regfi.regfi_iterator_cur_key(self._iter))
     958        self._lock.acquire()
     959        ret_val = Key(self._hive, regfi.regfi_iterator_cur_key(self._iter))
     960        self._lock.release()
     961        return ret_val
    909962
    910963
     
    919972        cpath = _strlist2charss(path)
    920973
    921         # XXX: Use non-generic exception
    922         if not regfi.regfi_iterator_walk_path(self._iter, cpath):
     974        self._lock.acquire()
     975        result = regfi.regfi_iterator_walk_path(self._iter, cpath)
     976        self._lock.release()
     977        if not result:
     978            # XXX: Use non-generic exception
    923979            raise Exception('Could not locate path.\n'+GetLogMessages())
    924980
Note: See TracChangeset for help on using the changeset viewer.