<s> """<STR_LIT>""" <EOL> import ctypes <EOL> import ctypes . wintypes <EOL> import exceptions <EOL> import os <EOL> import stat <EOL> import StringIO <EOL> import _winreg <EOL> from grr . client import vfs <EOL> from grr . lib import utils <EOL> from grr . lib . rdfvalues import client as rdf_client <EOL> from grr . lib . rdfvalues import paths as rdf_paths <EOL> from grr . lib . rdfvalues import protodict as rdf_protodict <EOL> WIN_UNIX_DIFF_MSECS = <NUM_LIT> <EOL> KEY_READ = <NUM_LIT> <EOL> def CanonicalPathToLocalPath ( path ) : <EOL> path = path . replace ( "<STR_LIT:/>" , "<STR_LIT:\\>" ) <EOL> return path . strip ( "<STR_LIT:\\>" ) <EOL> advapi32 = ctypes . windll . advapi32 <EOL> LPDWORD = ctypes . POINTER ( ctypes . wintypes . DWORD ) <EOL> LPBYTE = ctypes . POINTER ( ctypes . wintypes . BYTE ) <EOL> ERROR_SUCCESS = <NUM_LIT:0> <EOL> ERROR_MORE_DATA = <NUM_LIT> <EOL> class FileTime ( ctypes . Structure ) : <EOL> _fields_ = [ ( "<STR_LIT>" , ctypes . wintypes . DWORD ) , <EOL> ( "<STR_LIT>" , ctypes . wintypes . DWORD ) ] <EOL> RegCloseKey = advapi32 . RegCloseKey <EOL> RegCloseKey . restype = ctypes . c_long <EOL> RegCloseKey . argtypes = [ ctypes . c_void_p ] <EOL> RegEnumKeyEx = advapi32 . RegEnumKeyExW <EOL> RegEnumKeyEx . restype = ctypes . c_long <EOL> RegEnumKeyEx . argtypes = [ ctypes . c_void_p , ctypes . wintypes . DWORD , <EOL> ctypes . c_wchar_p , LPDWORD , <EOL> LPDWORD , ctypes . c_wchar_p , LPDWORD , <EOL> ctypes . POINTER ( FileTime ) ] <EOL> RegEnumValue = advapi32 . RegEnumValueW <EOL> RegEnumValue . restype = ctypes . c_long <EOL> RegEnumValue . argtypes = [ ctypes . c_void_p , ctypes . wintypes . DWORD , <EOL> ctypes . c_wchar_p , LPDWORD , LPDWORD , LPDWORD , LPBYTE , <EOL> LPDWORD ] <EOL> RegOpenKeyEx = advapi32 . RegOpenKeyExW <EOL> RegOpenKeyEx . restype = ctypes . c_long <EOL> RegOpenKeyEx . argtypes = [ ctypes . c_void_p , ctypes . c_wchar_p , ctypes . c_ulong , <EOL> ctypes . c_ulong , ctypes . POINTER ( ctypes . c_void_p ) ] <EOL> RegQueryInfoKey = advapi32 . RegQueryInfoKeyW <EOL> RegQueryInfoKey . restype = ctypes . c_long <EOL> RegQueryInfoKey . argtypes = [ ctypes . c_void_p , ctypes . c_wchar_p , LPDWORD , LPDWORD , <EOL> LPDWORD , LPDWORD , LPDWORD , LPDWORD , <EOL> LPDWORD , LPDWORD , LPDWORD , <EOL> ctypes . POINTER ( FileTime ) ] <EOL> RegQueryValueEx = advapi32 . RegQueryValueExW <EOL> RegQueryValueEx . restype = ctypes . c_long <EOL> RegQueryValueEx . argtypes = [ ctypes . c_void_p , ctypes . c_wchar_p , LPDWORD , LPDWORD , <EOL> LPBYTE , LPDWORD ] <EOL> class KeyHandle ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , value = <NUM_LIT:0> ) : <EOL> if value : <EOL> self . handle = ctypes . c_void_p ( value ) <EOL> else : <EOL> self . handle = ctypes . c_void_p ( ) <EOL> def __enter__ ( self ) : <EOL> return self <EOL> def __exit__ ( self , exc_type = None , exc_val = None , exc_tb = None ) : <EOL> self . Close ( ) <EOL> return False <EOL> def Close ( self ) : <EOL> if not self . handle : <EOL> return <EOL> if RegCloseKey is None : <EOL> return <EOL> rc = RegCloseKey ( self . handle ) <EOL> self . handle = ctypes . c_void_p ( ) <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> def __del__ ( self ) : <EOL> self . Close ( ) <EOL> def OpenKey ( key , sub_key ) : <EOL> """<STR_LIT>""" <EOL> new_key = KeyHandle ( ) <EOL> rc = RegOpenKeyEx ( key . handle , sub_key , <NUM_LIT:0> , KEY_READ , <EOL> ctypes . cast ( ctypes . byref ( new_key . handle ) , <EOL> ctypes . POINTER ( ctypes . c_void_p ) ) ) <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> return new_key <EOL> def CloseKey ( key ) : <EOL> rc = RegCloseKey ( key ) <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> def QueryInfoKey ( key ) : <EOL> """<STR_LIT>""" <EOL> null = LPDWORD ( ) <EOL> num_sub_keys = ctypes . wintypes . DWORD ( ) <EOL> num_values = ctypes . wintypes . DWORD ( ) <EOL> ft = FileTime ( ) <EOL> rc = RegQueryInfoKey ( key . handle , ctypes . c_wchar_p ( ) , null , null , <EOL> ctypes . byref ( num_sub_keys ) , null , null , <EOL> ctypes . byref ( num_values ) , null , null , null , <EOL> ctypes . byref ( ft ) ) <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> return ( num_sub_keys . value , num_values . value , <EOL> ft . dwLowDateTime | ( ft . dwHighDateTime << <NUM_LIT:32> ) ) <EOL> def QueryValueEx ( key , value_name ) : <EOL> """<STR_LIT>""" <EOL> size = <NUM_LIT> <EOL> data_type = ctypes . wintypes . DWORD ( ) <EOL> while True : <EOL> tmp_size = ctypes . wintypes . DWORD ( size ) <EOL> buf = ctypes . create_string_buffer ( size ) <EOL> rc = RegQueryValueEx ( key . handle , value_name , LPDWORD ( ) , <EOL> ctypes . byref ( data_type ) , <EOL> ctypes . cast ( buf , LPBYTE ) , ctypes . byref ( tmp_size ) ) <EOL> if rc != ERROR_MORE_DATA : <EOL> break <EOL> if size > <NUM_LIT:10> * <NUM_LIT> * <NUM_LIT> : <EOL> raise exceptions . WindowsError ( "<STR_LIT>" ) <EOL> size *= <NUM_LIT:2> <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> return ( Reg2Py ( buf , tmp_size . value , data_type . value ) , data_type . value ) <EOL> def EnumKey ( key , index ) : <EOL> """<STR_LIT>""" <EOL> buf = ctypes . create_unicode_buffer ( <NUM_LIT> ) <EOL> length = ctypes . wintypes . DWORD ( <NUM_LIT> ) <EOL> rc = RegEnumKeyEx ( key . handle , index , <EOL> ctypes . cast ( buf , ctypes . c_wchar_p ) , <EOL> ctypes . byref ( length ) , <EOL> LPDWORD ( ) , ctypes . c_wchar_p ( ) , LPDWORD ( ) , <EOL> ctypes . POINTER ( FileTime ) ( ) ) <EOL> if rc != <NUM_LIT:0> : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> return ctypes . wstring_at ( buf , length . value ) . rstrip ( u"<STR_LIT:\x00>" ) <EOL> def EnumValue ( key , index ) : <EOL> """<STR_LIT>""" <EOL> null = ctypes . POINTER ( ctypes . wintypes . DWORD ) ( ) <EOL> value_size = ctypes . wintypes . DWORD ( ) <EOL> data_size = ctypes . wintypes . DWORD ( ) <EOL> rc = RegQueryInfoKey ( key . handle , ctypes . c_wchar_p ( ) , null , null , null , <EOL> null , null , null , <EOL> ctypes . byref ( value_size ) , ctypes . byref ( data_size ) , <EOL> null , ctypes . POINTER ( FileTime ) ( ) ) <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> value_size . value += <NUM_LIT:1> <EOL> data_size . value += <NUM_LIT:1> <EOL> value = ctypes . create_unicode_buffer ( value_size . value ) <EOL> while True : <EOL> data = ctypes . create_string_buffer ( data_size . value ) <EOL> tmp_value_size = ctypes . wintypes . DWORD ( value_size . value ) <EOL> tmp_data_size = ctypes . wintypes . DWORD ( data_size . value ) <EOL> data_type = ctypes . wintypes . DWORD ( ) <EOL> rc = RegEnumValue ( key . handle , index , <EOL> ctypes . cast ( value , ctypes . c_wchar_p ) , <EOL> ctypes . byref ( tmp_value_size ) , null , <EOL> ctypes . byref ( data_type ) , <EOL> ctypes . cast ( data , LPBYTE ) , <EOL> ctypes . byref ( tmp_data_size ) ) <EOL> if rc != ERROR_MORE_DATA : <EOL> break <EOL> data_size . value *= <NUM_LIT:2> <EOL> if rc != ERROR_SUCCESS : <EOL> raise ctypes . WinError ( <NUM_LIT:2> ) <EOL> return ( value . value , Reg2Py ( data , tmp_data_size . value , data_type . value ) , <EOL> data_type . value ) <EOL> def Reg2Py ( data , size , data_type ) : <EOL> if data_type == _winreg . REG_DWORD : <EOL> if size == <NUM_LIT:0> : <EOL> return <NUM_LIT:0> <EOL> return ctypes . cast ( data , ctypes . POINTER ( ctypes . c_int ) ) . contents . value <EOL> elif data_type == _winreg . REG_SZ or data_type == _winreg . REG_EXPAND_SZ : <EOL> return ctypes . wstring_at ( data , size // <NUM_LIT:2> ) . rstrip ( u"<STR_LIT:\x00>" ) <EOL> elif data_type == _winreg . REG_MULTI_SZ : <EOL> return ctypes . wstring_at ( data , size // <NUM_LIT:2> ) . rstrip ( u"<STR_LIT:\x00>" ) . split ( u"<STR_LIT:\x00>" ) <EOL> else : <EOL> if size == <NUM_LIT:0> : <EOL> return None <EOL> return ctypes . string_at ( data , size ) <EOL> class RegistryFile ( vfs . VFSHandler ) : <EOL> """<STR_LIT>""" <EOL> supported_pathtype = rdf_paths . PathSpec . PathType . REGISTRY <EOL> auto_register = True <EOL> value = None <EOL> value_type = _winreg . REG_NONE <EOL> hive = None <EOL> last_modified = <NUM_LIT:0> <EOL> is_directory = True <EOL> fd = None <EOL> registry_map = { <EOL> _winreg . REG_NONE : rdf_client . StatEntry . RegistryType . REG_NONE , <EOL> _winreg . REG_SZ : rdf_client . StatEntry . RegistryType . REG_SZ , <EOL> _winreg . REG_EXPAND_SZ : rdf_client . StatEntry . RegistryType . REG_EXPAND_SZ , <EOL> _winreg . REG_BINARY : rdf_client . StatEntry . RegistryType . REG_BINARY , <EOL> _winreg . REG_DWORD : rdf_client . StatEntry . RegistryType . REG_DWORD , <EOL> _winreg . REG_DWORD_LITTLE_ENDIAN : ( <EOL> rdf_client . StatEntry . RegistryType . REG_DWORD_LITTLE_ENDIAN ) , <EOL> _winreg . REG_DWORD_BIG_ENDIAN : ( <EOL> rdf_client . StatEntry . RegistryType . REG_DWORD_BIG_ENDIAN ) , <EOL> _winreg . REG_LINK : rdf_client . StatEntry . RegistryType . REG_LINK , <EOL> _winreg . REG_MULTI_SZ : rdf_client . StatEntry . RegistryType . REG_MULTI_SZ , <EOL> } <EOL> def __init__ ( self , base_fd , pathspec = None , progress_callback = None , <EOL> full_pathspec = None ) : <EOL> super ( RegistryFile , self ) . __init__ ( base_fd , pathspec = pathspec , <EOL> full_pathspec = full_pathspec , <EOL> progress_callback = progress_callback ) <EOL> if base_fd is None : <EOL> self . pathspec . Append ( pathspec ) <EOL> elif base_fd . IsDirectory ( ) : <EOL> self . pathspec . last . path = utils . JoinPath ( self . pathspec . last . path , <EOL> pathspec . path ) <EOL> else : <EOL> raise IOError ( "<STR_LIT>" ) <EOL> path_components = filter ( None , self . pathspec . last . path . split ( "<STR_LIT:/>" ) ) <EOL> try : <EOL> self . hive = getattr ( _winreg , path_components [ <NUM_LIT:0> ] ) <EOL> self . hive = KeyHandle ( self . hive ) <EOL> except AttributeError : <EOL> raise IOError ( "<STR_LIT>" % path_components [ <NUM_LIT:0> ] ) <EOL> except IndexError : <EOL> return <EOL> self . key_name = "<STR_LIT:/>" . join ( path_components [ <NUM_LIT:1> : ] ) <EOL> self . local_path = CanonicalPathToLocalPath ( self . key_name ) <EOL> try : <EOL> key_name , value_name = os . path . split ( self . local_path ) <EOL> with OpenKey ( self . hive , key_name ) as key : <EOL> self . value , self . value_type = QueryValueEx ( key , value_name ) <EOL> self . is_directory = False <EOL> except exceptions . WindowsError : <EOL> try : <EOL> with OpenKey ( self . hive , self . local_path ) as key : <EOL> try : <EOL> self . value , self . value_type = QueryValueEx ( key , "<STR_LIT>" ) <EOL> except exceptions . WindowsError : <EOL> self . value = "<STR_LIT>" <EOL> self . value_type = _winreg . REG_NONE <EOL> except exceptions . WindowsError : <EOL> raise IOError ( "<STR_LIT>" % self . key_name ) <EOL> def Stat ( self ) : <EOL> return self . _Stat ( "<STR_LIT>" , self . value , self . value_type ) <EOL> def _Stat ( self , name , value , value_type ) : <EOL> response = rdf_client . StatEntry ( ) <EOL> response_pathspec = self . pathspec . Copy ( ) <EOL> response_pathspec . path_options = rdf_paths . PathSpec . Options . CASE_LITERAL <EOL> response_pathspec . last . path = utils . JoinPath ( <EOL> response_pathspec . last . path , name ) <EOL> response . pathspec = response_pathspec <EOL> if self . IsDirectory ( ) : <EOL> response . st_mode = stat . S_IFDIR <EOL> else : <EOL> response . st_mode = stat . S_IFREG <EOL> response . st_mtime = self . last_modified <EOL> response . st_size = len ( utils . SmartStr ( value ) ) <EOL> if value_type is not None : <EOL> response . registry_type = self . registry_map . get ( value_type , <NUM_LIT:0> ) <EOL> response . registry_data = rdf_protodict . DataBlob ( ) . SetValue ( value ) <EOL> return response <EOL> def ListNames ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . IsDirectory ( ) : return <EOL> if self . hive is None : <EOL> for name in dir ( _winreg ) : <EOL> if name . startswith ( "<STR_LIT>" ) : <EOL> yield name <EOL> return <EOL> try : <EOL> with OpenKey ( self . hive , self . local_path ) as key : <EOL> ( self . number_of_keys , self . number_of_values , <EOL> self . last_modified ) = QueryInfoKey ( key ) <EOL> self . last_modified = self . last_modified / <NUM_LIT> - WIN_UNIX_DIFF_MSECS <EOL> for i in range ( self . number_of_keys ) : <EOL> try : <EOL> yield EnumKey ( key , i ) <EOL> except exceptions . WindowsError : <EOL> pass <EOL> for i in range ( self . number_of_values ) : <EOL> try : <EOL> name , unused_value , unused_value_type = EnumValue ( key , i ) <EOL> yield name <EOL> except exceptions . WindowsError : <EOL> pass <EOL> except exceptions . WindowsError as e : <EOL> raise IOError ( "<STR_LIT>" % ( self . key_name , e ) ) <EOL> def ListFiles ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . IsDirectory ( ) : return <EOL> if self . hive is None : <EOL> for name in dir ( _winreg ) : <EOL> if name . startswith ( "<STR_LIT>" ) : <EOL> response = rdf_client . StatEntry ( <EOL> st_mode = stat . S_IFDIR ) <EOL> response_pathspec = self . pathspec . Copy ( ) <EOL> response_pathspec . last . path = utils . JoinPath ( <EOL> response_pathspec . last . path , name ) <EOL> response . pathspec = response_pathspec <EOL> yield response <EOL> return <EOL> try : <EOL> with OpenKey ( self . hive , self . local_path ) as key : <EOL> ( self . number_of_keys , self . number_of_values , <EOL> self . last_modified ) = QueryInfoKey ( key ) <EOL> self . last_modified = self . last_modified / <NUM_LIT> - WIN_UNIX_DIFF_MSECS <EOL> for i in range ( self . number_of_keys ) : <EOL> try : <EOL> name = EnumKey ( key , i ) <EOL> key_name = utils . JoinPath ( self . local_path , name ) <EOL> try : <EOL> with OpenKey ( self . hive , key_name ) as subkey : <EOL> value , value_type = QueryValueEx ( subkey , "<STR_LIT>" ) <EOL> except exceptions . WindowsError : <EOL> value , value_type = None , None <EOL> response = self . _Stat ( name , value , value_type ) <EOL> response . st_mode = stat . S_IFDIR <EOL> yield response <EOL> except exceptions . WindowsError : <EOL> pass <EOL> for i in range ( self . number_of_values ) : <EOL> try : <EOL> name , value , value_type = EnumValue ( key , i ) <EOL> response = self . _Stat ( name , value , value_type ) <EOL> response . st_mode = stat . S_IFREG <EOL> yield response <EOL> except exceptions . WindowsError : <EOL> pass <EOL> except exceptions . WindowsError as e : <EOL> raise IOError ( "<STR_LIT>" % ( self . key_name , e ) ) <EOL> def IsDirectory ( self ) : <EOL> return self . is_directory <EOL> def Read ( self , length ) : <EOL> if not self . fd : <EOL> self . fd = StringIO . StringIO ( utils . SmartStr ( self . value ) ) <EOL> return self . fd . read ( length ) <EOL> def Seek ( self , offset , whence = <NUM_LIT:0> ) : <EOL> if not self . fd : <EOL> self . fd = StringIO . StringIO ( utils . SmartStr ( self . value ) ) <EOL> return self . fd . seek ( offset , whence ) </s>
