617 lines
11 KiB
C
617 lines
11 KiB
C
|
|
||
|
#pragma once
|
||
|
#include <atlbase.h>
|
||
|
#include <utility>
|
||
|
#include <assert.h>
|
||
|
#include "dexception.h"
|
||
|
|
||
|
|
||
|
// AutoPtrBase
|
||
|
//
|
||
|
// Safe pointer class that knows to delete the referrent object when
|
||
|
// the pointer goes out of scope or is replaced, etc.
|
||
|
|
||
|
template<class _TYPE> class AutoPtrBase
|
||
|
{
|
||
|
protected:
|
||
|
|
||
|
mutable BOOL m_bOwns;
|
||
|
_TYPE * m_pRaw;
|
||
|
|
||
|
public:
|
||
|
|
||
|
// Create from raw pointer. This auto pointer now owns the data.
|
||
|
|
||
|
AutoPtrBase(_TYPE * pRaw = NULL)
|
||
|
{
|
||
|
m_bOwns = (pRaw != NULL);
|
||
|
m_pRaw = pRaw;
|
||
|
|
||
|
assert( !m_bOwns || m_pRaw );
|
||
|
}
|
||
|
|
||
|
// Create from other auto pointer. Other auto pointer disowns the data.
|
||
|
|
||
|
AutoPtrBase(const AutoPtrBase<_TYPE> & ptrOther)
|
||
|
{
|
||
|
m_bOwns = ptrOther.m_bOwns;
|
||
|
m_pRaw = (_TYPE *) const_cast<AutoPtrBase<_TYPE> &>(ptrOther)._disownptr();
|
||
|
}
|
||
|
|
||
|
AutoPtrBase<_TYPE> & take(_TYPE * pRawIn)
|
||
|
{
|
||
|
if (m_pRaw != pRawIn)
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
nukeit();
|
||
|
}
|
||
|
m_bOwns = (pRawIn != NULL);
|
||
|
m_pRaw = pRawIn;
|
||
|
|
||
|
assert( !m_bOwns || m_pRaw );
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
virtual ~AutoPtrBase()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
delete m_pRaw;
|
||
|
}
|
||
|
|
||
|
AutoPtrBase<_TYPE> & operator=(_TYPE * pRawIn)
|
||
|
{
|
||
|
take(pRawIn);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
// Assignment of other auto pointer to ourselves. If we are not the
|
||
|
// same object, we take ownership of the data, first releasing any
|
||
|
// we already own.
|
||
|
|
||
|
AutoPtrBase<_TYPE> & operator=(const AutoPtrBase<_TYPE> & ptrOther)
|
||
|
{
|
||
|
if ((void *)this != (void *)&ptrOther)
|
||
|
{
|
||
|
_TYPE * pRaw = const_cast<AutoPtrBase<_TYPE>&>(ptrOther)._disownptr();
|
||
|
take(pRaw);
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
AutoPtrBase<_TYPE> & replace(const AutoPtrBase<_TYPE>& ptrOtherIn)
|
||
|
{
|
||
|
return *this = ptrOtherIn;
|
||
|
}
|
||
|
|
||
|
virtual operator _TYPE*()
|
||
|
{
|
||
|
return get();
|
||
|
}
|
||
|
|
||
|
virtual operator const _TYPE*() const
|
||
|
{
|
||
|
return get();
|
||
|
}
|
||
|
|
||
|
/* Not allowed, since void * wouldn't worl
|
||
|
_TYPE& operator*() const
|
||
|
{
|
||
|
return (*get());
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
_TYPE ** operator&()
|
||
|
{
|
||
|
return _getoutptr();
|
||
|
}
|
||
|
|
||
|
// Will produce errors if applied using infix notation
|
||
|
//#pragma warning(disable:4284)
|
||
|
// _TYPE *operator->() const
|
||
|
// {
|
||
|
// return (get());
|
||
|
// }
|
||
|
//#pragma warning(default:4284)
|
||
|
|
||
|
_TYPE *get() const
|
||
|
{
|
||
|
return (m_pRaw);
|
||
|
}
|
||
|
|
||
|
_TYPE * _disownptr()
|
||
|
{
|
||
|
m_bOwns = FALSE;
|
||
|
return m_pRaw;
|
||
|
}
|
||
|
|
||
|
_TYPE ** _getoutptr()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
nukeit();
|
||
|
m_bOwns = TRUE;
|
||
|
return (&m_pRaw);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// AutoHLOCK
|
||
|
//
|
||
|
|
||
|
template<class _TYPE>
|
||
|
class AutoHLOCK : public AutoPtrBase<_TYPE>
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
protected:
|
||
|
|
||
|
HGLOBAL m_hGlobal;
|
||
|
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
// If the memory object is still locked after decrementing the lock count,
|
||
|
// the return value is a nonzero value. If the function fails, the return
|
||
|
// value is zero. To get extended error information, we call GetLastError.
|
||
|
// If GetLastError returns NO_ERROR, the memory object is unlocked.
|
||
|
|
||
|
if (0 == GlobalUnlock( m_hGlobal) )
|
||
|
assert(NO_ERROR == GetLastError());
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
AutoHLOCK<_TYPE>& operator=(HGLOBAL _H)
|
||
|
{
|
||
|
if (m_hGlobal != _H)
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
nukeit();
|
||
|
m_pRaw = _H ? ((_TYPE*) GlobalLock(_H)) : NULL;
|
||
|
m_bOwns = (NULL != m_pRaw);
|
||
|
|
||
|
m_hGlobal = _H;
|
||
|
|
||
|
assert( !m_bOwns || m_pRaw );
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
~AutoHLOCK()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHLOCK(HGLOBAL _H = 0)
|
||
|
: m_hGlobal(NULL)
|
||
|
{
|
||
|
*this = _H;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// AutoHPALETTE (HPALETTE)
|
||
|
//
|
||
|
|
||
|
class AutoHPALETTE : public AutoPtrBase<struct HPALETTE__>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
DeleteObject((HPALETTE)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHPALETTE()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHPALETTE(HPALETTE pRawIn = 0)
|
||
|
: AutoPtrBase<struct HPALETTE__>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
// AutoHPROPSHEETPAGE
|
||
|
//
|
||
|
|
||
|
class AutoHPROPSHEETPAGE : public AutoPtrBase<struct _PSP>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
DestroyPropertySheetPage((HPROPSHEETPAGE)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHPROPSHEETPAGE()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHPROPSHEETPAGE(HPROPSHEETPAGE pRawIn = 0)
|
||
|
: AutoPtrBase<struct _PSP>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// AutoHKEY (HKEY)
|
||
|
//
|
||
|
|
||
|
class AutoHKEY : public AutoPtrBase<struct HKEY__>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
RegCloseKey((HKEY)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHKEY()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHKEY(HKEY pRawIn = 0)
|
||
|
: AutoPtrBase<struct HKEY__>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// AutoHICON (HICON)
|
||
|
//
|
||
|
|
||
|
class AutoHICON : public AutoPtrBase<struct HICON__>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
DestroyIcon((HICON)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHICON()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHICON& operator=(struct HICON__ * pRawIn)
|
||
|
{
|
||
|
take(pRawIn);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
AutoHICON(HICON pRawIn = 0)
|
||
|
: AutoPtrBase<struct HICON__>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// AutoHBITMAP (HBITMAP)
|
||
|
//
|
||
|
|
||
|
class AutoHBITMAP : public AutoPtrBase<struct HBITMAP__>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
DeleteObject((HBITMAP)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHBITMAP()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHBITMAP& operator=(struct HBITMAP__ * pRawIn)
|
||
|
{
|
||
|
take(pRawIn);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
AutoHBITMAP(HBITMAP pRawIn = 0)
|
||
|
: AutoPtrBase<struct HBITMAP__>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// AutoHDC (HDC)
|
||
|
//
|
||
|
|
||
|
typedef pair<HDC, HWND> WindowDCPair;
|
||
|
|
||
|
class AutoHDC : public AutoPtrBase<WindowDCPair>
|
||
|
{
|
||
|
// If this was from GetDC() call, we'll have the handle of the
|
||
|
// window against which we will need to release it. If not,
|
||
|
// we assume we need to actually DeleteDC() on it.
|
||
|
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
|
||
|
if (get()->second)
|
||
|
ReleaseDC(get()->second, get()->first);
|
||
|
else
|
||
|
DeleteDC(get()->first);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
HDC m_hDC;
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHDC()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHDC& operator=(HDC pRawIn)
|
||
|
{
|
||
|
take( &WindowDCPair(pRawIn, NULL) );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
AutoHDC& operator=( WindowDCPair in)
|
||
|
{
|
||
|
take(&in);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
AutoHDC(HDC hdc = NULL, HWND hwndFrom = NULL)
|
||
|
: AutoPtrBase<WindowDCPair>( &WindowDCPair(hdc, hwndFrom) )
|
||
|
{
|
||
|
}
|
||
|
|
||
|
AutoHDC(HWND hwndFrom)
|
||
|
: AutoPtrBase<WindowDCPair>( &WindowDCPair(GetDC(hwndFrom), hwndFrom) )
|
||
|
{
|
||
|
if (NULL == get()->first)
|
||
|
throw new win32error;
|
||
|
}
|
||
|
|
||
|
operator HDC()
|
||
|
{
|
||
|
return get()->first;
|
||
|
}
|
||
|
|
||
|
operator const HDC() const
|
||
|
{
|
||
|
return get()->first;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// AutoHGLOBAL (HGLOBAL)
|
||
|
//
|
||
|
|
||
|
class AutoHGLOBAL : public AutoPtrBase<void>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
GlobalFree((HGLOBAL)m_pRaw);
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoHGLOBAL()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoHGLOBAL(HGLOBAL pRawIn = 0)
|
||
|
: AutoPtrBase<void>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
class AutoFindHandle
|
||
|
{
|
||
|
public:
|
||
|
AutoFindHandle(HANDLE handle = INVALID_HANDLE_VALUE)
|
||
|
: m_handle(handle), m_bOwns(INVALID_HANDLE_VALUE != handle) { }
|
||
|
|
||
|
AutoFindHandle(const AutoFindHandle& rhs)
|
||
|
: m_handle(INVALID_HANDLE_VALUE), m_bOwns(false)
|
||
|
{ *this = rhs; }
|
||
|
|
||
|
~AutoFindHandle(void)
|
||
|
{ Close(); }
|
||
|
|
||
|
void Close(void);
|
||
|
|
||
|
HANDLE Detach(void) const
|
||
|
{ m_bOwns = false; return m_handle; }
|
||
|
|
||
|
void Attach(HANDLE handle)
|
||
|
{ Close(); m_handle = handle; m_bOwns = true; }
|
||
|
|
||
|
operator HANDLE() const
|
||
|
{ return m_handle; }
|
||
|
|
||
|
bool IsValid(void) const
|
||
|
{ return INVALID_HANDLE_VALUE != m_handle; }
|
||
|
|
||
|
AutoFindHandle& operator = (HANDLE handle)
|
||
|
{ Attach(handle); return *this; }
|
||
|
|
||
|
AutoFindHandle& operator = (const AutoFindHandle& rhs);
|
||
|
|
||
|
private:
|
||
|
mutable HANDLE m_handle;
|
||
|
mutable bool m_bOwns;
|
||
|
};
|
||
|
|
||
|
// AutoPtr
|
||
|
//
|
||
|
|
||
|
template<class _TYPE>
|
||
|
class AutoPtr : public AutoPtrBase<_TYPE>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
delete m_pRaw;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoPtr()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoPtr(_TYPE *pRawIn = 0)
|
||
|
: AutoPtrBase<_TYPE>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
AutoPtr<_TYPE> & operator=(const AutoPtr<_TYPE> & ptrOther)
|
||
|
{
|
||
|
if (this != &ptrOther)
|
||
|
{
|
||
|
AutoPtr<_TYPE> * pptrOther = const_cast<AutoPtr<_TYPE> *>(&ptrOther);
|
||
|
m_bOwns = pptrOther->m_bOwns;
|
||
|
m_pRaw = (_TYPE *) (pptrOther->_disownptr());
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
AutoPtr(const AutoPtr<_TYPE> & ptrOther)
|
||
|
{
|
||
|
*this = ptrOther;
|
||
|
}
|
||
|
|
||
|
// AutoPtr<_TYPE> & operator=(_TYPE * pRawIn)
|
||
|
AutoPtr<_TYPE> & operator=(_TYPE * pRawIn)
|
||
|
{
|
||
|
take(pRawIn);
|
||
|
return *this;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// AutoComPtr
|
||
|
//
|
||
|
// Smart pointer that calls _disownptr() on the referent when the pointer itself
|
||
|
// goes out of scope
|
||
|
|
||
|
template <class _TYPE>
|
||
|
class AutoComPtr : public CComPtr<_TYPE>
|
||
|
{
|
||
|
public:
|
||
|
AutoComPtr(void) { }
|
||
|
|
||
|
AutoComPtr(_TYPE *p)
|
||
|
: CComPtr<_TYPE>(p) { }
|
||
|
|
||
|
AutoComPtr(const AutoComPtr<_TYPE>& rhs)
|
||
|
: CComPtr<_TYPE>(rhs.p) { }
|
||
|
|
||
|
AutoComPtr& operator = (const AutoComPtr& rhs)
|
||
|
{
|
||
|
if (this != &rhs)
|
||
|
{
|
||
|
CComPtr<_TYPE>::operator = (rhs);
|
||
|
}
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Retrieve the address of the contained interface ptr.
|
||
|
// ptr._getoutptr() is equivalent to &ptr.p
|
||
|
//
|
||
|
_TYPE **_getoutptr(void)
|
||
|
{
|
||
|
return &p;
|
||
|
}
|
||
|
|
||
|
_TYPE * _disownptr(void)
|
||
|
{
|
||
|
return Detach();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// WARNING: This hides the CComPtr implementation of operator&().
|
||
|
// It's intentional. Otherwise you can't pass the address
|
||
|
// of an AutoComPtr to a function and get the expected semantics.
|
||
|
// CComPtr's implementation returns the address of the contained
|
||
|
// pointer. If this is what you want, use AutoComtPtr::_getoutptr().
|
||
|
//
|
||
|
AutoComPtr *operator& (void)
|
||
|
{
|
||
|
return this;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef USE_SHELL_AUTOPTR
|
||
|
|
||
|
#include <cshalloc.h>
|
||
|
|
||
|
// App must declare a global instance of this class
|
||
|
|
||
|
extern CSHAlloc g_SHAlloc;
|
||
|
|
||
|
// AutoShellPtr
|
||
|
//
|
||
|
// Smart pointer that manually runs the referent's destructor and then
|
||
|
// calls the shell's task allocator to free the object's memory footprint
|
||
|
|
||
|
template<class _TYPE>
|
||
|
class AutoShellPtr : virtual public AutoPtrBase<_TYPE>
|
||
|
{
|
||
|
virtual void nukeit()
|
||
|
{
|
||
|
if (m_pRaw)
|
||
|
{
|
||
|
m_pRaw->~_TYPE();
|
||
|
g_SHAlloc.Free(m_pRaw);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
~AutoShellPtr()
|
||
|
{
|
||
|
if (m_bOwns)
|
||
|
this->nukeit();
|
||
|
}
|
||
|
|
||
|
AutoShellPtr(_TYPE *pRawIn = 0)
|
||
|
: AutoPtrBase<_TYPE>(pRawIn)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
AutoShellPtr<_TYPE> & operator=(_TYPE * pRawIn)
|
||
|
{
|
||
|
take(pRawIn);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
#endif
|