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

Windows Kernel

Development Platform:

Visual C++

  1. /*++
  2.     Implements IEnumIDList.
  3. --*/
  4. #include <windows.h>
  5. #include <shlobj.h>
  6. #include "pstore.h"
  7. #include "utility.h"
  8. #include "enumid.h"
  9. #include "shfolder.h"
  10. extern LONG       g_DllRefCount;
  11. CEnumIDList::CEnumIDList(
  12.     LPITEMIDLIST pidl,
  13.     BOOL bEnumItems
  14.     )
  15. {
  16.     m_pIEnumProviders = NULL;
  17.     m_pIPStoreProvider = NULL;
  18.     m_pIEnumTypes = NULL;
  19.     m_pIEnumTypesGlobal = NULL;
  20.     m_pIEnumSubtypes = NULL;
  21.     m_pIEnumItems = NULL;
  22.     m_bEnumItems = bEnumItems;
  23.     //
  24.     // get the shell's IMalloc pointer
  25.     // we'll keep this until we get destroyed
  26.     //
  27.     if(FAILED(SHGetMalloc(&m_pMalloc)))
  28.         delete this;
  29.     m_KeyType = PST_KEY_CURRENT_USER;
  30.     if(pidl == NULL) {
  31.         if( PStoreEnumProviders(0, &m_pIEnumProviders) != S_OK )
  32.             m_pIEnumProviders = NULL;
  33.         m_dwType = PIDL_TYPE_PROVIDER;  // top-level
  34.     } else {
  35.         m_dwType = GetLastPidlType(pidl) + 1;   // parent + 1
  36.     }
  37.     //
  38.     // get provider interface
  39.     //
  40.     if(m_dwType > PIDL_TYPE_PROVIDER) {
  41.         PST_PROVIDERID      *ProviderId = GetPidlGuid(pidl);
  42.         if(PStoreCreateInstance(&m_pIPStoreProvider, ProviderId, NULL, 0) != S_OK)
  43.             m_pIPStoreProvider = NULL;
  44.     }
  45.     //
  46.     // prepare two type enumerators, if appropriate:
  47.     // PST_KEY_CURRENT_USER and PST_KEY_LOCAL_MACHINE
  48.     //
  49.     if(m_dwType == PIDL_TYPE_TYPE && m_pIPStoreProvider) {
  50.         m_pIPStoreProvider->EnumTypes(PST_KEY_CURRENT_USER, 0, &m_pIEnumTypes);
  51.         m_pIPStoreProvider->EnumTypes(PST_KEY_LOCAL_MACHINE, 0, &m_pIEnumTypesGlobal);
  52.     }
  53.     //
  54.     // prepare subtype enumerator
  55.     //
  56.     if(m_dwType == PIDL_TYPE_SUBTYPE && m_pIPStoreProvider) {
  57.         GUID    *pguidType;
  58.         m_KeyType = GetLastPidlKeyType(pidl);
  59.         pguidType = GetLastPidlGuid(pidl);
  60.         CopyMemory(&m_guidType, pguidType, sizeof(GUID));
  61.         m_pIPStoreProvider->EnumSubtypes(
  62.                 m_KeyType,
  63.                 pguidType,
  64.                 0,
  65.                 &m_pIEnumSubtypes
  66.                 );
  67.     }
  68.     //
  69.     // prepare item enumerator if appropriate.
  70.     //
  71.     if(m_dwType == PIDL_TYPE_ITEM && m_bEnumItems && m_pIPStoreProvider) {
  72.         GUID    *pguidType;
  73.         GUID    *pguidSubtype;
  74.         m_KeyType = GetLastPidlKeyType(pidl);
  75.         pguidSubtype = GetLastPidlGuid(pidl);
  76.         CopyMemory(&m_guidSubtype, pguidSubtype, sizeof(GUID));
  77.         pguidType = GetPidlGuid(SearchPidlByType(pidl, PIDL_TYPE_TYPE));
  78.         CopyMemory(&m_guidType, pguidType, sizeof(GUID));
  79.         m_pIPStoreProvider->EnumItems(
  80.                 m_KeyType,
  81.                 pguidType,
  82.                 pguidSubtype,
  83.                 0,
  84.                 &m_pIEnumItems
  85.                 );
  86.     }
  87.     m_ulCurrent = 0;
  88.     m_ObjRefCount = 1;
  89.     InterlockedIncrement(&g_DllRefCount);
  90. }
  91. CEnumIDList::~CEnumIDList()
  92. {
  93.     //
  94.     // free any interfaces we established.
  95.     //
  96.     if(m_pIEnumProviders) {
  97.         m_pIEnumProviders->Release();
  98.         m_pIEnumProviders = NULL;
  99.     }
  100.     if(m_pIPStoreProvider) {
  101.         m_pIPStoreProvider->Release();
  102.         m_pIPStoreProvider = NULL;
  103.     }
  104.     if(m_pIEnumTypes) {
  105.         m_pIEnumTypes->Release();
  106.         m_pIEnumTypes = NULL;
  107.     }
  108.     if(m_pIEnumTypesGlobal) {
  109.         m_pIEnumTypesGlobal->Release();
  110.         m_pIEnumTypesGlobal = NULL;
  111.     }
  112.     if(m_pIEnumSubtypes) {
  113.         m_pIEnumSubtypes->Release();
  114.         m_pIEnumSubtypes = NULL;
  115.     }
  116.     if(m_pIEnumItems) {
  117.         m_pIEnumItems->Release();
  118.         m_pIEnumItems = NULL;
  119.     }
  120.     if(m_pMalloc) {
  121.         m_pMalloc->Release();
  122.         m_pMalloc = NULL;
  123.     }
  124.     InterlockedDecrement(&g_DllRefCount);
  125. }
  126. STDMETHODIMP
  127. CEnumIDList::QueryInterface(
  128.     REFIID riid,
  129.     LPVOID *ppReturn
  130.     )
  131. {
  132.     *ppReturn = NULL;
  133.     if(IsEqualIID(riid, IID_IUnknown))
  134.         *ppReturn = (IUnknown*)(CEnumIDList*)this;
  135.     else if(IsEqualIID(riid, IID_IEnumIDList))
  136.         *ppReturn = (CEnumIDList*)this;
  137.     if(*ppReturn == NULL)
  138.         return E_NOINTERFACE;
  139.     (*(LPUNKNOWN*)ppReturn)->AddRef();
  140.     return S_OK;
  141. }
  142. STDMETHODIMP_(DWORD)
  143. CEnumIDList::AddRef()
  144. {
  145.     return InterlockedIncrement(&m_ObjRefCount);
  146. }
  147. STDMETHODIMP_(DWORD)
  148. CEnumIDList::Release()
  149. {
  150.     LONG lDecremented = InterlockedDecrement(&m_ObjRefCount);
  151.     if(lDecremented == 0)
  152.         delete this;
  153.     return lDecremented;
  154. }
  155. STDMETHODIMP
  156. CEnumIDList::Next(
  157.     ULONG ulElements,
  158.     LPITEMIDLIST *pPidl,
  159.     ULONG *pulFetched
  160.     )
  161. /*++
  162.     Retrieves the specified number of item identifiers in the enumeration
  163.     sequence and advances the current position.
  164.     Returns the NOERROR value if successful,
  165.     Returns S_FALSE value if there are no more items in the enumeration
  166.     or an OLE-defined error value if an error occurs.
  167. --*/
  168. {
  169.     HRESULT hr;
  170.     *pPidl = NULL;
  171.     *pulFetched = 0;
  172.     if(m_bEnumItems) {
  173.         if(m_dwType > PIDL_TYPE_ITEM)
  174.             return S_FALSE;
  175.     } else {
  176.         if(m_dwType > PIDL_TYPE_SUBTYPE)
  177.             return S_FALSE; // nothing left to enumerate
  178.     }
  179.     if(m_dwType == PIDL_TYPE_PROVIDER && m_pIEnumProviders)
  180.     {
  181.         PPST_PROVIDERINFO   pProvInfo;
  182.         if( m_pIEnumProviders->Next(1, &pProvInfo, &m_ulCurrent) != S_OK ) {
  183.             //
  184.             // enumeration of providers complete
  185.             //
  186.             return S_FALSE;
  187.         }
  188.         hr = CreateIDList(m_dwType, m_KeyType, &(pProvInfo->ID), pProvInfo->szProviderName, pPidl);
  189.         CoTaskMemFree(pProvInfo);
  190.         if(hr != S_OK)
  191.             return S_FALSE;
  192.         *pulFetched = 1;
  193.         return NOERROR;
  194.     }
  195.     //
  196.     // must have a valid provider interface at this point
  197.     //
  198.     if(m_pIPStoreProvider == NULL)
  199.         return S_FALSE;
  200.     if(m_dwType == PIDL_TYPE_TYPE) {
  201.         IEnumPStoreTypes    *pIEnumTypes;
  202.         PST_KEY             KeyType = PST_KEY_CURRENT_USER;
  203.         GUID                guidType;
  204. type_enum:
  205.         if(KeyType == PST_KEY_LOCAL_MACHINE)
  206.             pIEnumTypes = m_pIEnumTypesGlobal;
  207.         else
  208.             pIEnumTypes = m_pIEnumTypes;
  209.         if(pIEnumTypes == NULL)
  210.             return S_FALSE;
  211.         if(pIEnumTypes->Next(1, &guidType, &m_ulCurrent) != S_OK) {
  212.             //
  213.             // if enumeration at PST_KEY_CURRENT_USER level complete,
  214.             // continue at the PST_KEY_LOCAL_MACHINE level.
  215.             //
  216.             if(KeyType == PST_KEY_CURRENT_USER) {
  217.                 KeyType = PST_KEY_LOCAL_MACHINE;
  218.                 goto type_enum;
  219.             }
  220.             //
  221.             // enumeration of types complete
  222.             //
  223.             return S_FALSE;
  224.         }
  225.         PST_TYPEINFO        *pTypeInfo = NULL;
  226.         if(S_OK != m_pIPStoreProvider->GetTypeInfo(
  227.                     KeyType,
  228.                     &guidType,
  229.                     &pTypeInfo,
  230.                     0
  231.                     )) return S_FALSE;
  232.         hr = CreateIDList(m_dwType, KeyType, &guidType, pTypeInfo->szDisplayName, pPidl);
  233.         //
  234.         // free pTypeInfo data
  235.         //
  236.         CoTaskMemFree(pTypeInfo);
  237.         if(hr != S_OK)
  238.             return S_FALSE;
  239.         *pulFetched = 1;
  240.         return NOERROR;
  241.     }
  242.     if (m_dwType == PIDL_TYPE_SUBTYPE && m_pIEnumSubtypes) {
  243.         GUID                guidSubtype;
  244.         GUID                *pguidType = &m_guidType;
  245.         if(m_pIEnumSubtypes->Next(1, &guidSubtype, &m_ulCurrent) != S_OK) {
  246.             //
  247.             // enumeration of types complete
  248.             //
  249.             return S_FALSE;
  250.         }
  251.         PST_TYPEINFO        *pTypeInfo = NULL;
  252.         if(m_pIPStoreProvider->GetSubtypeInfo(m_KeyType, pguidType, &guidSubtype, &pTypeInfo, 0) != S_OK)
  253.             return S_FALSE;
  254.         hr = CreateIDList(m_dwType, m_KeyType, &guidSubtype, pTypeInfo->szDisplayName, pPidl);
  255.         //
  256.         // free pTypeInfo data
  257.         //
  258.         CoTaskMemFree(pTypeInfo);
  259.         if(hr != S_OK)
  260.             return S_FALSE;
  261.         *pulFetched = 1;
  262.         return NOERROR;
  263.     }
  264.     if(m_dwType == PIDL_TYPE_ITEM && m_pIEnumItems) {
  265.         LPWSTR pszItem;
  266.         //
  267.         // enumerate and add items associated with specified subtype
  268.         //
  269.         if(m_pIEnumItems->Next(1, &pszItem, &m_ulCurrent) != S_OK) {
  270.             //
  271.             // enumeration of items complete
  272.             //
  273.             return S_FALSE;
  274.         }
  275.         hr = CreateIDList(
  276.                     m_dwType,
  277.                     m_KeyType,
  278.                     NULL, // no item guid
  279.                     pszItem,
  280.                     pPidl
  281.                     );
  282.         //
  283.         // free pszItem data
  284.         //
  285.         CoTaskMemFree(pszItem);
  286.         if(hr != S_OK)
  287.             return S_FALSE;
  288.         *pulFetched = 1;
  289.         return NOERROR;
  290.     }
  291.     return S_FALSE;
  292. }
  293. STDMETHODIMP
  294. CEnumIDList::CreateIDList(
  295.     DWORD dwType,
  296.     PST_KEY KeyType,
  297.     GUID *guid,
  298.     LPCWSTR szString,
  299.     LPITEMIDLIST *pPidlOut
  300.     )
  301. {
  302.     DWORD cbString = 0;
  303.     DWORD cbPidlContent;
  304.     if(szString) {
  305.         cbString = lstrlenW(szString);
  306.     }
  307.     cbString = (cbString + 1) * sizeof(WCHAR);
  308.     cbPidlContent = sizeof(PIDL_CONTENT) + cbString;
  309.     //
  310.     // allocate the memory
  311.     //
  312.     *pPidlOut = (LPITEMIDLIST)m_pMalloc->Alloc(
  313.             sizeof(ITEMIDLIST) +    // this item's ITEMIDLIST
  314.             cbPidlContent +         // this item's data
  315.             sizeof(ITEMIDLIST)      // terminal ITEMIDLIST
  316.             );
  317.     if(*pPidlOut == NULL)
  318.         return E_OUTOFMEMORY;
  319.     LPITEMIDLIST pidlTemp = *pPidlOut;
  320.     LPPIDL_CONTENT pidlContent = (LPPIDL_CONTENT)&(pidlTemp->mkid.abID);
  321.     //
  322.     // set the size of this item
  323.     //
  324.     pidlTemp->mkid.cb = sizeof(ITEMIDLIST) + cbPidlContent;
  325.     //
  326.     // set the data for this item
  327.     //
  328.     pidlContent->dwType = dwType;
  329.     pidlContent->KeyType = KeyType;
  330.     if( guid ) {
  331.         CopyMemory(&(pidlContent->guid), guid, sizeof(GUID));
  332.     } else {
  333.         ZeroMemory(&(pidlContent->guid), sizeof(GUID));
  334.     }
  335.     if(szString) {
  336.         CopyMemory((LPBYTE)(pidlContent+1), szString, cbString);
  337.     } else {
  338.         ((LPWSTR)(pidlContent+1))[0] = L'';
  339.     }
  340.     //
  341.     // advance and terminate item ID list
  342.     //
  343.     pidlTemp = (LPITEMIDLIST)GetPidlNextItem(*pPidlOut);
  344.     pidlTemp->mkid.cb = 0;
  345.     pidlTemp->mkid.abID[0] = 0;
  346.     return NOERROR;
  347. }
  348. STDMETHODIMP
  349. CEnumIDList::Skip(
  350.     ULONG ulSkip
  351.     )
  352. {
  353.     m_ulCurrent += ulSkip;
  354.     return NOERROR;
  355. }
  356. STDMETHODIMP
  357. CEnumIDList::Reset(
  358.     void
  359.     )
  360. {
  361.     m_ulCurrent = 0;
  362.     return NOERROR;
  363. }
  364. STDMETHODIMP
  365. CEnumIDList::Clone(
  366.     LPENUMIDLIST *ppEnum
  367.     )
  368. {
  369.     return E_NOTIMPL;
  370. }