Changeset 207


Ignore:
Timestamp:
09/06/10 23:03:36 (14 years ago)
Author:
tim
Message:

reworked regfi API to accomodate more convenient subkey/value searches without an iterator.

continued implementation on pyregfi

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/regfi.h

    r206 r207  
    963963
    964964
     965/** Retrieves number of subkeys referenced by this key.
     966 *
     967 * Number of subkeyss in key structure and subkey list structure could differ,
     968 * so this provides a standard/sane way of determining the number.
     969 *
     970 * @param key  the key whose number of subkeys is desired
     971 *
     972 * @return Returns the number of subkeys referenced by this key.
     973 *
     974 * @ingroup regfiBase
     975 */
     976_EXPORT
     977uint32_t regfi_fetch_num_subkeys(const REGFI_NK* key);
     978
     979
     980/** Retrieves number of values referenced by this key.
     981 *
     982 * Number of values in key structure and value list structure could differ,
     983 * so this provides a standard/sane way of determining the number.
     984 *
     985 * @param key  the key whose number of values is desired
     986 *
     987 * @return Returns the number of values referenced by this key.
     988 *
     989 * @ingroup regfiBase
     990 */
     991_EXPORT
     992uint32_t regfi_fetch_num_values(const REGFI_NK* key);
     993
     994
    965995/** Retrieves classname for a given key.
    966996 *
     
    10041034const REGFI_DATA* regfi_fetch_data(REGFI_FILE* file,
    10051035                                   const REGFI_VK* value);
     1036
     1037
     1038/** Locates a specific subkey of a given key.
     1039 *
     1040 * @param file  the file from which key is derived
     1041 * @param key   the key whose subkey is desired
     1042 * @param name  name of the desired subkey
     1043 * @param index a return value: the index of the desired subkey.
     1044 *              undefined on error
     1045 *
     1046 * @return true if the subkey is found, false if an error occurred or if the
     1047 *         specified name could not be found. If an error occurs, messages
     1048 *         will be written explaining the issue. (See regfi_log_get_str.)
     1049 *
     1050 * @ingroup regfiBase
     1051 */
     1052_EXPORT
     1053bool regfi_find_subkey(REGFI_FILE* file, const REGFI_NK* key,
     1054                       const char* name, uint32_t* index);
     1055
     1056
     1057/** Locates a specific value of a given key.
     1058 *
     1059 * @param file  the file from which key is derived
     1060 * @param key   the key whose value is desired
     1061 * @param name  name of the desired value
     1062 * @param index a return value: the index of the desired value. 
     1063 *              undefined on error
     1064 *
     1065 * @return true if the value is found, false if an error occurred or if the
     1066 *         specified name could not be found. If an error occurs, messages
     1067 *         will be written explaining the issue. (See regfi_log_get_str.)
     1068 *
     1069 * @ingroup regfiBase
     1070 */
     1071_EXPORT
     1072bool regfi_find_value(REGFI_FILE* file, const REGFI_NK* key,
     1073                      const char* name, uint32_t* index);
     1074
     1075
     1076/** Retrieves a specific subkey of a given key.
     1077 *
     1078 * @param file  the file from which key is derived
     1079 * @param key   the key whose subkey is desired
     1080 * @param index the index of the desired subkey
     1081 *
     1082 * @return the requested subkey or NULL on error.
     1083 *
     1084 * @ingroup regfiBase
     1085 */
     1086_EXPORT
     1087const REGFI_NK* regfi_get_subkey(REGFI_FILE* file, const REGFI_NK* key,
     1088                                 uint32_t index);
     1089
     1090
     1091/** Retrieves a specific value of a given key.
     1092 *
     1093 * @param file  the file from which key is derived
     1094 * @param key   the key whose value is desired
     1095 * @param index the index of the desired value
     1096 *
     1097 * @return the requested value or NULL on error.
     1098 *
     1099 * @ingroup regfiBase
     1100 */
     1101_EXPORT
     1102const REGFI_VK* regfi_get_value(REGFI_FILE* file, const REGFI_NK* key,
     1103                                uint32_t index);
     1104
    10061105
    10071106
     
    11661265/** Searches for a subkey with a given name under the current key.
    11671266 *
    1168  * @param i           the iterator
    1169  * @param subkey_name subkey name to search for
     1267 * @param i     the iterator
     1268 * @param name subkey name to search for
    11701269 *
    11711270 * @return True if such a subkey was found, false otherwise.  If a subkey is
     
    11761275 */
    11771276_EXPORT
    1178 bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* subkey_name);
     1277bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* name);
    11791278
    11801279
     
    12201319/** Searches for a value with a given name under the current key.
    12211320 *
    1222  * @param i          the iterator
    1223  * @param value_name value name to search for
     1321 * @param i     the iterator
     1322 * @param name value name to search for
    12241323 *
    12251324 * @return True if such a value was found, false otherwise.  If a value is
     
    12301329 */
    12311330_EXPORT
    1232 bool regfi_iterator_find_value(REGFI_ITERATOR* i,
    1233                                const char* value_name);
     1331bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* name);
    12341332
    12351333
  • trunk/lib/regfi.c

    r206 r207  
    17211721
    17221722
     1723
     1724/******************************************************************************
     1725 *****************************************************************************/
     1726uint32_t regfi_fetch_num_subkeys(const REGFI_NK* key)
     1727{
     1728  uint32_t num_in_list = 0;
     1729  if(key->subkeys != NULL)
     1730    num_in_list = key->subkeys->num_keys;
     1731
     1732  if(num_in_list != key->num_subkeys)
     1733  {
     1734    regfi_log_add(REGFI_LOG_INFO, "Key at offset 0x%.8X contains %d keys in its"
     1735                  " subkey list but reports %d should be available.",
     1736                  key->offset, num_in_list, key->num_subkeys);
     1737    return (num_in_list < key->num_subkeys)?num_in_list:key->num_subkeys;
     1738  }
     1739 
     1740  return num_in_list;
     1741}
     1742
     1743
     1744/******************************************************************************
     1745 *****************************************************************************/
     1746uint32_t regfi_fetch_num_values(const REGFI_NK* key)
     1747{
     1748  uint32_t num_in_list = 0;
     1749  if(key->values != NULL)
     1750    num_in_list = key->values->num_values;
     1751
     1752  if(num_in_list != key->num_values)
     1753  {
     1754    regfi_log_add(REGFI_LOG_INFO, "Key at offset 0x%.8X contains %d values in"
     1755                  " its value list but reports %d should be available.",
     1756                  key->offset, num_in_list, key->num_values);
     1757    return (num_in_list < key->num_values)?num_in_list:key->num_values;
     1758  }
     1759 
     1760  return num_in_list;
     1761}
     1762
     1763
    17231764/******************************************************************************
    17241765 *****************************************************************************/
     
    18361877/******************************************************************************
    18371878 *****************************************************************************/
    1838 bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* subkey_name)
    1839 {
    1840   REGFI_NK* subkey;
    1841   bool found = false;
    1842   uint32_t old_subkey = i->cur_subkey;
    1843 
    1844   if(subkey_name == NULL)
    1845     return false;
    1846 
    1847   /* XXX: this alloc/free of each sub key might be a bit excessive */
    1848   regfi_iterator_first_subkey(i);
    1849   while((subkey = regfi_iterator_cur_subkey(i)) != NULL && (found == false))
    1850   {
    1851     if(subkey->name != NULL
    1852        && strcasecmp(subkey->name, subkey_name) == 0)
    1853       found = true;
    1854     else
    1855     {
    1856       talloc_unlink(NULL, subkey);
    1857       regfi_iterator_next_subkey(i);
    1858     }
    1859   }
    1860 
    1861   if(found == false)
    1862   {
    1863     i->cur_subkey = old_subkey;
    1864     return false;
    1865   }
    1866 
    1867   talloc_unlink(NULL, subkey);
    1868   return true;
     1879bool regfi_iterator_find_subkey(REGFI_ITERATOR* i, const char* name)
     1880{
     1881  uint32_t new_index;
     1882
     1883  if(regfi_find_subkey(i->f, i->cur_key, name, &new_index))
     1884  {
     1885    i->cur_subkey = new_index;
     1886    return true;
     1887  }
     1888
     1889  return false;
    18691890}
    18701891
     
    19221943 
    19231944  return ((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE)
    1924           && (i->cur_subkey < i->cur_key->num_subkeys));
     1945          && (i->cur_subkey < regfi_fetch_num_subkeys(i->cur_key)));
    19251946}
    19261947
     
    19301951const REGFI_NK* regfi_iterator_cur_subkey(REGFI_ITERATOR* i)
    19311952{
    1932   uint32_t nk_offset;
    1933 
    1934   if((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE)
    1935      && (i->cur_subkey < i->cur_key->num_subkeys))
    1936   {
    1937     nk_offset = i->cur_key->subkeys->elements[i->cur_subkey].offset;
    1938 
    1939     return regfi_load_key(i->f, nk_offset+REGFI_REGF_SIZE,
    1940                           i->f->string_encoding, true);
    1941   }
    1942 
    1943   return NULL;
     1953  return regfi_get_subkey(i->f, i->cur_key, i->cur_subkey);
    19441954}
    19451955
     
    19521962
    19531963  return ((i->cur_key != NULL) && (i->cur_key->subkeys_off!=REGFI_OFFSET_NONE)
    1954           && (i->cur_subkey < i->cur_key->num_subkeys));
     1964          && (i->cur_subkey < regfi_fetch_num_subkeys(i->cur_key)));
    19551965}
    19561966
     
    19581968/******************************************************************************
    19591969 *****************************************************************************/
    1960 bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* value_name)
    1961 {
    1962   const REGFI_VK* cur;
    1963   bool found = false;
    1964   uint32_t old_value = i->cur_value;
    1965 
    1966   /* XXX: cur->name can be NULL in the registry. 
    1967    *      Should we allow for a way to search for that?
    1968    */
    1969   if(value_name == NULL)
    1970     return false;
    1971 
    1972   regfi_iterator_first_value(i);
    1973   while((cur = regfi_iterator_cur_value(i)) != NULL && (found == false))
    1974   {
    1975     if((cur->name != NULL)
    1976        && (strcasecmp(cur->name, value_name) == 0))
    1977       found = true;
    1978     else
    1979     {
    1980       regfi_free_record(cur);
    1981       regfi_iterator_next_value(i);
    1982     }
    1983   }
    1984  
    1985   if(found == false)
    1986   {
    1987     i->cur_value = old_value;
    1988     return false;
    1989   }
    1990 
    1991   regfi_free_record(cur);
    1992   return true;
     1970bool regfi_iterator_find_value(REGFI_ITERATOR* i, const char* name)
     1971{
     1972  uint32_t new_index;
     1973
     1974  if(regfi_find_value(i->f, i->cur_key, name, &new_index))
     1975  {
     1976    i->cur_value = new_index;
     1977    return true;
     1978  }
     1979
     1980  return false;
    19931981}
    19941982
     
    20001988  i->cur_value = 0;
    20011989  return (i->cur_key->values != NULL && i->cur_key->values->elements != NULL
    2002           && (i->cur_value < i->cur_key->values->num_values));
     1990          && (i->cur_value < regfi_fetch_num_values(i->cur_key)));
    20031991}
    20041992
     
    20081996const REGFI_VK* regfi_iterator_cur_value(REGFI_ITERATOR* i)
    20091997{
    2010   REGFI_VK* ret_val = NULL;
    2011   uint32_t voffset;
    2012 
    2013   if(i->cur_key->values != NULL && i->cur_key->values->elements != NULL
    2014      && (i->cur_value < i->cur_key->values->num_values))
    2015   {
    2016     voffset = i->cur_key->values->elements[i->cur_value];
    2017     ret_val = regfi_load_value(i->f, voffset+REGFI_REGF_SIZE,
    2018                                i->f->string_encoding, true);
    2019   }
    2020 
    2021   return ret_val;
     1998  return regfi_get_value(i->f, i->cur_key, i->cur_value);
    20221999}
    20232000
     
    20292006  i->cur_value++;
    20302007  return (i->cur_key->values != NULL && i->cur_key->values->elements != NULL
    2031           && (i->cur_value < i->cur_key->values->num_values));
     2008          && (i->cur_value < regfi_fetch_num_values(i->cur_key)));
    20322009}
    20332010
     
    21412118 
    21422119  return ret_val;
     2120}
     2121
     2122
     2123
     2124/******************************************************************************
     2125 *****************************************************************************/
     2126bool regfi_find_subkey(REGFI_FILE* file, const REGFI_NK* key,
     2127                       const char* name, uint32_t* index)
     2128{
     2129  const REGFI_NK* cur;
     2130  uint32_t i;
     2131  uint32_t num_subkeys = regfi_fetch_num_subkeys(key);
     2132  bool found = false;
     2133
     2134  /* XXX: cur->name can be NULL in the registry. 
     2135   *      Should we allow for a way to search for that?
     2136   */
     2137  if(name == NULL)
     2138    return false;
     2139
     2140  for(i=0; (i < num_subkeys) && (found == false); i++)
     2141  {
     2142    cur = regfi_get_subkey(file, key, i);
     2143    if(cur == NULL)
     2144      return false;
     2145
     2146    if((cur->name != NULL)
     2147       && (strcasecmp(cur->name, name) == 0))
     2148    {
     2149      found = true;
     2150      *index = i;
     2151    }
     2152
     2153    regfi_free_record(cur);
     2154  }
     2155
     2156  return found;
     2157}
     2158
     2159
     2160
     2161/******************************************************************************
     2162 *****************************************************************************/
     2163bool regfi_find_value(REGFI_FILE* file, const REGFI_NK* key,
     2164                      const char* name, uint32_t* index)
     2165{
     2166  const REGFI_VK* cur;
     2167  uint32_t i;
     2168  uint32_t num_values = regfi_fetch_num_values(key);
     2169  bool found = false;
     2170
     2171  /* XXX: cur->name can be NULL in the registry. 
     2172   *      Should we allow for a way to search for that?
     2173   */
     2174  if(name == NULL)
     2175    return false;
     2176
     2177  for(i=0; (i < num_values) && (found == false); i++)
     2178  {
     2179    cur = regfi_get_value(file, key, i);
     2180    if(cur == NULL)
     2181      return false;
     2182
     2183    if((cur->name != NULL)
     2184       && (strcasecmp(cur->name, name) == 0))
     2185    {
     2186      found = true;
     2187      *index = i;
     2188    }
     2189
     2190    regfi_free_record(cur);
     2191  }
     2192
     2193  return found;
     2194}
     2195
     2196
     2197
     2198/******************************************************************************
     2199 *****************************************************************************/
     2200const REGFI_NK* regfi_get_subkey(REGFI_FILE* file, const REGFI_NK* key,
     2201                                 uint32_t index)
     2202{
     2203  if(index < regfi_fetch_num_subkeys(key))
     2204  {
     2205    return regfi_load_key(file,
     2206                          key->subkeys->elements[index].offset+REGFI_REGF_SIZE,
     2207                          file->string_encoding, true);
     2208  }
     2209
     2210  return NULL;
     2211}
     2212
     2213
     2214
     2215/******************************************************************************
     2216 *****************************************************************************/
     2217const REGFI_VK* regfi_get_value(REGFI_FILE* file, const REGFI_NK* key,
     2218                                uint32_t index)
     2219{
     2220  if(index < regfi_fetch_num_values(key))
     2221  {
     2222    return regfi_load_value(file,
     2223                            key->values->elements[index]+REGFI_REGF_SIZE,
     2224                            file->string_encoding, true);
     2225  }
     2226
     2227  return NULL; 
    21432228}
    21442229
  • trunk/python/pyregfi/__init__.py

    r206 r207  
    66import ctypes
    77import ctypes.util
    8 from ctypes import c_char,c_char_p,c_int,c_uint16,c_bool,POINTER
     8from ctypes import c_char,c_char_p,c_int,c_uint16,c_uint32,c_bool,POINTER
    99
    1010regfi = ctypes.CDLL(ctypes.util.find_library('regfi'), use_errno=True)
     
    2929regfi.regfi_free_record.restype = None
    3030
     31regfi.regfi_fetch_num_subkeys.argtypes = [POINTER(REGFI_NK)]
     32regfi.regfi_fetch_num_subkeys.restype = c_uint32
     33
     34regfi.regfi_fetch_num_values.argtypes = [POINTER(REGFI_NK)]
     35regfi.regfi_fetch_num_values.restype = c_uint32
     36
    3137regfi.regfi_fetch_classname.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK)]
    3238regfi.regfi_fetch_classname.restype = POINTER(REGFI_CLASSNAME)
     
    3844regfi.regfi_fetch_data.restype = POINTER(REGFI_DATA)
    3945
     46regfi.regfi_find_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
     47                                    c_char_p, POINTER(c_uint32)]
     48regfi.regfi_find_subkey.restype = c_bool
     49
     50regfi.regfi_find_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
     51                                    c_char_p, POINTER(c_uint32)]
     52regfi.regfi_find_value.restype = c_bool
     53
     54regfi.regfi_get_subkey.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
     55                                   c_uint32]
     56regfi.regfi_get_subkey.restype = POINTER(REGFI_NK)
     57
     58regfi.regfi_get_value.argtypes = [POINTER(REGFI_FILE), POINTER(REGFI_NK),
     59                                   c_uint32]
     60regfi.regfi_get_value.restype = POINTER(REGFI_VK)
     61
    4062regfi.regfi_iterator_new.argtypes = [POINTER(REGFI_FILE), REGFI_ENCODING]
    4163regfi.regfi_iterator_new.restype = POINTER(REGFI_ITERATOR)
     
    83105regfi.regfi_iterator_find_value.restype = c_bool
    84106
     107
     108
     109regfi.regfi_get_value
    85110
    86111regfi.regfi_init.argtypes = []
     
    93118    if msgs == None:
    94119        return ''
    95     return msgs
     120    return msgs.decode('ascii')
    96121
    97122
    98123class _StructureWrapper():
    99124    "Handles memory management and proxies attribute access to base structures"
     125    hive = None
    100126    base = None
    101127
    102     def __init__(self, base):
     128    def __init__(self, hive, base):
     129        self.hive = hive
    103130        # XXX: check for NULL here, throw an exception if so.
    104131        self.base = base
     
    117144
    118145
    119 class Key(_StructureWrapper):
    120     pass
    121 
    122146class Value(_StructureWrapper):
    123147    pass
    124148
     149
    125150class Data(_StructureWrapper):
    126151    pass
    127152
     153
    128154class Security(_StructureWrapper):
    129155    pass
     156
     157
     158class _ValueList():
     159    hive = None
     160    key = None
     161    length = None
     162    current = None
     163
     164    def __init__(self, key):
     165        self.hive = key.hive
     166        # XXX: check for NULL here, throw an exception if so.
     167        self.key = key
     168        self.length = regfi.regfi_fetch_num_values(key.base)
     169   
     170    def __len__(self):
     171        return self.length
     172
     173    def __getitem__(self, name):
     174        index = c_uint32()
     175        # XXX: need to do any funky unicode conversions on name?
     176        if regfi.regfi_find_value(self.hive.file, self.key.base,
     177                                  create_string_buffer(name), byref(index)):
     178            return Value(hive,
     179                         regfi.regfi_get_value(hive.file, key.base, index))
     180        raise KeyError('')
     181
     182    def __iter__(self):
     183        self.current = 0
     184        return self
     185   
     186    def __next__(self):
     187        if self.current >= self.length:
     188            raise StopIteration('')
     189
     190        vk = regfi.regfi_get_value(self.hive.file, self.key.base,
     191                                   c_uint32(self.current))
     192        self.current += 1
     193        return vk.contents
     194   
     195
     196class Key(_StructureWrapper):
     197    values = None
     198
     199    def __init__(self, hive, base):
     200        super(Key, self).__init__(hive, base)
     201        self.values = _ValueList(self)
     202
     203    def fetch_security(self):
     204        return Security(self.hive,
     205                        regfi.regfi_fetch_sk(self.hive.file, self.base))
     206
    130207
    131208class Hive():   
     
    229306
    230307    def current_key(self):
    231         return Key(regfi.regfi_iterator_cur_key(self.iter))
     308        return Key(self.hive, regfi.regfi_iterator_cur_key(self.iter))
Note: See TracChangeset for help on using the changeset viewer.