mruprop.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 14k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //-------------------------------------------------------------------------//
  2. //
  3. // MruProp.cpp
  4. //
  5. //-------------------------------------------------------------------------//
  6. #include "pch.h"
  7. #include "MruProp.h"
  8. #include "propvar.h"
  9. //-------------------------------------------------------------------------//
  10. static LPCTSTR szRECKEYNAMEFMT  = TEXT("%s\mru\%s\%02ld-%02ld"),    // subkey, fmtid, propid, vt
  11.                szINDEXVALNAME   = TEXT("index"),
  12.                szRECTITLEFMT    = TEXT("%02ld") ;
  13. static const int  cchVALNAME       = 4 ;
  14. static const ULONG INVALID_INDEX_VALUE   = (ULONG)-1 ;
  15. //-------------------------------------------------------------------------//
  16. #define INIT_INDEX_ELEMENT( iPos )  
  17.     { m_index[iPos].nRec   = INVALID_INDEX_VALUE ; 
  18.       m_index[iPos].dwHash = 0 ; }
  19. #define VALID_INDEX_ELEMENT( iPos ) 
  20.       ((iPos)>=0 && (iPos)<IndexCount())
  21. //-------------------------------------------------------------------------//
  22. CPropMruStor::CPropMruStor()
  23. {
  24.     Construct() ;
  25. }
  26. //-------------------------------------------------------------------------//
  27. CPropMruStor::CPropMruStor( HKEY hKeyRoot, LPCTSTR pszSubKey )
  28. {
  29.     Construct() ;
  30.     SetRoot( hKeyRoot, pszSubKey ) ;
  31. }
  32. //-------------------------------------------------------------------------//
  33. void CPropMruStor::Construct()
  34. {
  35.     m_hKey = 
  36.     m_hKeyRoot = NULL ;
  37.     m_pszRootSubKey = NULL ;
  38. m_pszRecSubKey = NULL ;
  39.     m_cRef = 0 ;
  40.     
  41.     for( ULONG i = 0; i < IndexCount(); i++ )
  42.         INIT_INDEX_ELEMENT( i ) ;
  43. }
  44. //-------------------------------------------------------------------------//
  45. CPropMruStor::~CPropMruStor()
  46. {
  47.     Close() ;
  48.     ClearRecKeyName() ;
  49.     ClearRoot() ;
  50. }
  51. //-------------------------------------------------------------------------//
  52. HRESULT CPropMruStor::SetRoot( HKEY hKeyRoot, LPCTSTR pszRootSubKey )
  53. {
  54.     LPTSTR  psz = NULL ;
  55.     int     cch = pszRootSubKey ? lstrlen( pszRootSubKey ) : 0 ;
  56.     if( cch )
  57.     {
  58.         if( (psz = new TCHAR[cch+1])==NULL )
  59.             return E_OUTOFMEMORY ;
  60.         lstrcpyn( psz, pszRootSubKey, cch+1 ) ;
  61.     }
  62.     
  63.     Close() ;
  64.     ClearRoot() ;
  65.     ClearRecKeyName() ;
  66.     m_hKeyRoot = hKeyRoot ;
  67.     m_pszRootSubKey = psz ;
  68.     return S_OK ;
  69. }
  70. //-------------------------------------------------------------------------//
  71. void CPropMruStor::ClearRoot()
  72. {
  73.     if( m_pszRootSubKey )
  74.     {
  75.         delete m_pszRootSubKey ;
  76.         m_pszRootSubKey = NULL ;
  77.     }
  78.     m_hKeyRoot = NULL ;
  79. }
  80. //-------------------------------------------------------------------------//
  81. HRESULT CPropMruStor::PushMruVal( REFFMTID fmtid, PROPID propid, VARTYPE vt, IN const PROPVARIANT& var )
  82. {
  83.     HRESULT hr ;
  84.     
  85.     //  Retrieve length of data
  86.     ULONG cbVal ;
  87.     if( !SUCCEEDED( (hr = PropVariantSize( var, cbVal, NULL )) ) )
  88.         return hr ;
  89.     cbVal += sizeof( var.vt ) ;
  90.     //  Build the key name
  91.     if( !SUCCEEDED( (hr = MakeRecKeyName( fmtid, propid, vt )) ) )
  92.         return hr ;
  93.     //  Open the key
  94.     if( !SUCCEEDED( (hr = Open()) ) )
  95.         return hr ;
  96.     //  Load the MRU index
  97.     LoadIndex( m_index ) ;
  98.     //  If the PROPVARIANT already exists, just promote it and get out.
  99.     ULONG iPosMatch ;
  100.     if( FindVal( var, iPosMatch )==S_OK )
  101.         return PromoteMruVal( iPosMatch ) ;
  102.     //  Determine PROPVARIANT's hash value
  103.     if( !SUCCEEDED( (hr = PropVariantHash( var, m_index[0].dwHash )) ) )
  104.         return hr ;
  105.     //  Pop the LRU value
  106.     if( !SUCCEEDED( (hr = PopMruVal()) ) )
  107.         return hr ;
  108.     //  Assign new index value
  109.     m_index[0].nRec     = GetUnusedRecNo() ;
  110.     TCHAR  szValName[cchVALNAME] ;
  111.     if( !GetRecTitle( 0, szValName ) )
  112.     {
  113.         INIT_INDEX_ELEMENT( 0 ) ;
  114.         return E_UNEXPECTED ;
  115.     }
  116.     
  117.     //  Persist the new index and PROPVARIANT value
  118.     if( !SUCCEEDED( (hr = PropVariantWriteRegistry( m_hKey, szValName, var )) ) )
  119.     {
  120.         INIT_INDEX_ELEMENT( 0 ) ;
  121.         return hr ;
  122.     }
  123.     
  124.     //  Persist the index
  125.     hr = UpdateIndex() ;
  126.     return hr ;
  127. }
  128. //-------------------------------------------------------------------------//
  129. //  Removes the LRU item.
  130. HRESULT CPropMruStor::PopMruVal()
  131. {
  132.     ASSERT( IsOpen() ) ;
  133.     HRESULT hr = S_OK ;
  134.     if( GetRecNo( 0 )==INVALID_INDEX_VALUE )
  135.         return hr ;
  136.     TCHAR szValName[cchVALNAME] ;
  137.     if( GetRecTitle( IndexCount()-1, szValName ) )
  138.     {
  139.         DWORD dwRet = RegDeleteValue( m_hKey, szValName ) ;
  140.         if( !SUCCEEDED( (hr = HRESULT_FROM_WIN32( dwRet )) ) )
  141.             return hr ;
  142.     }
  143.     //  Advance indices by one position.
  144.     for( int i= IndexCount()-1; i>0; i-- )
  145.         m_index[i] = m_index[i-1] ;
  146.     
  147.     //  Clear head
  148.     INIT_INDEX_ELEMENT( 0 ) ;
  149.     return hr ;
  150. }
  151. //-------------------------------------------------------------------------//
  152. HRESULT CPropMruStor::FindVal( IN const PROPVARIANT& var, OUT ULONG& iPos )
  153. {
  154.     ASSERT( IsOpen() ) ;
  155.     HRESULT hr ;
  156.     ULONG   dwHash = 0 ;
  157.     iPos = INVALID_INDEX_VALUE ;
  158.     if( !SUCCEEDED( (hr = PropVariantHash( var, dwHash )) ) )
  159.         return hr ;
  160.     for( ULONG i=0; i < IndexCount(); i++ )
  161.     {
  162.         PROPVARIANT varOther ;
  163.         TCHAR       szValName[cchVALNAME] ;
  164.         
  165.         if( m_index[i].dwHash != dwHash )
  166.             continue ;
  167.         if( !GetRecTitle( i, szValName ) )
  168.             continue ;
  169.         if( !SUCCEEDED( (hr = PropVariantReadRegistry( m_hKey, szValName, varOther )) ) )
  170.             continue ;
  171.         
  172.         if( PropVariantCompare( var, varOther, STRICT_COMPARE )!=0 )
  173.             continue ;
  174.         
  175.         iPos = i ;
  176.         return S_OK ;
  177.     }
  178.     return S_FALSE ;
  179. }
  180. //-------------------------------------------------------------------------//
  181. HRESULT CPropMruStor::PromoteMruVal( IN ULONG iPosSrc )
  182. {
  183.     if( !VALID_INDEX_ELEMENT( iPosSrc ) )
  184.     {
  185.         ASSERT( FALSE ) ;
  186.         return E_INVALIDARG ;
  187.     }
  188.            
  189.     if( iPosSrc==0 )
  190.         return S_OK ;
  191.         
  192.     INDEX index = m_index[iPosSrc] ;
  193.     for( ULONG iPos = iPosSrc; iPos > 0; iPos-- )
  194.         m_index[iPos] = m_index[iPos-1] ;
  195.     
  196.     m_index[0] = index ;
  197.     return UpdateIndex() ;
  198. }
  199. //-------------------------------------------------------------------------//
  200. ULONG CPropMruStor::GetUnusedRecNo() const
  201. {
  202.     BYTE    iPos, bUsed ;
  203.     ULONG   nRec ;
  204.     
  205.     //  For each posssible value between 0 and the limit
  206.     for( nRec=0; nRec < IndexCount(); nRec++ )
  207.     {
  208.         //  For each array element
  209.         for( iPos = 0, bUsed = FALSE; iPos < IndexCount(); iPos++ )
  210.         {
  211.             //  If the value ofthe element equals our test value,
  212.             //  go to next possible value
  213.             if( m_index[iPos].nRec == nRec )
  214.             {
  215.                 bUsed = TRUE ;
  216.                 break ;
  217.             }
  218.         }
  219.         
  220.         if( bUsed ) continue ;
  221.         return nRec ;
  222.     }
  223.     
  224.     ASSERT( FALSE ) ;   // should never happen
  225.     return INVALID_INDEX_VALUE ;
  226. }
  227. //-------------------------------------------------------------------------//
  228. ULONG CPropMruStor::GetRecNo( ULONG iPos ) const
  229. {
  230.     ASSERT( VALID_INDEX_ELEMENT( iPos ) ) ;
  231.     return m_index[iPos].nRec ;
  232. }
  233. //-------------------------------------------------------------------------//
  234. BOOL CPropMruStor::GetRecTitle( ULONG iPos, LPTSTR pszBuf ) const
  235. {
  236.     ASSERT( pszBuf ) ;
  237.     ULONG  nRec ;
  238.     
  239.     if( (nRec = GetRecNo( iPos ))==INVALID_INDEX_VALUE )
  240.     {
  241.         *pszBuf = 0 ;
  242.         return FALSE ;
  243.     }
  244.     
  245.     wsprintf( pszBuf, szRECTITLEFMT, nRec ) ;
  246.     return TRUE ;
  247. }
  248. //-------------------------------------------------------------------------//
  249. HRESULT CPropMruStor::BeginFetch( REFFMTID fmtid, PROPID propid, VARTYPE vt )
  250. {
  251.     HRESULT hr ;
  252.     //  Build the key name and open the key
  253.     if( !SUCCEEDED( (hr = MakeRecKeyName( fmtid, propid, vt )) ) )
  254.         return hr ;
  255.     //  Open the key
  256.     if( !SUCCEEDED( (hr = Open()) ) )
  257.         return hr ;
  258.     //  Load MRU order index.
  259.     return LoadIndex( m_index ) ;
  260. }
  261. //-------------------------------------------------------------------------//
  262. HRESULT CPropMruStor::FetchNext( LONG& iStart, PROPVARIANT_DISPLAY& var )
  263. {
  264.     TCHAR  szValName[cchVALNAME] ;
  265.     //  Ensure stor is open
  266.     if( !IsOpen() )
  267.         return E_ACCESSDENIED ;
  268.     var.bstrDisplay = NULL ;
  269.     //  Move through records beginning with requested position.
  270.     for( LONG iPos = iStart; iPos < (LONG)IndexCount(); iPos++ )
  271.     {    
  272.         if( !GetRecTitle( iPos, szValName ) )
  273.             continue ;
  274.     
  275.         if( !SUCCEEDED( PropVariantReadRegistry( m_hKey, szValName, var.val ) ) )
  276.             continue ;
  277.         iStart = ++iPos ;
  278.         return S_OK ;
  279.     }
  280.     return E_FAIL ;
  281. }
  282. #if 0 // (implemented, but not used)
  283. //-------------------------------------------------------------------------//
  284. HANDLE CPropMruStor::EnumFirst( REFFMTID fmtid, PROPID propid, VARTYPE vt, OUT PROPVARIANT& var )
  285. {
  286.     HRESULT hr ;    
  287.     ENUM*  pEnum = NULL ;
  288.     //  Build the key name
  289.     if( !SUCCEEDED( (hr = MakeRecKeyName( fmtid, propid, vt )) ) )
  290.         return pEnum ;
  291.     //  Open the key
  292.     if( !SUCCEEDED( (hr = Open()) ) )
  293.         return pEnum ;
  294.     //  Load the MRU index
  295.     LoadIndex( m_index ) ;
  296.     for( ULONG iPos =0; iPos< IndexCount(); iPos++ )
  297.     {
  298.         TCHAR  szValName[cchVALNAME] ;
  299.         if( !GetRecTitle( iPos, szValName ) )
  300.             continue ;
  301.         
  302.         if( !SUCCEEDED( PropVariantReadRegistry( m_hKey, szValName, var ) ) )
  303.             continue ;
  304.         if( (pEnum = new ENUM )!=NULL )
  305.             pEnum->iPos = iPos ;
  306.         break ;
  307.     }
  308.     return pEnum ;
  309. }
  310. //-------------------------------------------------------------------------//
  311. BOOL CPropMruStor::EnumNext( HANDLE hEnum, PROPVARIANT& var ) const
  312. {
  313.     BOOL    bRet = FALSE ;
  314.     ENUM*  pEnum = (ENUM*)hEnum ;
  315.     if( (m_hKey && pEnum) ) 
  316.     {
  317.         for( pEnum->iPos++; pEnum->iPos < IndexCount(); pEnum->iPos++ )
  318.         {
  319.             TCHAR  szValName[cchVALNAME] ;
  320.             if( !GetRecTitle( pEnum->iPos, szValName ) )
  321.                 continue ;
  322.         
  323.             if( !SUCCEEDED( PropVariantReadRegistry( m_hKey, szValName, var ) ) )
  324.                 continue ;
  325.             
  326.             bRet = TRUE ;
  327.             break ;
  328.         }
  329.     }
  330.     return bRet ;
  331. }
  332. //-------------------------------------------------------------------------//
  333. void CPropMruStor::EndEnum( HANDLE& hEnum ) const
  334. {
  335. ENUM* pEnum = (ENUM*)hEnum ;
  336. if( pEnum )
  337. {
  338. delete pEnum ;
  339. hEnum = NULL ;
  340. }
  341. }
  342. #endif //0
  343. //-------------------------------------------------------------------------//
  344. HRESULT CPropMruStor::MakeRecKeyName( REFFMTID fmtid, PROPID propid, VARTYPE vt )
  345. {
  346.     HRESULT hr ;
  347.     LPOLESTR pwszFmtID    = NULL ;
  348.     LPTSTR   psz          = NULL ;
  349.     USES_CONVERSION ;
  350.     if( SUCCEEDED( (hr = StringFromCLSID( fmtid, &pwszFmtID )) ) )
  351.     {
  352.         int cch = lstrlen( m_pszRootSubKey ) +
  353.                   lstrlenW( pwszFmtID ) + 16 +
  354.                   lstrlen( szRECKEYNAMEFMT ) ;
  355.                   
  356.         if( (psz = new TCHAR[cch])!=NULL )
  357.         {
  358.             wsprintf( psz, szRECKEYNAMEFMT,
  359.                       m_pszRootSubKey, W2T( pwszFmtID ), propid, vt ) ;
  360.             ClearRecKeyName() ;
  361.             m_pszRecSubKey = psz ;
  362.         }            
  363.         else
  364.             hr = E_OUTOFMEMORY ;
  365.     }
  366.     if( pwszFmtID ) CoTaskMemFree( pwszFmtID ) ;
  367.     return hr ;
  368. }
  369. //-------------------------------------------------------------------------//
  370. void CPropMruStor::ClearRecKeyName()
  371. {
  372.     if( m_pszRecSubKey )
  373.     {
  374.         delete [] m_pszRecSubKey ;
  375.         m_pszRecSubKey = NULL ;
  376.     }
  377. }
  378. //-------------------------------------------------------------------------//
  379. HRESULT CPropMruStor::LoadIndex( PVOID pvDest )
  380. {
  381.     ASSERT( IsOpen() ) ;
  382.     HRESULT hr ;
  383.     DWORD   dwType = REG_BINARY,
  384.             cbDest = sizeof(m_index),
  385.             dwRet ;
  386.     dwRet = RegQueryValueEx( m_hKey, szINDEXVALNAME, 0L, &dwType, 
  387.                              (LPBYTE)pvDest, &cbDest ) ;
  388.     if( S_OK == (hr = HRESULT_FROM_WIN32( dwRet )) )
  389.     {
  390.         if( pvDest != &m_index )
  391.             memcpy( m_index, pvDest, sizeof(m_index) ) ;
  392.         return S_OK ;
  393.     }
  394.     else if( ERROR_MORE_DATA == dwRet )
  395.     {
  396.         // registry value corruption.
  397.         RegDeleteValue( m_hKey, szINDEXVALNAME ) ;
  398.         ASSERT( FALSE ) ; 
  399.         hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) ;
  400.     }
  401.     return hr ;
  402. }
  403. //-------------------------------------------------------------------------//
  404. HRESULT CPropMruStor::UpdateIndex()
  405. {
  406.     ASSERT( IsOpen() ) ;
  407.     DWORD dwRet = RegSetValueEx( m_hKey, szINDEXVALNAME, 0L, REG_BINARY,
  408.                        (LPBYTE)m_index, sizeof(m_index) ) ;
  409.     return HRESULT_FROM_WIN32( dwRet ) ;
  410. }
  411. //-------------------------------------------------------------------------//
  412. HRESULT CPropMruStor::Open( REGSAM sam )
  413. {
  414.     ASSERT( m_hKeyRoot ) ;
  415.     ASSERT( m_pszRecSubKey && *m_pszRecSubKey ) ;
  416.     HRESULT hr ;
  417.     HKEY    hKey = NULL ;
  418.     DWORD   dwDisp = 0L,
  419.             dwRet ;
  420.     dwRet = RegCreateKeyEx( m_hKeyRoot, m_pszRecSubKey, 0L, NULL, 
  421.                             REG_OPTION_NON_VOLATILE, sam, NULL, 
  422.                             &hKey, &dwDisp ) ;
  423.     if( S_OK == (hr = HRESULT_FROM_WIN32( dwRet )) )
  424.     {
  425.         Close() ;
  426.         m_hKey = hKey ;
  427.     }
  428.     return hr ;
  429. }
  430. //-------------------------------------------------------------------------//
  431. void CPropMruStor::Close()
  432. {
  433.     if( m_hKey )
  434.     {
  435.         RegCloseKey( m_hKey ) ;
  436.         m_hKey = NULL ;
  437.     }
  438. }