Revision 1 (by moose, 2006/03/06 10:00:33) Initial Import
// CacheIter.h - An STL Iterator for the Internet Explorer Cache

// Copyright 2000 by Samir Bajaj

//

// NOTES

//     This file contains the implementation of an input iterator

//     for the Microsoft Internet Explorer cache.



#include <wininet.h>

#include <iostream>

#include <iomanip>

#include <iterator>

#include <functional>



class cache_iterator : public std::iterator<std::input_iterator_tag,
                                            INTERNET_CACHE_ENTRY_INFO>
{
    HANDLE                      m_hCacheEntry;
    LPINTERNET_CACHE_ENTRY_INFO m_lpCacheEntryInfo;
    static const unsigned int CACHE_ENTRY_INFO_SIZE;

public:
    cache_iterator() : m_hCacheEntry(0), m_lpCacheEntryInfo(0)
    {
        DWORD dwInitCacheEntrySize = CACHE_ENTRY_INFO_SIZE;
        m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[dwInitCacheEntrySize]);
        m_lpCacheEntryInfo->dwStructSize = dwInitCacheEntrySize;

        m_hCacheEntry = ::FindFirstUrlCacheEntry(0 /* all */, m_lpCacheEntryInfo, &dwInitCacheEntrySize);
        if (0 == m_hCacheEntry)
        {
            delete [] m_lpCacheEntryInfo;

            switch (::GetLastError())
            {
            case ERROR_NO_MORE_ITEMS:
                break;

            case ERROR_INSUFFICIENT_BUFFER:
                // reallocate and retry

                m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[dwInitCacheEntrySize]);
                m_lpCacheEntryInfo->dwStructSize = dwInitCacheEntrySize;
                if (0 == (m_hCacheEntry = ::FindFirstUrlCacheEntry(0, m_lpCacheEntryInfo, &dwInitCacheEntrySize)))
                    delete [] m_lpCacheEntryInfo;

                break;

            default:
                ::FindCloseUrlCache(m_hCacheEntry);
                m_hCacheEntry = 0;
            }
        }
    }

    cache_iterator(LPINTERNET_CACHE_ENTRY_INFO) : m_hCacheEntry(0), m_lpCacheEntryInfo(0)
    {
    }

    cache_iterator(const cache_iterator& cit) : m_hCacheEntry(cit.m_hCacheEntry),
                                                m_lpCacheEntryInfo(cit.m_lpCacheEntryInfo)
    {
    }

    cache_iterator& operator++()
    {
        DWORD dwInitCacheEntrySize = 4096;
        m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[dwInitCacheEntrySize]);
        m_lpCacheEntryInfo->dwStructSize = dwInitCacheEntrySize;

        if (!::FindNextUrlCacheEntry(m_hCacheEntry, m_lpCacheEntryInfo, &dwInitCacheEntrySize))
        {
            delete [] m_lpCacheEntryInfo;

            switch (::GetLastError())
            {
            case ERROR_NO_MORE_ITEMS:
                ::FindCloseUrlCache(m_hCacheEntry);
                m_hCacheEntry = 0;
                break;

            case ERROR_INSUFFICIENT_BUFFER:
                // re-allocate and try

                m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[dwInitCacheEntrySize]);
                m_lpCacheEntryInfo->dwStructSize = dwInitCacheEntrySize;
                if (!::FindNextUrlCacheEntry(m_hCacheEntry, m_lpCacheEntryInfo, &dwInitCacheEntrySize))
                {
                    delete [] m_lpCacheEntryInfo;
                    ::FindCloseUrlCache(m_hCacheEntry);
                    m_hCacheEntry = 0;
                }
                break;

            default:
                ::FindCloseUrlCache(m_hCacheEntry);
                m_hCacheEntry = 0;
            }        
        }
        return *this;
    }

    bool operator==(const cache_iterator& cit) const
    {
        return m_hCacheEntry == cit.m_hCacheEntry;
    }

    bool operator!=(const cache_iterator& cit) const
    {
        return !(*this == cit);
    }

    INTERNET_CACHE_ENTRY_INFO operator*()
    {
        return *m_lpCacheEntryInfo;
    }
};