⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utility.h

📁 《ATL深入解析》随书源码
💻 H
📖 第 1 页 / 共 2 页
字号:
// Utility.h : Declaration of the utility classes

#ifndef __UTILITY_H_
#define __UTILITY_H_

/////////////////////////////////////////////////////////////////////////////
// CDummyStream - Provides an implementation of IStream.

class CDummyStream : public IStream
{
public:
        CDummyStream() { m_libSeek.QuadPart = 0; m_libMaxOffset.QuadPart = 0; }

        STDMETHODIMP QueryInterface (REFIID riid, void**ppv)
        {
            if (riid == IID_IStream ||
                riid == IID_ISequentialStream || riid == IID_IUnknown)
                *ppv = static_cast <IStream*> (this);
            return *ppv = NULL, E_NOINTERFACE;
        }
        STDMETHODIMP_(ULONG) AddRef() { return 2; }
        STDMETHODIMP_(ULONG) Release () { return 1; }

        STDMETHODIMP Read(void* pv, ULONG cb, ULONG* pcbRead) { return E_NOTIMPL; }
        STDMETHODIMP Write(const void* pv, ULONG cb, ULONG* pcbWritten)
        {
            m_libMaxOffset.QuadPart = max (m_libMaxOffset.QuadPart, m_libSeek.QuadPart + cb);
            *pcbWritten = cb;
            return S_OK;
        }
        STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER*plibNewPosition)
        {
            switch (dwOrigin) {
            case STREAM_SEEK_SET:
                m_libSeek.QuadPart = dlibMove.QuadPart;
                break;
            case STREAM_SEEK_CUR:
                m_libSeek.QuadPart += dlibMove.QuadPart;
                break;
            case STREAM_SEEK_END:
                m_libSeek.QuadPart = m_libMaxOffset.QuadPart - dlibMove.QuadPart;
                if (m_libSeek.QuadPart < 0) m_libSeek.QuadPart = 0;
                break;
            default:
                return E_UNEXPECTED;
            }
            *plibNewPosition = m_libSeek;
            return S_OK;
        }
        STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize)
        {
            m_libMaxOffset.QuadPart = libNewSize.QuadPart;
            return S_OK;
        }
        STDMETHODIMP CopyTo(IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten) { return E_NOTIMPL; }
        STDMETHODIMP Commit(DWORD grfCommitFlags) { return E_NOTIMPL; }
        STDMETHODIMP Revert() { return E_NOTIMPL; }
        STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return E_NOTIMPL; }
        STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return E_NOTIMPL; }
        STDMETHODIMP Stat(STATSTG* pstatstg, DWORD grfStatFlag) { return E_NOTIMPL; }
        STDMETHODIMP Clone(IStream**ppstm) { return E_NOTIMPL; }

        ULARGE_INTEGER Size () { return m_libMaxOffset; }
        void Clear() { m_libMaxOffset.QuadPart = 0; }

        ULARGE_INTEGER m_libSeek;
        ULARGE_INTEGER m_libMaxOffset;
};
        

/////////////////////////////////////////////////////////////////////////////
// IPersistMemoryImpl - Provides an implementation of IPersistMemory.

template <class T, class S = IPersistStreamInit>
class ATL_NO_VTABLE IPersistMemoryImpl : public IPersistMemory
{
public:
	// IPersist
	STDMETHODIMP GetClassID(CLSID *pClassID)
	{
		ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::GetClassID\n"));
		T* pT = static_cast<T*>(this);
        S* psi = static_cast <S*> (pT);
        return psi->GetClassID(pClassID);
	}

