COM enumerators implement Reset(), Next(), Skip() and Clone(). Here’s the client side:

    // initialize COM libraries
    HRESULT hr = OleInitialize ((LPVOID) 0);

    // retrieve contents of clipboard
    IDataObject * pIDataObject;
    hr = OleGetClipboard (& pIDataObject);

    // retrieve a FORMATETC enumerator
    hr = pIDataObject -> EnumFormatEtc (DATADIR_GET, & pIEnumFORMATETC);

    // enumerate all FORMATETCs supported by this data object
    while ((pIEnumFORMATETC -> Next (1, & fe, (ULONG *) 0)) == S_OK)
        CLIPFORMAT cfFormat = fe.cfFormat;
        if (cfFormat < CF_MAX) {
            ODS1 ("[Clipboard]\tgot format %s\n", rszClipboardNames [cfFormat]);
        else {
            ODS1 ("[Clipboard]\tunknown clipboard format %d\n", cfFormat);

    // release enumerator object
    hr = pIEnumFORMATETC -> Release ();

ATL has a number of classes to support enumeration on the server side. To create a collection that can be consumed like in the code above, CComEnum and CComEnumImpl are classes of interest.

ATL also has support for loading a COM collection into a C++ STL vector, e.g. std:vector<IThing*>, which is kind of a neat trick. See CComEnumOnSTL and IEnumOnSTLImpl