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

Windows Kernel

Development Platform:

Visual C++

  1. #include "shellprv.h"
  2. #include "ftascstr.h" //for now, until CoCreateInstance
  3. #include "ftassoc.h" //for now, until CoCreate IAssocInfo
  4. #include "ftenum.h"
  5. #define EHKCR_NONE      0
  6. #define EHKCR_EXT       1
  7. #define EHKCR_PROGID    2
  8. ///////////////////////////////////////////////////////////////////////////////
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //  CFTEnumAssocInfo
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // Contructor / Destructor
  13. CFTEnumAssocInfo::CFTEnumAssocInfo() : _cRef(1)
  14. {
  15.     //DLLAddRef();
  16. }
  17. CFTEnumAssocInfo::~CFTEnumAssocInfo()
  18. {
  19.     //DLLRelease();
  20. }
  21. ///////////////////////////////////////////////////////////////////////////////
  22. // IUnknown methods
  23. HRESULT CFTEnumAssocInfo::QueryInterface(REFIID riid, PVOID* ppv)
  24. {
  25.     //nothing for now
  26.     return E_NOTIMPL;
  27. }
  28. ULONG CFTEnumAssocInfo::AddRef()
  29. {
  30.     return InterlockedIncrement(&_cRef);
  31. }
  32. ULONG CFTEnumAssocInfo::Release()
  33. {
  34.     if (InterlockedDecrement(&_cRef) > 0)
  35.         return _cRef;
  36.     delete this;
  37.     return 0;
  38. }
  39. ///////////////////////////////////////////////////////////////////////////////
  40. // IEnum methods
  41. HRESULT CFTEnumAssocInfo::Init(ASENUM asenumFlags, LPTSTR pszStr, 
  42.                                AIINIT aiinitFlags)
  43. {
  44.     HRESULT hres = E_INVALIDARG;
  45.     if (((ASENUM_PROGID & asenumFlags) && !(ASENUM_EXT & asenumFlags)) ||
  46.         (!(ASENUM_PROGID & asenumFlags) && (ASENUM_EXT & asenumFlags)) ||
  47.         (ASENUM_ACTION & asenumFlags) )
  48.     {
  49.         hres = S_OK;
  50.         _asenumFlags = asenumFlags;
  51.         _aiinitFlags = aiinitFlags;
  52.         if (pszStr)
  53.             StrCpyN(_szInitStr, pszStr, ARRAYSIZE(_szInitStr));
  54.         else
  55.             _szInitStr[0] = 0;
  56.     }
  57.     return hres;
  58. }
  59. HRESULT CFTEnumAssocInfo::Next(IAssocInfo** ppAI)
  60. {
  61.     HRESULT hres = E_FAIL;
  62.     TCHAR szStr[MAX_FTMAX];
  63.     DWORD cchStr = ARRAYSIZE(szStr);
  64.     AIINIT aiinitFlags = 0;
  65.     *szStr = 0;
  66.     switch(_aiinitFlags)
  67.     {
  68.         // We go through the registry
  69.         case AIINIT_NONE:
  70.         {
  71.             switch(_asenumFlags & ASENUM_MAINMASK)
  72.             {
  73.                 case ASENUM_EXT:
  74.                     hres = _EnumHKCR(_asenumFlags, szStr, &cchStr);
  75.                     aiinitFlags = AIINIT_EXT;
  76.                     break;
  77.                 case ASENUM_PROGID:
  78.                     hres = _EnumHKCR(_asenumFlags, szStr, &cchStr);
  79.                     aiinitFlags = AIINIT_PROGID;
  80.                     break;
  81.                 default:
  82.                     hres = E_INVALIDARG;
  83.                     break;
  84.             }
  85.             break;
  86.         }
  87.         // In theory, we go through the value linked to a progID
  88.         case AIINIT_PROGID:
  89.         {
  90.             switch(_asenumFlags & ASENUM_MAINMASK)
  91.             {
  92.                 case ASENUM_EXT:
  93.                     hres = _EnumHKCR(_asenumFlags, szStr, &cchStr);
  94.                     aiinitFlags = AIINIT_EXT;
  95.                     break;
  96.                 case ASENUM_ACTION:
  97.                     hres = _EnumProgIDActions(szStr, &cchStr);
  98.                     break;
  99.                 default:
  100.                     hres = E_INVALIDARG;
  101.                     break;
  102.             }
  103.             break;
  104.         }
  105.         default:
  106.             hres = E_INVALIDARG;
  107.             break;
  108.     }
  109.     if (SUCCEEDED(hres) && (S_FALSE != hres))
  110.     {
  111.         if (*szStr)
  112.         {
  113.             *ppAI = new CFTAssocInfo();
  114.             if (*ppAI)
  115.             {
  116.                 if (ASENUM_ACTION != (_asenumFlags & ASENUM_MAINMASK))
  117.                     hres = (*ppAI)->Init(aiinitFlags, szStr);
  118.                 else
  119.                     hres = (*ppAI)->InitComplex(AIINIT_PROGID, _szInitStr, AIINIT_ACTION, szStr);
  120.             }
  121.             else
  122.                 hres = E_OUTOFMEMORY;
  123.         }
  124.         else
  125.             hres = E_FAIL;
  126.     }
  127.     return hres;
  128. }
  129. // This beast goes through the HKCR reg key and check that the
  130. // key meets the criteria of dwFlags (mostly extension vs progID)
  131. HRESULT CFTEnumAssocInfo::_EnumHKCR(ASENUM asenumFlags, LPTSTR pszStr, 
  132.                                     DWORD* pcchStr)
  133. {
  134.     HRESULT hres = E_FAIL;
  135.     BOOL fNext = TRUE;
  136.     while (fNext)
  137.     {
  138.         // This will mean "no more item"
  139.         hres = S_FALSE;
  140.         DWORD cchStr = *pcchStr;
  141.         LONG lRes = RegEnumKeyEx(HKEY_CLASSES_ROOT, _dwIndex, pszStr, &cchStr, NULL, NULL,
  142.             NULL, NULL);
  143.         ++_dwIndex;
  144.         if (lRes != ERROR_NO_MORE_ITEMS)
  145.         {
  146.             if (TEXT('*') != *pszStr)
  147.             {
  148.                 if (!_EnumKCRStop(asenumFlags, pszStr))
  149.                 {
  150.                     if (!_EnumKCRSkip(asenumFlags, pszStr))
  151.                     {
  152.                         hres = S_OK;
  153.                         fNext = FALSE;
  154.                     }
  155.                 }
  156.                 else
  157.                 {
  158.                     hres = S_FALSE;
  159.                     fNext = FALSE;
  160.                 }
  161.             }
  162.         }
  163.         else
  164.         {
  165.             fNext = FALSE;
  166.         }
  167.     }
  168.     // Did we found the first ext?
  169.     if (!_fFirstExtFound && SUCCEEDED(hres) && (S_FALSE != hres) && (TEXT('.') == *pszStr))
  170.     {
  171.         // Yes
  172.         _fFirstExtFound = TRUE;
  173.     }
  174.     return hres;
  175. }
  176. HRESULT CFTEnumAssocInfo::_EnumProgIDActions(LPTSTR pszStr, DWORD* pcchStr)
  177. {
  178.     // 5 for "shell"
  179.     TCHAR szSubKey[MAX_PROGID + 5 + 1];
  180.     HRESULT hres = S_OK;
  181.     HKEY hKey = NULL;
  182.     StrCpyN(szSubKey, _szInitStr, MAX_PROGID);
  183.     StrCat(szSubKey, TEXT("\shell"));
  184.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0, KEY_READ, &hKey))
  185.     {
  186.         LONG lRes = RegEnumKeyEx(hKey, _dwIndex, pszStr, pcchStr, NULL,
  187.             NULL, NULL, NULL);
  188.         if (ERROR_SUCCESS !=lRes)
  189.         {
  190.             if (ERROR_NO_MORE_ITEMS == lRes)
  191.                 hres = S_FALSE;
  192.             else
  193.                 hres = E_FAIL;
  194.         }
  195.         // BUGBUG
  196. #if 0
  197.         else
  198.         {
  199.             TCHAR szNiceText[MAX_ACTIONDESCR];
  200.             LONG lNiceText = ARRAYSIZE(szNiceText);
  201. #endif
  202.             ++_dwIndex;
  203. #if 0
  204.             // Check if there is nice text for the action
  205.             if ((ERROR_SUCCESS == SHRegQueryValue(hKey, pszStr, szNiceText, 
  206.                 &lNiceText)) && (lNiceText > SIZEOF(TCHAR)))
  207.             {
  208.                 StrCpyN(pszStr, szNiceText, ARRAYSIZE(pszStr));
  209.             }
  210.         }
  211. #endif
  212.         RegCloseKey(hKey);
  213.     }
  214.     return hres;
  215. }
  216. ///////////////////////////////////////////////////////////////////////////////
  217. // Helpers
  218. BOOL CFTEnumAssocInfo::_EnumKCRSkip(DWORD asenumFlags, LPTSTR pszExt)
  219. {
  220.     BOOL fRet = FALSE;
  221.     if (AIINIT_NONE == _aiinitFlags)
  222.     {
  223.         //BUGBUG: remove theis CFTAssocStore creation
  224.         CFTAssocStore* pAssocStore = NULL;
  225.         //BUGBUG: end
  226.         // Do we want the Exts?
  227.         if (!(ASENUM_EXT & asenumFlags))
  228.         {
  229.             // No
  230.             // Is the first char a '.'?
  231.             if (TEXT('.') == *pszExt)
  232.             {
  233.                 // Yes, skip this one
  234.                 fRet = TRUE;
  235.             }
  236.         }
  237.         else
  238.         {
  239.             // Yes
  240.             // Is the first char a '.'?
  241.             if (TEXT('.') != *pszExt)
  242.             {
  243.                 // No, skip it
  244.                 fRet = TRUE;
  245.             }
  246.         }
  247.         // we want to skip all the ext having explorer.exe as the executable for
  248.         // their default verb.
  249.         if ((ASENUM_NOEXPLORERSHELLACTION & asenumFlags) && !fRet)
  250.         {
  251.             IQueryAssociations* pQA = NULL;
  252.             ASSERT(ASENUM_EXT & asenumFlags);
  253.             HRESULT hres = AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations,
  254.                 (LPVOID*)&pQA);
  255.             if (SUCCEEDED(hres))
  256.             {
  257.                 WCHAR szwExt[MAX_EXT];
  258.                 DWORD cchExt = ARRAYSIZE(szwExt);
  259.                 SHTCharToUnicode(pszExt, szwExt, ARRAYSIZE(szwExt));
  260.                 hres = pQA->Init(0, szwExt, NULL, NULL);
  261.         
  262.                 if (SUCCEEDED(hres))
  263.                 {
  264.                     WCHAR szwExec[MAX_APPFRIENDLYNAME];
  265.                     DWORD cchExec = ARRAYSIZE(szwExec);
  266.                     hres = pQA->GetString(ASSOCF_VERIFY,
  267.                         ASSOCSTR_EXECUTABLE, NULL, szwExec, &cchExec);
  268.                     if (!StrCmpIW(PathFindFileNameW(szwExec), L"explorer.exe"))
  269.                     {
  270.                         fRet = TRUE;
  271.                     }
  272.                 }
  273.                 pQA->Release();
  274.             }
  275.         }
  276.         if ((ASENUM_NOEXCLUDED & asenumFlags) && !fRet)
  277.         {
  278.             IAssocInfo* pAI = NULL;
  279.             HRESULT hres = E_FAIL;
  280.             //BUGBUG: remove theis CFTAssocStore creation
  281.             if (!pAssocStore)
  282.                 pAssocStore = new CFTAssocStore();
  283.             //BUGBUG: end
  284.             ASSERT(ASENUM_EXT & asenumFlags);
  285.             if (pAssocStore)
  286.                 hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  287.             
  288.             if (SUCCEEDED(hres))
  289.             {
  290.                 hres = pAI->GetBOOL(AIBOOL_EXCLUDE, &fRet);
  291.                 pAI->Release();
  292.             }
  293.         }
  294.         if ((ASENUM_NOEXE & asenumFlags) && !fRet)
  295.         {
  296.             ASSERT(ASENUM_EXT & asenumFlags);
  297.             fRet = PathIsExe(pszExt);
  298.         }
  299.         if ((ASENUM_ASSOC_YES & asenumFlags) &&
  300.             (ASENUM_ASSOC_ALL != (ASENUM_ASSOC_ALL & asenumFlags)) && !fRet)
  301.         {
  302.             IAssocInfo* pAI = NULL;
  303.             HRESULT hres = E_FAIL;
  304.             //BUGBUG: remove theis CFTAssocStore creation
  305.             if (!pAssocStore)
  306.                 pAssocStore = new CFTAssocStore();
  307.             //BUGBUG: end
  308.             
  309.             ASSERT(ASENUM_EXT & asenumFlags);
  310.             if (pAssocStore)
  311.                 hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  312.             
  313.             if (SUCCEEDED(hres))
  314.             {
  315.                 BOOL fExtAssociated = FALSE;
  316.                 hres = pAI->GetBOOL(AIBOOL_EXTASSOCIATED, &fExtAssociated);
  317.                 fRet = (fExtAssociated ? FALSE : TRUE);
  318.                 pAI->Release();
  319.             }
  320.         }
  321.         if ((ASENUM_ASSOC_NO & asenumFlags) &&
  322.             (ASENUM_ASSOC_ALL != (ASENUM_ASSOC_ALL & asenumFlags)) && !fRet)
  323.         {
  324.             IAssocInfo* pAI = NULL;
  325.             HRESULT hres = E_FAIL;
  326.             //BUGBUG: remove theis CFTAssocStore creation
  327.             if (!pAssocStore)
  328.                 pAssocStore = new CFTAssocStore();
  329.             //BUGBUG: end
  330.             
  331.             ASSERT(ASENUM_EXT & asenumFlags);
  332.             if (pAssocStore)
  333.                 hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_EXT, &pAI);
  334.             
  335.             if (SUCCEEDED(hres))
  336.             {
  337.                 hres = pAI->GetBOOL(AIBOOL_EXTASSOCIATED, &fRet);
  338.                 pAI->Release();
  339.             }
  340.         }
  341.         if ((ASENUM_SHOWONLY & asenumFlags) && !fRet)
  342.         {
  343.             IAssocInfo* pAI = NULL;
  344.             HRESULT hres = E_FAIL;
  345.             //BUGBUG: remove theis CFTAssocStore creation
  346.             if (!pAssocStore)
  347.                 pAssocStore = new CFTAssocStore();
  348.             //BUGBUG: end
  349.             ASSERT(ASENUM_PROGID & asenumFlags);
  350.             // I know pszExt is not an Extension but a progID...
  351.             if (pAssocStore)
  352.                 hres = pAssocStore->GetAssocInfo(pszExt, AIINIT_PROGID, &pAI);
  353.             
  354.             if (SUCCEEDED(hres))
  355.             {
  356.                 BOOL fTmpRet = FALSE;
  357.                 hres = pAI->GetBOOL(AIBOOL_SHOW, &fTmpRet);
  358.                 // If it has the show flag (FTA_Show), we don't skip it, so
  359.                 // invert the fTmpRet
  360.                 fRet = fTmpRet ? FALSE : TRUE;
  361.                 pAI->Release();
  362.             }
  363.         }
  364.         //BUGBUG: remove theis CFTAssocStore creation
  365.         if (pAssocStore)
  366.             delete pAssocStore;
  367.         //BUGBUG: end
  368.     }
  369.     else
  370.     {
  371.         if (AIINIT_PROGID == _aiinitFlags)
  372.         {
  373.             fRet = TRUE;
  374.             // Do we want the Exts?
  375.             if (ASENUM_EXT & asenumFlags)
  376.             {
  377.                 DWORD dwType = 0;
  378.                 TCHAR szProgID[MAX_PROGID];
  379.                 DWORD cbProgID = ARRAYSIZE(szProgID) * sizeof(TCHAR);
  380.                 LONG lRes = SHGetValue(HKEY_CLASSES_ROOT, pszExt, NULL,
  381.                     &dwType, szProgID, &cbProgID);
  382.                 if (ERROR_SUCCESS == lRes)
  383.                 {
  384.                     // Does it have the same progID?
  385.                     if (!lstrcmpi(szProgID, _szInitStr))
  386.                     {
  387.                         // Yes, don't skip
  388.                         fRet = FALSE;
  389.                     }
  390.                 }
  391.             }
  392.         }
  393.     }
  394.     
  395.     return fRet;
  396. }
  397. BOOL CFTEnumAssocInfo::_EnumKCRStop(DWORD asenumFlags, LPTSTR pszExt)
  398. {
  399.     BOOL fRet = FALSE;
  400.     // If we want only the extensions, and the first char is not a '.', then stop
  401.     if (ASENUM_EXT & asenumFlags)
  402.     {
  403.         // Don't go out if we haven't found the first extension
  404.         if ((TEXT('.') != *pszExt) && _fFirstExtFound)
  405.             fRet = TRUE;
  406.     }
  407.         
  408.     return fRet;
  409. }
  410. ///////////////////////////////////////////////////////////////////////////////
  411. // Non-implemented IEnum methods
  412. HRESULT CFTEnumAssocInfo::Clone(IEnumAssocInfo* pEnum)
  413. {
  414.     // Will never be implemented
  415.     return E_FAIL;
  416. }
  417. HRESULT CFTEnumAssocInfo::Skip(DWORD dwSkip)
  418. {
  419.     return E_NOTIMPL;
  420. }
  421. HRESULT CFTEnumAssocInfo::Reset()
  422. {
  423.     return E_NOTIMPL;
  424. }