home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winui / shell / regview / enumidl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-27  |  9.6 KB  |  428 lines

  1. /**************************************************************************
  2.    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3.    ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4.    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5.    PARTICULAR PURPOSE.
  6.  
  7.    Copyright 1997 Microsoft Corporation.  All Rights Reserved.
  8. **************************************************************************/
  9.  
  10. /**************************************************************************
  11.  
  12.    File:          EnumIDL.cpp
  13.    
  14.    Description:   Implements IEnumIDList.
  15.  
  16. **************************************************************************/
  17.  
  18. /**************************************************************************
  19.    #include statements
  20. **************************************************************************/
  21.  
  22. #include "EnumIDL.h"
  23. #include "ShlFldr.h"
  24.  
  25. /**************************************************************************
  26.  
  27.    CEnumIDList::CEnumIDList
  28.  
  29. **************************************************************************/
  30.  
  31. CEnumIDList::CEnumIDList(HKEY hKeyRoot, LPCTSTR lpszSubKey, DWORD dwFlags, HRESULT *pResult)
  32. {
  33. if(pResult)
  34.    *pResult = S_OK;
  35.  
  36. m_pFirst = m_pLast = m_pCurrent = NULL;
  37.  
  38. m_pPidlMgr = new CPidlMgr();
  39. if(!m_pPidlMgr)
  40.    {
  41.    if(pResult)
  42.       *pResult = E_OUTOFMEMORY;
  43.  
  44.    delete this;
  45.    return;
  46.    }
  47.  
  48. //get the shell's IMalloc pointer
  49. //we'll keep this until we get destroyed
  50. if(FAILED(SHGetMalloc(&m_pMalloc)))
  51.    {
  52.    if(pResult)
  53.       *pResult = E_OUTOFMEMORY;
  54.  
  55.    delete this;
  56.    return;
  57.    }
  58.  
  59. if(!CreateEnumList(hKeyRoot, lpszSubKey, dwFlags))
  60.    {
  61.    if(pResult)
  62.       *pResult = E_OUTOFMEMORY;
  63.  
  64.    delete this;
  65.    return;
  66.    }
  67.  
  68. m_ObjRefCount = 1;
  69.  
  70. g_DllRefCount++;
  71. }
  72.  
  73. /**************************************************************************
  74.  
  75.    CEnumIDList::~CEnumIDList
  76.  
  77. **************************************************************************/
  78.  
  79. CEnumIDList::~CEnumIDList()
  80. {
  81. DeleteList();
  82.  
  83. if(m_pMalloc)
  84.    m_pMalloc->Release();
  85.  
  86. if(m_pPidlMgr)
  87.    delete m_pPidlMgr;
  88.  
  89. g_DllRefCount--;
  90. }
  91.  
  92. /**************************************************************************
  93.  
  94.    CEnumIDList::QueryInterface
  95.  
  96. **************************************************************************/
  97.  
  98. STDMETHODIMP CEnumIDList::QueryInterface(REFIID riid, LPVOID *ppReturn)
  99. {
  100. *ppReturn = NULL;
  101.  
  102. //IUnknown
  103. if(IsEqualIID(riid, IID_IUnknown))
  104.    {
  105.    *ppReturn = this;
  106.    }
  107.    
  108. //IEnumIDList
  109. else if(IsEqualIID(riid, IID_IEnumIDList))
  110.    {
  111.    *ppReturn = (IEnumIDList*)this;
  112.    }   
  113.  
  114. if(*ppReturn)
  115.    {
  116.    (*(LPUNKNOWN*)ppReturn)->AddRef();
  117.    return S_OK;
  118.    }
  119.  
  120. return E_NOINTERFACE;
  121. }                                             
  122.  
  123. /**************************************************************************
  124.  
  125.    CEnumIDList::AddRef
  126.  
  127. **************************************************************************/
  128.  
  129. STDMETHODIMP_(DWORD) CEnumIDList::AddRef()
  130. {
  131. return ++m_ObjRefCount;
  132. }
  133.  
  134.  
  135. /**************************************************************************
  136.  
  137.    CEnumIDList::Release
  138.  
  139. **************************************************************************/
  140.  
  141. STDMETHODIMP_(DWORD) CEnumIDList::Release()
  142. {
  143. if(--m_ObjRefCount == 0)
  144.    {
  145.    delete this;
  146.    return 0;
  147.    }
  148.    
  149. return m_ObjRefCount;
  150. }
  151.  
  152. /**************************************************************************
  153.  
  154.    CEnumIDList::Next()
  155.    
  156. **************************************************************************/
  157.  
  158. STDMETHODIMP CEnumIDList::Next(DWORD dwElements, LPITEMIDLIST apidl[], LPDWORD pdwFetched)
  159. {
  160. DWORD    dwIndex;
  161. HRESULT  hr = S_OK;
  162.  
  163. if(dwElements > 1 && !pdwFetched)
  164.    return E_INVALIDARG;
  165.  
  166. for(dwIndex = 0; dwIndex < dwElements; dwIndex++)
  167.    {
  168.    //is this the last item in the list?
  169.    if(!m_pCurrent)
  170.       {
  171.       hr =  S_FALSE;
  172.       break;
  173.       }
  174.  
  175.    apidl[dwIndex] = m_pPidlMgr->Copy(m_pCurrent->pidl);
  176.  
  177.    m_pCurrent = m_pCurrent->pNext;
  178.    }
  179.  
  180. if(pdwFetched)
  181.    *pdwFetched = dwIndex;
  182.  
  183. return hr;
  184. }
  185.  
  186. /**************************************************************************
  187.  
  188.    CEnumIDList::Skip()
  189.    
  190. **************************************************************************/
  191.  
  192. STDMETHODIMP CEnumIDList::Skip(DWORD dwSkip)
  193. {
  194. DWORD    dwIndex;
  195. HRESULT  hr = S_OK;
  196.  
  197. for(dwIndex = 0; dwIndex < dwSkip; dwIndex++)
  198.    {
  199.    //is this the last item in the list?
  200.    if(!m_pCurrent)
  201.       {
  202.       hr = S_FALSE;
  203.       break;
  204.       }
  205.  
  206.    m_pCurrent = m_pCurrent->pNext;
  207.    }
  208.  
  209. return hr;
  210. }
  211.  
  212. /**************************************************************************
  213.  
  214.    CEnumIDList::Reset()
  215.    
  216. **************************************************************************/
  217.  
  218. STDMETHODIMP CEnumIDList::Reset(void)
  219. {
  220. m_pCurrent = m_pFirst;
  221.  
  222. return S_OK;
  223. }
  224.  
  225. /**************************************************************************
  226.  
  227.    CEnumIDList::Clone()
  228.    
  229. **************************************************************************/
  230.  
  231. STDMETHODIMP CEnumIDList::Clone(LPENUMIDLIST *ppEnum)
  232. {
  233. return E_NOTIMPL;
  234. }
  235.  
  236. /**************************************************************************
  237.  
  238.    CEnumIDList::CreateEnumList()
  239.    
  240. **************************************************************************/
  241.  
  242. BOOL CEnumIDList::CreateEnumList(HKEY hKeyRoot, LPCTSTR lpszSubKey, DWORD dwFlags)
  243. {
  244. LPITEMIDLIST   pidl;
  245. DWORD          dwIndex;
  246.  
  247. //enumerate the folders (keys)
  248. if(dwFlags & SHCONTF_FOLDERS)
  249.    {
  250.    /*
  251.    special case - we can't enumerate the root level keys (HKEY_CLASSES_ROOT, etc.), 
  252.    so if both of these are NULL, then we need to fake an enumeration of those.
  253.    */
  254.    if((!hKeyRoot) && (!lpszSubKey))
  255.       {
  256.       HKEY  ahKey[] = { HKEY_CLASSES_ROOT,
  257.                         HKEY_CURRENT_USER,
  258.                         HKEY_LOCAL_MACHINE,
  259.                         HKEY_USERS,
  260.                         HKEY_PERFORMANCE_DATA,
  261.                         HKEY_CURRENT_CONFIG,
  262.                         HKEY_DYN_DATA,
  263.                         (HKEY)-1};
  264.       
  265.       for(dwIndex = 0; ahKey[dwIndex] != (HKEY)-1; dwIndex++)
  266.          {
  267.          //only add the root keys that actually exists on this system
  268.          if(RootKeyExists(ahKey[dwIndex]))
  269.             {
  270.             //create the pidl for this item
  271.             pidl = m_pPidlMgr->CreateRootKey(ahKey[dwIndex]);
  272.             if(pidl)
  273.                {
  274.                if(!AddToEnumList(pidl))
  275.                   return FALSE;
  276.                }
  277.             else
  278.                {
  279.                return FALSE;
  280.                }
  281.             }   
  282.          }
  283.       }
  284.    else
  285.       {
  286.       TCHAR    szKey[REGSTR_MAX_VALUE_LENGTH];
  287.  
  288.       dwIndex = 0;
  289.  
  290.       //get the next item
  291.       while(GetKeyName(hKeyRoot, lpszSubKey, dwIndex++, szKey, sizeof(szKey)))
  292.          {
  293.          //create the pidl for this item
  294.          pidl = m_pPidlMgr->CreateSubKey(szKey);
  295.          if(pidl)
  296.             {
  297.             if(!AddToEnumList(pidl))
  298.                return FALSE;
  299.             }
  300.          else
  301.             {
  302.             return FALSE;
  303.             }   
  304.          }
  305.       }
  306.    }   
  307.  
  308. //enumerate the non-folder items (values)
  309. if(dwFlags & SHCONTF_NONFOLDERS)
  310.    {
  311.    TCHAR    szValue[REGSTR_MAX_VALUE_LENGTH];
  312.  
  313.    dwIndex = 0;
  314.  
  315.    /*
  316.    There is a special case here. All keys have a default value, but if the 
  317.    default value is empty, then it won't be enumerated. If it has data, then 
  318.    it will be enumerated but the name will be NULL. 
  319.    
  320.    To work around this, we will add a default item here and then not add it 
  321.    if it shows up in the enumeration in the loop below.
  322.    */
  323.    //create the default item
  324.    pidl = m_pPidlMgr->CreateValue(TEXT(""));
  325.    if(pidl)
  326.       {
  327.       if(!AddToEnumList(pidl))
  328.          return FALSE;
  329.       }
  330.    else
  331.       {
  332.       return FALSE;
  333.       }   
  334.    
  335.    //get the items
  336.    while(GetValueName(hKeyRoot, lpszSubKey, dwIndex++, szValue, sizeof(szValue)))
  337.       {
  338.       //don't add a default value that may have shown up in the enumeration
  339.       if(!szValue[0])
  340.          continue;
  341.  
  342.       //create the pidl for this item
  343.       pidl = m_pPidlMgr->CreateValue(szValue);
  344.  
  345.       if(pidl)
  346.          {
  347.          if(!AddToEnumList(pidl))
  348.             return FALSE;
  349.          }
  350.       else
  351.          {
  352.          return FALSE;
  353.          }   
  354.       }
  355.    }
  356.    
  357. return TRUE;
  358. }
  359.  
  360. /**************************************************************************
  361.  
  362.    CEnumIDList::AddToEnumList()
  363.    
  364. **************************************************************************/
  365.  
  366. BOOL CEnumIDList::AddToEnumList(LPITEMIDLIST pidl)
  367. {
  368. LPENUMLIST  pNew;
  369.  
  370. pNew = (LPENUMLIST)m_pMalloc->Alloc(sizeof(ENUMLIST));
  371.  
  372. if(pNew)
  373.    {
  374.    //set the next pointer
  375.    pNew->pNext = NULL;
  376.    pNew->pidl = pidl;
  377.  
  378.    //is this the first item in the list?
  379.    if(!m_pFirst)
  380.       {
  381.       m_pFirst = pNew;
  382.       m_pCurrent = m_pFirst;
  383.       }
  384.    
  385.    if(m_pLast)
  386.       {
  387.       //add the new item to the end of the list
  388.       m_pLast->pNext = pNew;
  389.       }
  390.    
  391.    //update the last item pointer
  392.    m_pLast = pNew;
  393.  
  394.    return TRUE;
  395.    }
  396.  
  397. return FALSE;
  398. }
  399.  
  400. /**************************************************************************
  401.  
  402.    CEnumIDList::DeleteList()
  403.    
  404. **************************************************************************/
  405.  
  406. BOOL CEnumIDList::DeleteList(void)
  407. {
  408. LPENUMLIST  pDelete;
  409.  
  410. while(m_pFirst)
  411.    {
  412.    pDelete = m_pFirst;
  413.    m_pFirst = pDelete->pNext;
  414.  
  415.    //free the pidl
  416.    //m_pMalloc->Free(pDelete->pidl);
  417.    m_pPidlMgr->Delete(pDelete->pidl);
  418.    
  419.    //free the list item
  420.    m_pMalloc->Free(pDelete);
  421.    }
  422.  
  423. m_pFirst = m_pLast = m_pCurrent = NULL;
  424.  
  425. return TRUE;
  426. }
  427.  
  428.