ptsniff.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. //  PTsniff.cpp - API for quick determination of file type support.
  4. //
  5. //-------------------------------------------------------------------------//
  6. #include "pch.h"
  7. #include "PTsniff.h"
  8. #include "dictbase.h"
  9. typedef struct tagPTSRV_FILE_TYPES
  10. {
  11.     PTSRV_FILETYPE    fileType ;
  12.     PTSRV_FILECLASS   fileClass ;
  13.     LPCTSTR             pszExt ;
  14. } PTSRV_FILE_TYPES, *PPTSRV_FILE_TYPES, *LPPTSRV_FILE_TYPES;
  15. static const PTSRV_FILE_TYPES ptsrv_file_types[]  =
  16. {
  17.     { PTSFTYPE_DOC,  PTSFCLASS_OFFICEDOC, TEXT("DOC") },
  18.     { PTSFTYPE_XLS,  PTSFCLASS_OFFICEDOC, TEXT("XLS") },
  19.     { PTSFTYPE_PPT,  PTSFCLASS_OFFICEDOC, TEXT("PPT") },
  20.     { PTSFTYPE_BMP,  PTSFCLASS_IMAGE, TEXT("BMP") },
  21.     { PTSFTYPE_EPS,  PTSFCLASS_IMAGE, TEXT("EPS") },
  22.     { PTSFTYPE_GIF,  PTSFCLASS_IMAGE, TEXT("GIF") },
  23.     { PTSFTYPE_JPG,  PTSFCLASS_IMAGE, TEXT("JPG") },
  24.     { PTSFTYPE_FPX,  PTSFCLASS_IMAGE, TEXT("FPX") },
  25.     { PTSFTYPE_JPG,  PTSFCLASS_IMAGE, TEXT("JPEG") },
  26.     { PTSFTYPE_PCD,  PTSFCLASS_IMAGE, TEXT("PCD") },
  27.     { PTSFTYPE_PCX,  PTSFCLASS_IMAGE, TEXT("PCX") },
  28.     { PTSFTYPE_PICT, PTSFCLASS_IMAGE, TEXT("PICT") },
  29.     { PTSFTYPE_PNG,  PTSFCLASS_IMAGE, TEXT("PNG") },
  30.     { PTSFTYPE_TGA,  PTSFCLASS_IMAGE, TEXT("TGA") },
  31.     { PTSFTYPE_TIF,  PTSFCLASS_IMAGE, TEXT("TIF") },
  32.     { PTSFTYPE_TIF,  PTSFCLASS_IMAGE, TEXT("TIFF") },
  33.     { PTSFTYPE_AVI,  PTSFCLASS_VIDEO,  TEXT("avi") },
  34.     { PTSFTYPE_WAV,  PTSFCLASS_AUDIO,  TEXT("wav") },
  35.     { PTSFTYPE_MIDI, PTSFCLASS_AUDIO,  TEXT("mid") },
  36.     { PTSFTYPE_MIDI, PTSFCLASS_AUDIO,  TEXT("midi") },
  37.     { PTSFTYPE_HTML, PTSFCLASS_UNSUPPORTED, TEXT("htm") },
  38.     { PTSFTYPE_HTML, PTSFCLASS_UNSUPPORTED, TEXT("html") },
  39.     { PTSFTYPE_XML,  PTSFCLASS_UNSUPPORTED, TEXT("xml") },
  40.     { PTSFTYPE_LNK,  PTSFCLASS_UNSUPPORTED, TEXT("lnk") },
  41.     { PTSFTYPE_XML,  PTSFCLASS_UNSUPPORTED, TEXT("url") },
  42. } ;
  43. #define cFILETYPES sizeof(ptsrv_file_types)/sizeof(PTSRV_FILE_TYPES)
  44. //-------------------------------------------------------------------------//
  45. LPCTSTR ExtFromPath( LPCTSTR pszPath )
  46. {
  47.     LPCTSTR pszExt = NULL ;
  48.     for( int i = lstrlen( pszPath )-1; i>=0; i-- )
  49.     {
  50.         if( pszPath[i]==TEXT('.') )  {
  51.             pszExt = &pszPath[i+1] ;
  52.             break ;
  53.         }
  54.     }
  55.     return pszExt ;
  56. }
  57. //-------------------------------------------------------------------------//
  58. BOOL WINAPI IsPTsrvKnownFileType(
  59.     LPCTSTR pszPath,
  60.     OUT OPTIONAL PTSRV_FILETYPE* pType,
  61.     OUT OPTIONAL PTSRV_FILECLASS* pClass )
  62. {
  63.     BOOL    bRet = FALSE ;
  64.     if( pType )  *pType  = PTSFTYPE_UNKNOWN ;
  65.     if( pClass ) *pClass = PTSFCLASS_UNKNOWN ;
  66.     LPCTSTR pszExt = ExtFromPath( pszPath ) ;
  67.     if( pszExt && *pszExt )
  68.     {
  69.         for( int j=0, max = cFILETYPES ; j < max; j++ )
  70.         {
  71.             if( lstrcmpi( pszExt, ptsrv_file_types[j].pszExt )==0 )
  72.             {
  73.                 if( pType )  *pType  = ptsrv_file_types[j].fileType ;
  74.                 if( pClass ) *pClass = ptsrv_file_types[j].fileClass ;
  75.                 bRet = TRUE ;
  76.                 break ;
  77.             }
  78.         }
  79.     }
  80.     return bRet ;
  81. }
  82. //-------------------------------------------------------------------------//
  83. BOOL WINAPI IsPropSetStgFmt( IN LPCTSTR pszPath, ULONG dwStgFmt, OUT OPTIONAL LPBOOL pbWriteAccess )
  84. {
  85.     LPPROPERTYSETSTORAGE ppss = NULL ;
  86.     USES_CONVERSION ;
  87.     if( pbWriteAccess )
  88.     {
  89.         *pbWriteAccess = FALSE;
  90.         if( SUCCEEDED( StgOpenStorageEx( T2CW( pszPath ), STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
  91.                        dwStgFmt, 0, 0, NULL, IID_IPropertySetStorage, (PVOID*)&ppss ) ) )
  92.         {
  93.             *pbWriteAccess = FALSE;
  94.             ppss->Release();
  95.             return TRUE;
  96.         }
  97.     }
  98.     if( SUCCEEDED( StgOpenStorageEx( T2W( (LPTSTR)pszPath), STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE,
  99.                                      dwStgFmt, 0, 0, NULL, IID_IPropertySetStorage, (PVOID*)&ppss )) )
  100.     {
  101.         ppss->Release() ;
  102.         return TRUE ;
  103.     }
  104.     return FALSE ;
  105. }
  106. //-------------------------------------------------------------------------//
  107. EXTERN_C BOOL WINAPI IsOfficeDocFile( IN LPCTSTR pszPath )
  108. {
  109.     PTSRV_FILECLASS ptfc ;
  110.     return IsPTsrvKnownFileType( pszPath, NULL, &ptfc ) &&
  111.            PTSFCLASS_OFFICEDOC == ptfc ;
  112. }
  113. //-------------------------------------------------------------------------//
  114. //  File extension wrapper
  115. typedef class tagPROPFILEEXT
  116. {
  117. public:
  118.     tagPROPFILEEXT() : _bAdvanced(1) { *_szExt = 0 ; }
  119.     tagPROPFILEEXT( LPCTSTR pszExt ) : _bAdvanced(1)  {
  120.         if( pszExt ) lstrcpyn( _szExt, pszExt, ARRAYSIZE(_szExt) ) ;
  121.         else *_szExt = 0 ;
  122.     }
  123.     BOOL operator == ( const tagPROPFILEEXT& other ) const   {
  124.         return  _bAdvanced == other._bAdvanced && 
  125.                 0 == lstrcmpi( _szExt, other._szExt ) ;
  126.     }
  127.     ULONG Hash() const    {
  128.         return HashStringi( (LPTSTR)_szExt ) + (_bAdvanced ? 1 : 0) ;
  129.     }
  130.     TCHAR _szExt[MAX_PATH/2] ;
  131.     BOOL  _bAdvanced ;
  132. } PROPFILEEXT, *PPROPFILEEXT, *LPPROPFILEEXT ;
  133. //-------------------------------------------------------------------------//
  134. //  Global map of file name extension to IAdvancedPropertyServer clsids.
  135. typedef TDictionaryBase< PROPFILEEXT, CLSID >
  136.         CFileAssocMapBase ;
  137. class CFileAssocMap : public CFileAssocMapBase
  138. //-------------------------------------------------------------------------//
  139. {
  140. public:
  141.     CFileAssocMap()
  142.         :   CFileAssocMapBase( 4 /*allocation block size*/ ) {}
  143.     BOOL    Lookup( LPCTSTR pszExt, BOOL bAdvanced, CLSID* pclsidServer ) const ;
  144.     BOOL    Insert( LPCTSTR pszExt, BOOL bAdvanced, REFCLSID clsidServer ) ;
  145. protected:
  146.     virtual ULONG HashKey( const tagPROPFILEEXT& ext ) const {
  147.         return ext.Hash() ;
  148.     }
  149.     virtual BOOLEAN IsEqual( PROPFILEEXT& key1, PROPFILEEXT& key2, BOOLEAN& bHandled ) const {
  150.         bHandled = TRUE ;  return (BOOLEAN)(key1 == key2) ;
  151.     }
  152. } ;
  153. CFileAssocMap _theFileAssocMap ;    // static global instance
  154. //-------------------------------------------------------------------------//
  155. BOOL CFileAssocMap::Lookup( LPCTSTR pszExt, BOOL bAdvanced, CLSID* pclsidServer ) const
  156. {
  157.     PROPFILEEXT ext( pszExt ) ;
  158.     ext._bAdvanced = bAdvanced ;
  159.     return (pszExt && *pszExt) ? CFileAssocMapBase::Lookup( ext, *pclsidServer ) : FALSE ;
  160. }
  161. //-------------------------------------------------------------------------//
  162. BOOL CFileAssocMap::Insert( LPCTSTR pszExt, BOOL bAdvanced, REFCLSID clsidServer )
  163. {
  164.     PROPFILEEXT ext( pszExt ) ;
  165.     CLSID       clsid = clsidServer ;
  166.     int         c = Count() ;
  167.     ext._bAdvanced = bAdvanced ;
  168.     if( pszExt && *pszExt )
  169.     {
  170.         if( Lookup( pszExt, bAdvanced, &clsid ) )
  171.             return TRUE ;
  172.         (*this)[ext] = clsid ;
  173.         return c < Count() ;
  174.     }
  175.     return FALSE ;
  176. }
  177. //-------------------------------------------------------------------------//
  178. //  Retrieves the appropriate server for the indicated source file.
  179. STDMETHODIMP GetPropServerClassForFile(
  180.     IN LPCTSTR pszPath,
  181.     BOOL bAdvanced,
  182.     OUT LPCLSID pclsid )
  183. {
  184.     HRESULT hr = E_FAIL;
  185.     LPCTSTR pszExt = NULL;
  186.     TCHAR   szSubKey[MAX_PATH];
  187.     TCHAR   szProgID[MAX_PATH];
  188.     USES_CONVERSION;
  189.     static LPCTSTR pszAdvancedHandlerKey = TEXT("ShellEx\AdvancedPropertyHandlers"),
  190.                    pszBasicHandlerKey    = TEXT("ShellEx\BasicPropertyHandlers");
  191.     LPCTSTR pszHandlerKey = bAdvanced ? pszAdvancedHandlerKey : pszBasicHandlerKey ;
  192.     ASSERT( pclsid ) ;
  193.     ASSERT( pszPath && *pszPath ) ;
  194.     *pclsid = CLSID_NULL ;
  195.     if( (pszExt = PathFindExtension( pszPath )) == NULL )
  196.         return hr;
  197.     lstrcpy( szSubKey, pszExt );
  198.     //  check our cache for an association...
  199.     if( _theFileAssocMap.Lookup( pszExt, bAdvanced, pclsid ) )
  200.         return S_OK ;
  201.     HKEY  hkeyExt = NULL,
  202.           hkeyClsid = NULL  ;
  203.     DWORD dwType, cbSize, dwRet ;
  204.     BOOL  bContinue = TRUE ;
  205.     while( bContinue )
  206.     {
  207.         //  Open subkey
  208.         dwRet = RegOpenKeyEx( HKEY_CLASSES_ROOT, szSubKey, 0L, KEY_READ, &hkeyExt ) ;
  209.         if( ERROR_SUCCESS == dwRet )
  210.         {
  211.             //  Enumerate ShellEx\{Advanced/Basic}PropertyHandlers
  212.             dwRet = RegOpenKeyEx( hkeyExt, pszHandlerKey,
  213.                                   0L, KEY_READ, &hkeyClsid ) ;
  214.             if( ERROR_SUCCESS == dwRet )
  215.             {
  216.                 for( DWORD i = 0; bContinue && ERROR_SUCCESS == dwRet; i++ )
  217.                 {
  218.                     TCHAR szClsid[128],
  219.                           szClass[128] ;
  220.                     DWORD cchClsid = ARRAYSIZE(szClsid),
  221.                           cchClass = ARRAYSIZE(szClass) ;
  222.                     FILETIME ft ;
  223.                     dwRet = RegEnumKeyEx( hkeyClsid, i, szClsid, &cchClsid, NULL,
  224.                                           szClass, &cchClass, &ft ) ;
  225.                     if( ERROR_SUCCESS == dwRet )
  226.                     {
  227.                         if( SUCCEEDED( CLSIDFromString( T2W(szClsid), pclsid ) ) )
  228.                         {
  229.                             bContinue = FALSE ;
  230.                             //  cache the extension, server association.
  231.                             _theFileAssocMap.Insert( pszExt, bAdvanced, *pclsid ) ;
  232.                             hr = S_OK ;
  233.                         }
  234.                     }
  235.                 }
  236.                 RegCloseKey( hkeyClsid ) ;
  237.                 hkeyClsid = NULL ;
  238.             }
  239.             //  If we don't have a server at this point, check for progID...
  240.             if( bContinue )
  241.             {
  242.                 cbSize = sizeof(szProgID) ;
  243.                 dwRet = RegQueryValueEx( hkeyExt, NULL, 0L, &dwType,
  244.                                         (LPBYTE)szProgID, &cbSize ) ;
  245.                 if( ERROR_SUCCESS == dwRet )
  246.                 {
  247.                     if( 0 == lstrcmpi( szSubKey, szProgID ) )
  248.                         bContinue = FALSE ; // progid == description; weird case.
  249.                     else
  250.                         lstrcpy( szSubKey, szProgID ); // got progID; loop and try again
  251.                 }
  252.                 else
  253.                     bContinue = FALSE ;
  254.             }
  255.             RegCloseKey( hkeyExt ) ;
  256.             hkeyExt = NULL ;
  257.         }
  258.         else
  259.             bContinue = FALSE ;
  260.     }
  261.     return hr ;
  262. }
  263. //-------------------------------------------------------------------------//
  264. //  Retrieves the appropriate server for the indicated source file.
  265. BOOL OpenRegKeyForExtension( LPCTSTR pszExt, REGSAM samDesired, OUT HKEY* phKey )
  266. {
  267.     ASSERT( pszExt && *pszExt );
  268.     ASSERT( phKey );
  269.     HKEY  hKey;
  270.     TCHAR szSubKey[MAX_PATH];
  271.     BOOL  bContinueNext = TRUE;
  272.     *phKey = NULL;
  273.     lstrcpyn( szSubKey, pszExt, ARRAYSIZE(szSubKey) );
  274.     while( bContinueNext )
  275.     {
  276.         bContinueNext = FALSE;
  277.         if( RegOpenKeyEx( HKEY_CLASSES_ROOT, szSubKey,
  278.                           0L, samDesired|KEY_READ, &hKey ) == ERROR_SUCCESS )
  279.         {
  280.             if( *phKey )
  281.                 RegCloseKey( *phKey );
  282.             *phKey = hKey;
  283.             TCHAR szProgID[MAX_PATH];
  284.             DWORD dwType,
  285.                   cbRet = sizeof(szProgID)+sizeof(TCHAR);
  286.             HKEY  hkeyShellEx = NULL;
  287.             //  If we have a shellex subkey here, no neec to go further.
  288.             if( RegOpenKeyEx( hKey, TEXT("ShellEx"), 0L, KEY_READ, &hkeyShellEx ) == ERROR_SUCCESS )
  289.                 RegCloseKey( hkeyShellEx );
  290.             else  // no shellex key, so pine down further.
  291.             {
  292.                 if( RegQueryValueEx( hKey, NULL, NULL,
  293.                         &dwType, (LPBYTE)szProgID, &cbRet ) == ERROR_SUCCESS && *szProgID )
  294.                 {
  295.                     lstrcpyn( szSubKey, szProgID, ARRAYSIZE(szSubKey) );
  296.                     bContinueNext = TRUE;
  297.                 }
  298.                 else
  299.                 {
  300.                     //  If our intention is to write out a shellex subkey, and we ran to the 
  301.                     //  last progid in the chain without finding one, we slam one in.
  302.                     if( samDesired & KEY_WRITE )
  303.                     {
  304.                         DWORD dwDisp = 0L;
  305.                         if( RegCreateKeyEx( hKey, TEXT("ShellEx"), 0L, NULL, 0, KEY_WRITE, NULL,
  306.                                             &hkeyShellEx, &dwDisp ) == ERROR_SUCCESS )
  307.                         {
  308.                             RegCloseKey( hkeyShellEx );
  309.                         }
  310.                     }
  311.                 }
  312.             }
  313.         }
  314.     }
  315.     return *phKey != NULL;
  316. }
  317. HRESULT RegisterPropServerClassForExtension( IN LPCTSTR pszExt, REFCLSID clsid )
  318. {
  319.     OLECHAR szClsid[48] ;
  320.     HRESULT hr = E_FAIL ;
  321.     if( SUCCEEDED( (hr = StringFromGUID2( clsid, szClsid, ARRAYSIZE(szClsid) )) ) )
  322.     {
  323.         HKEY hKey, hSubKey ;
  324.         DWORD dwErr, dwDisp ;
  325.         if( !OpenRegKeyForExtension( pszExt, KEY_WRITE, &hKey ) )
  326.             return E_FAIL ;
  327.         dwErr = RegCreateKeyEx( hKey, TEXT("ShellEx\AdvancedPropertyHandlers"),
  328.                                 0L, NULL, 0L, KEY_WRITE, NULL, &hSubKey, &dwDisp ) ;
  329.         hr = HRESULT_FROM_WIN32( dwErr ) ;
  330.         if( ERROR_SUCCESS == dwErr )
  331.         {
  332.             HKEY hkeyClsid ;
  333.             dwErr = RegCreateKeyEx( hSubKey, szClsid, 0L, NULL, 0L, KEY_WRITE, NULL,
  334.                                     &hkeyClsid, &dwDisp ) ;
  335.             hr = HRESULT_FROM_WIN32( dwErr ) ;
  336.             if( ERROR_SUCCESS == dwErr )
  337.                 RegCloseKey( hkeyClsid ) ;
  338.             RegCloseKey( hSubKey ) ;
  339.         }
  340.         RegCloseKey( hKey ) ;
  341.     }
  342.     return hr ;
  343. }