📄 utility.h
字号:
// 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 + -