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

Windows Kernel

Development Platform:

Visual C++

  1. #include "priv.h"
  2. #include "guids.h"
  3. ///////////////
  4. //
  5. // This file contains the implementation of the column handlers
  6. // Called from fstreex's FS_HandleExtendedColumn
  7. //
  8. #define PIDDSI_COMPANY 0x0000000F
  9. STDAPI CExeDllColumnProvider_CreateInstance(IUnknown *punk, REFIID riid, void **pcpOut);
  10. //  FMTID_ExeDllInformation,
  11. //// {0CEF7D53-FA64-11d1-A203-0000F81FEDEE}
  12. static const SHCOLUMNID SCID_CompanyName        =   { //from the Doc Summary information.
  13.     { 0xd5cdd502, 0x2e9c, 0x101b, 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae  }//this one is overloaded.
  14.     , PIDDSI_COMPANY};
  15. static const SHCOLUMNID SCID_FileDescription    =   {
  16.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  17.     , PIDSI_FileDescription};
  18. static const SHCOLUMNID SCID_FileVersion        =   { 
  19.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  20.     , PIDSI_FileVersion};
  21. static const SHCOLUMNID SCID_InternalName       =   { 
  22.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  23.     , PIDSI_InternalName};  
  24. static const SHCOLUMNID SCID_OriginalFileName   =   {    
  25.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  26.     , PIDSI_OriginalFileName};
  27. static const SHCOLUMNID SCID_ProductName        =   {
  28.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  29.     , PIDSI_ProductName};
  30. static const SHCOLUMNID SCID_ProductVersion     =   {
  31.     { 0xcef7d53, 0xfa64, 0x11d1, 0xa2, 0x3, 0x0, 0x0, 0xf8, 0x1f, 0xed, 0xee }
  32.     , PIDSI_ProductVersion};
  33. // A PROPVARIANT can hold a few more types than a VARIANT can.  We convert the types that are
  34. // only supported by a PROPVARIANT into equivalent VARIANT types.
  35. typedef struct {
  36.     const SHCOLUMNID *pscid;
  37.     DWORD id;
  38.     DWORD dwWid;
  39.     VARTYPE vt;             // Note that the type of a given FMTID/PID pair is a known, fixed value
  40. } COLMAP;
  41. // W because pidl is always converted to widechar filename
  42. const LPCTSTR c_szExeDllExtensions[] = {
  43.     TEXT(".DLL"), TEXT(".EXE"), NULL
  44. };
  45. const COLMAP c_rgExeDllColumns[] = {
  46.     { &SCID_CompanyName,IDS_EXCOL_CompanyName, 20, VT_BSTR },
  47.     { &SCID_FileDescription,IDS_EXCOL_FileDescription, 20, VT_BSTR },
  48.     { &SCID_FileVersion,IDS_EXCOL_FileVersion, 20, VT_BSTR },
  49.     { &SCID_InternalName,IDS_EXCOL_InternalName, 20, VT_BSTR },
  50.     { &SCID_OriginalFileName,IDS_EXCOL_OriginalFileName, 20, VT_BSTR },
  51.     { &SCID_ProductName,IDS_EXCOL_ProductName, 20, VT_BSTR },
  52.     { &SCID_ProductVersion,IDS_EXCOL_ProductVersion, 20, VT_BSTR },
  53.    
  54. };
  55. class CDefColumnProvider :
  56.     public IPersist, 
  57.     public IColumnProvider
  58. {
  59.     // IUnknown methods
  60. public:
  61.     virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvOut)
  62.     {
  63.         static const QITAB qit[] = {
  64.             QITABENT(CDefColumnProvider, IColumnProvider),           // IID_IColumnProvider
  65.             QITABENT(CDefColumnProvider, IPersist),           // IID_IColumnProvider
  66.             { 0 },
  67.         };
  68.         return QISearch(this, qit, riid, ppvOut);
  69.     };
  70.     
  71.     virtual STDMETHODIMP_(ULONG) AddRef()
  72.     {
  73.         return InterlockedIncrement(&_cRef);
  74.     };
  75.     virtual STDMETHODIMP_(ULONG) Release()
  76.     {
  77.         if (InterlockedDecrement(&_cRef))
  78.             return _cRef;
  79.         delete this;
  80.         return 0;
  81.     };
  82.     // *** IPersist methods ***
  83.     virtual STDMETHODIMP GetClassID(CLSID *pClassID) { *pClassID = *_pclsid; return S_OK; };
  84.     // IColumnProvider methods
  85.     virtual STDMETHODIMP Initialize(LPCSHCOLUMNINIT psci) {return E_NOTIMPL;};  // Inheriting class is required to impl
  86.     virtual STDMETHODIMP GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci);
  87.     virtual STDMETHODIMP GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData) = 0;
  88.     virtual STDMETHODIMP_(ULONG) GetColumnCount() { return _iCount; };
  89. protected:
  90.     CDefColumnProvider(const CLSID *pclsid, const COLMAP rgColMap[], int iCount, const LPCTSTR rgExts[]) : 
  91.        _cRef(1), _pclsid(pclsid), _rgColumns(rgColMap), _iCount(iCount), _rgExts(rgExts)
  92.        {
  93.            DllAddRef();
  94.        };
  95.     virtual ~CDefColumnProvider() 
  96.     {
  97.         DllRelease();
  98.     };
  99.     // helper fns
  100.     BOOL _IsHandled(LPCTSTR szExtension);
  101.     int _iCount;
  102.     const COLMAP  *_rgColumns;
  103. private:
  104.     // variables
  105.     long _cRef;
  106.     const CLSID * _pclsid;
  107.     const LPCTSTR *_rgExts;
  108. };
  109. // the index is an arbitrary zero based index used for enumeration
  110. STDMETHODIMP CDefColumnProvider::GetColumnInfo(DWORD dwIndex, SHCOLUMNINFO *psci)
  111. {
  112.     ZeroMemory(psci, sizeof(*psci));
  113.     
  114.     if (dwIndex < (UINT) _iCount)
  115.     {
  116.         TCHAR szTitle[MAX_COLUMN_NAME_LEN];
  117.         
  118.         psci->scid = *_rgColumns[dwIndex].pscid;
  119.         psci->cChars = _rgColumns[dwIndex].dwWid;
  120.         psci->vt = _rgColumns[dwIndex].vt;
  121.         psci->fmt = LVCFMT_LEFT;
  122.         psci->csFlags = SHCOLSTATE_TYPE_STR;
  123.         // Not called very often, easier to just load from resource file
  124.         LoadString(HINST_THISDLL, _rgColumns[dwIndex].id, szTitle, ARRAYSIZE(szTitle));
  125.         SHTCharToUnicode(szTitle, psci->wszTitle, ARRAYSIZE(psci->wszTitle));
  126.         SHTCharToUnicode(szTitle, psci->wszDescription, ARRAYSIZE(psci->wszDescription));
  127.         return S_OK;
  128.     }
  129.     return S_FALSE;
  130. }
  131. // TODO: there's probably some way to check this via
  132. // the registry. If the BROWSABLE bit is set or something...
  133. BOOL CDefColumnProvider::_IsHandled(LPCTSTR szExtension)
  134. {
  135.     int i=0;
  136.     while (_rgExts[i])
  137.     {
  138.         if (0 == StrCmpI(szExtension, _rgExts[i]))
  139.             return TRUE;
  140.         i++;
  141.     }
  142.     return FALSE;
  143. }
  144. ////////////////////////////////////////////////////////////////////////////////
  145. // Exe and DLL  handler
  146. class CExeDllColumnProvider : 
  147.     public CDefColumnProvider
  148. {
  149.     STDMETHODIMP Initialize(LPCSHCOLUMNINIT psci) {return E_NOTIMPL;};  // We should really do something here.
  150.     STDMETHODIMP GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData);
  151. private:
  152.     // help on initializing base classes: mk:@ivt:vclang/FB/DD/S44B5E.HTM
  153.     CExeDllColumnProvider() : CDefColumnProvider(&CLSID_ExeDllColumnProvider, c_rgExeDllColumns, ARRAYSIZE(c_rgExeDllColumns), c_szExeDllExtensions)
  154.     {
  155.     };
  156.     
  157.     virtual ~CExeDllColumnProvider() 
  158.     {
  159.     };
  160.     // friends
  161.     friend HRESULT CExeDllColumnProvider_CreateInstance(IUnknown *punk, REFIID riid, void **pcpOut);
  162. };
  163. STDMETHODIMP CExeDllColumnProvider::GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvarData)
  164. {
  165.     TCHAR szPath[MAX_PATH];
  166.     HRESULT hr = E_OUTOFMEMORY;
  167.     // should we match against a list of known extensions, or always try to open?
  168.     StrCpyN(szPath, TEXT("C:\"), ARRAYSIZE(szPath));
  169.     // clear our output
  170.     if (!_IsHandled(PathFindExtension(szPath))) //check to see if we should be handling this file.
  171.         return S_FALSE;
  172.     //start stuff specific to the DLL and EXE versioning.
  173.     DWORD   versionISize; //A Dword to receive the size of the whole version structure
  174.     DWORD   dwVestigial;  //A Dword to be ignored.
  175.     LPVOID  pvAllTheInfo; //A pointer to the whole version data structure
  176.     LPTSTR  pszVersionInfo = NULL; //A pointer to the specific version info I am looking for
  177.     UINT    uInfoSize=0;        //the size of the info returned.
  178.     //stolen from Relja's code
  179.     TCHAR   szVersionKey[60];   //a string to hold all the format string for VerQueryValue
  180.     TCHAR   szField[40];        //a temporary variable to get the field-specific formatting info
  181.      struct _VERXLATE 
  182.     {
  183.         WORD wLanguage;
  184.         WORD wCodePage;
  185.     } *lpXlate;                     /* ptr to translations data */
  186.     versionISize=GetFileVersionInfoSize(szPath, &dwVestigial); //gets the version info size.
  187.     pvAllTheInfo= new BYTE[versionISize];
  188.     if (!(pvAllTheInfo)) 
  189.         return E_OUTOFMEMORY; // error, out of memory.
  190.     if (!(GetFileVersionInfo(szPath, dwVestigial, versionISize, pvAllTheInfo)))//assign actual version stuff in TheInfo
  191.     {
  192.         delete (BYTE*) pvAllTheInfo;
  193.         return E_FAIL;// fubar use GetLastError for more info
  194.     }
  195.     //AllTheInfo is now initialized.
  196.     //setup the field name we are looking for based on the SCID passed in
  197.     switch (pscid->pid){
  198.         case PIDDSI_COMPANY: strcpy(szField,TEXT("CompanyName")); break;
  199.         case PIDSI_FileDescription: strcpy(szField,TEXT("FileDescription")); break;
  200.         case PIDSI_FileVersion: strcpy(szField,TEXT("FileVersion")); break;
  201.         case PIDSI_InternalName: strcpy(szField,TEXT("InternalName")); break;
  202.         case PIDSI_OriginalFileName: strcpy(szField,TEXT("OriginalFileName")); break;
  203.         case PIDSI_ProductName: strcpy(szField,TEXT("ProductName")); break;
  204.         case PIDSI_ProductVersion: strcpy(szField,TEXT("ProductVersion")); break;
  205.         default: delete (BYTE*)pvAllTheInfo; return E_FAIL; break;
  206.         };
  207.     //look for the intended language in the examined object.
  208.     //this is a fallthrough set of if statements.
  209.     //on a failure, it just tries the next one, until it runs out of tries.
  210.     if (VerQueryValue(pvAllTheInfo, TEXT("\VarFileInfo\Translation"), (void **)&lpXlate, &uInfoSize))
  211.     {
  212.         wnsprintf(szVersionKey, ARRAYSIZE(szVersionKey), TEXT("\StringFileInfo\%04X%04X\%s"),
  213.                                             lpXlate[0].wLanguage, lpXlate[0].wCodePage, szField);
  214.         if (!VerQueryValue(pvAllTheInfo, szVersionKey, (LPVOID*) &pszVersionInfo, &uInfoSize))
  215.         {
  216. #ifdef UNICODE
  217.         wnsprintf(szVersionKey, ARRAYSIZE(szVersionKey), TEXT("\StringFileInfo\040904B0\%s"),szField);
  218.         if (!VerQueryValue(pvAllTheInfo, szVersionKey,(LPVOID*) &pszVersionInfo, &uInfoSize))
  219. #endif
  220.         {
  221.             wnsprintf(szVersionKey, ARRAYSIZE(szVersionKey), TEXT("\StringFileInfo\040904E4\%s"),szField);
  222.             if (!VerQueryValue(pvAllTheInfo, szVersionKey, (LPVOID*) &pszVersionInfo, &uInfoSize))
  223.             {
  224.                 wnsprintf(szVersionKey, ARRAYSIZE(szVersionKey), TEXT("\StringFileInfo\04090000\%s"),szField);
  225.                 if (!VerQueryValue(pvAllTheInfo, szVersionKey, (LPVOID*) &pszVersionInfo, &uInfoSize))
  226.                 {
  227.                     pszVersionInfo=NULL;
  228.                 }
  229.             
  230.             }
  231.         }
  232.         }
  233.     };
  234.     
  235.     //getting here is success, prepare the output, clean up memory and exit.
  236.     if (pszVersionInfo)
  237.     {
  238.         pvarData->vt = VT_BSTR;
  239.         pvarData->bstrVal = TCharSysAllocString(pszVersionInfo);
  240.         hr = S_OK;
  241.     }
  242.     else
  243.         hr=E_FAIL;
  244.     delete (BYTE*)pvAllTheInfo;
  245.     return hr;
  246. };
  247. STDAPI CExeDllColumnProvider_CreateInstance(IUnknown *punk, REFIID riid, void **pcpOut)
  248. {
  249.     HRESULT hres;
  250.     CExeDllColumnProvider *pdocp = new CExeDllColumnProvider;
  251.     if (pdocp)
  252.     {
  253.         hres = pdocp->QueryInterface(riid, pcpOut);
  254.         pdocp->Release();
  255.     }
  256.     else
  257.     {
  258.         *pcpOut = NULL;
  259.         hres = E_OUTOFMEMORY;
  260.     };
  261.     return hres;
  262. };