	// IPersistMemory
    STDMETHODIMP IsDirty()
	{
		ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::IsDirty\n"));
		T* pT = static_cast<T*>(this);
        S* psi = static_cast <S*> (pT);
		return psi->IsDirty();
	}
	STDMETHODIMP Load(void* pvMem, ULONG cbSize)
	{
		ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::Load\n"));
		T* pT = static_cast<T*>(this);

        // Get memory handle
        HGLOBAL h = GlobalAlloc (GMEM_MOVEABLE, cbSize);
        if (NULL == h) return E_OUTOFMEMORY;
        LPVOID pv = GlobalLock (h);
        if (!pv) return E_OUTOFMEMORY;

        // Copy to memory block
        CopyMemory (pv, pvMem, cbSize);
        CComPtr<IStream> spStrm;
        // Create stream on memory
        HRESULT hr = CreateStreamOnHGlobal (h, TRUE, &spStrm);
        if (FAILED (hr)) {
            GlobalUnlock (h);
            GlobalFree (h);
            return hr;
        }
        // Stream now owns the memory

        // Load from stream
        S* psi = static_cast <S*> (pT);
        hr = psi->Load (spStrm);

        GlobalUnlock (h);
		return hr;
	}
	STDMETHODIMP Save(void* pvMem, BOOL fClearDirty, ULONG cbSize)
    {
		ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::Save\n"));
		T* pT = static_cast<T*>(this);

        // Get memory handle
        HGLOBAL h = GlobalAlloc (GMEM_MOVEABLE, cbSize);
        if (NULL == h) return E_OUTOFMEMORY;

        // Create stream on memory
        CComPtr<IStream> spStrm;
        HRESULT hr = CreateStreamOnHGlobal (h, TRUE, &spStrm);
        if (FAILED (hr)) {
            GlobalFree (h);
            return hr;
        }
        // Stream now owns the memory

        // Set logical size of stream to physical size of memory
        // (Global memory block allocation rounding causes differences)
        ULARGE_INTEGER uli;
        uli.QuadPart = cbSize ;
        spStrm->SetSize (uli);

        S* psi = static_cast <S*> (pT);
        hr = psi->Save (spStrm, fClearDirty);
        if (FAILED (hr)) return hr;

        LPVOID pv = GlobalLock (h);
        if (!pv) return E_OUTOFMEMORY;

        // Copy to memory block
        CopyMemory (pvMem, pv, cbSize);
        
		return hr;
	}
	STDMETHODIMP GetSizeMax(ULONG* pCbSize)
	{
        if (NULL == pCbSize) return E_POINTER;
        *pCbSize = 0 ;

		T* pT = static_cast<T*>(this);
        S* psi = static_cast <S*> (pT);
        ULARGE_INTEGER uli ;
        uli.QuadPart = 0;
        HRESULT hr = psi->GetSizeMax (&uli);
        if (SUCCEEDED (hr)) *pCbSize = uli.LowPart;

        return hr;
	}

	STDMETHODIMP InitNew()
    {
        ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::InitNew\n"));
        T* pT = static_cast<T*>(this);
        S* psi = static_cast <S*> (pT);
        return psi->InitNew();
    }
};


#if 0   
template <class T, class S>
STDMETHODIMP IPersistMemoryImpl<T, IPersistStream>::InitNew()
{
    ATLTRACE2(atlTraceCOM, 0, _T("IPersistMemoryImpl::InitNew\n"));
    return S_OK;
}
#endif

/////////////////////////////////////////////////////////////////////////////
// IMarshalByValueImpl - Provides an implementation of IMarshal that marshals
// by value any object that fully implements IPersistStream. This means the
// object must implement GetSizeMax. Derived from code originally presented
// by Don Box in MSJ and subsequently modified by Jonathan Bordan, Chris Sells
// and Brent Rector.

template <class T>
class ATL_NO_VTABLE IMarshalByValueImpl : public IMarshal
{
    STDMETHODIMP GetUnmarshalClass(REFIID /* riid */, void* /* pv */, DWORD /* dwDestContext */, void* /* pvDestContext */, DWORD /* mshlflags */, CLSID *pCid)
    {
        T* pT = static_cast<T*>(this);
        IPersistStreamInit* psi = static_cast <IPersistStreamInit*> (pT);
        return psi->GetClassID (pCid);
    }
    STDMETHODIMP GetMarshalSizeMax(REFIID /* riid */, void* /* pv */, DWORD /* dwDestContext */, void* /* pvDestContext */, DWORD /* mshlflags */, DWORD* pSize)
    {
        T* pT = static_cast<T*>(this);
        IPersistStreamInit* psi = static_cast <IPersistStreamInit*> (pT);

        ULARGE_INTEGER uli = { 0 };

        HRESULT hr = psi->GetSizeMax(&uli);
        if (SUCCEEDED (hr)) *pSize = uli.LowPart;
        return hr;
    }
    STDMETHODIMP MarshalInterface(IStream *pStm, REFIID /* riid */, void* /* pv */, DWORD /* dwDestContext */, void* /* pvDestCtx */, DWORD /* mshlflags */)
    {
        T* pT = static_cast<T*>(this);
        IPersistStreamInit* psi = static_cast <IPersistStreamInit*> (pT);
        return psi->Save(pStm, FALSE);
    }
    STDMETHODIMP UnmarshalInterface(IStream *pStm, REFIID riid, void **ppv)
    {
        T* pT = static_cast<T*>(this);
        IPersistStreamInit* psi = static_cast <IPersistStreamInit*> (pT);
        HRESULT hr = psi->Load(pStm);
        if (SUCCEEDED (hr)) hr = pT->QueryInterface (riid, ppv);
        return hr;
    }
    STDMETHODIMP ReleaseMarshalData(IStream* /* pStm */) { return S_OK; }
    STDMETHODIMP DisconnectObject(DWORD /* dwReserved */) { return S_OK; }
};

/////////////////////////////////////////////////////////////////////////////
// IPersistStreamInitImpl2 - Provides an implementation of IPersistStreamInit
// that actually implements GetSizeMax.

template <class T>
class ATL_NO_VTABLE IPersistStreamInitImpl2 : public IPersistStreamInitImpl<T>
{
public:
#if 0
    STDMETHOD(GetSizeMax)(ULARGE_INTEGER* pcbSize)
    {
        if (NULL == pcbSize) return E_POINTER;

        pcbSize->QuadPart = 0;

        T*      pT = static_cast<T*>(this);

        CComPtr<IUnknown>   pUnk = pT->GetUnknown();
        ATL_PROPMAP_ENTRY*  pMap = T::GetPropertyMap();
        ATLASSERT(pMap != NULL);

        CComPtr<IDispatch>  pDispatch;
        const IID*          piidOld = NULL;

        // For each persistent property entry in the property map
        for (int i = 0; pMap[i].pclsidPropPage != NULL; i++) {
            if (pMap[i].szDesc == NULL)
                continue;

            // Just use the actual size of a raw data entry
            if (pMap[i].dwSizeData != 0) {
                pcbSize->QuadPart += pMap[i].dwSizeData;
                continue;
            }

            // Fetch the new IDispatch interface when we don't already have it
            CComVariant var;
            if (pMap[i].piidDispatch != piidOld) {
                pDispatch.Release();
                if (FAILED(pUnk->QueryInterface(*pMap[i].piidDispatch, (void**)&pDispatch))) {
                    ATLTRACE2(atlTraceCOM, 0, _T("Failed to get a dispatch pointer for property #%i\n"), i);
                    return E_FAIL;
                }
                piidOld = pMap[i].piidDispatch;
            }

            // Fetch the property described in the property map
            if (FAILED(CComDispatchDriver::GetProperty(pDispatch, pMap[i].dispid, &var))) {
                ATLTRACE2(atlTraceCOM, 0, _T("Invoked failed on DISPID %x\n"), pMap[i].dispid);
                return E_FAIL;
            }

            // Interface pointers persist as a CLSID followed by the object's persistent stream
            switch (var.vt) {
            case VT_UNKNOWN:    case VT_DISPATCH:
            {
                CComQIPtr<IPersistStream> spStream(var.punkVal);
                if (!spStream) QueryInterface(IID_IPersistStreamInit, (void**)&spStream);
                if (!spStream) {
                    ATLTRACE2(atlTraceCOM, 0, _T("Object doesn't implement IPersistStream[Init]\n"));
                    return E_FAIL;
                }
                ULARGE_INTEGER cbWrite = { 0 };
                HRESULT hr = spStream->GetSizeMax(&cbWrite);
                if (FAILED(hr)) return hr;
                pcbSize->QuadPart += cbWrite.QuadPart + sizeof(CLSID);
                continue;
            }

            // Scalar types persist as their size
            case VT_UI1:    case VT_I1:
                pcbSize->QuadPart += sizeof(BYTE);
                continue;
            case VT_I2:     case VT_UI2:    case VT_BOOL:
                pcbSize->QuadPart += sizeof(short);
                continue;
            case VT_I4:     case VT_UI4:    case VT_R4:
            case VT_INT:    case VT_UINT:   case VT_ERROR:
                pcbSize->QuadPart += sizeof(long);
                continue;
            case VT_R8:     case VT_CY:     case VT_DATE:
                pcbSize->QuadPart += sizeof(double);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -