diff options
Diffstat (limited to 'shared/com_ptr.h')
-rw-r--r-- | shared/com_ptr.h | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/shared/com_ptr.h b/shared/com_ptr.h new file mode 100644 index 00000000..1ce7eae6 --- /dev/null +++ b/shared/com_ptr.h @@ -0,0 +1,186 @@ +// ************************************************************************** +// * This file is part of the FreeFileSync project. It is distributed under * +// * GNU General Public License: http://www.gnu.org/licenses/gpl.html * +// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// ************************************************************************** +// +#ifndef SMART_COM_PTR_H +#define SMART_COM_PTR_H + +#include <Objbase.h> +#include <algorithm> + +namespace util +{ +/* +ComPtr: RAII class handling COM objects + +Example: + -------- + ComPtr<IUPnPDeviceFinder> devFinder; + if (FAILED(::CoCreateInstance(CLSID_UPnPDeviceFinder, + NULL, + CLSCTX_ALL, + IID_PPV_ARGS(devFinder.init())))) + return -1; + + ComPtr<IEnumUnknown> devEnum = com_dynamic_cast<IEnumUnknown>(devColl); + if (!devEnum) + return -1; +*/ + +template <class T> +class ComPtr +{ +public: + ComPtr(); + ComPtr(const ComPtr& rhs); + ComPtr& operator=(const ComPtr& rhs); + ~ComPtr(); + T** init(); //get pointer for use with ::CoCreateInstance() + T* get() const; + T* release(); + void swap(ComPtr& rhs); //throw() + T* operator->() const; + operator bool() const; + +private: + T* ptr; +}; + + +template <class S, class T> +ComPtr<S> com_dynamic_cast(const ComPtr<T>& other); //throw() + + + + + + + + + + + + + + + + + + + + + + + + + +//################# Inline Implementation ############################# + +template <class T> +inline +ComPtr<T>::ComPtr() : ptr(NULL) {} + + +template <class T> +inline +ComPtr<T>::ComPtr(const ComPtr& rhs) : ptr(rhs.ptr) +{ + if (ptr) + ptr->AddRef(); +} + + +template <class T> +inline +ComPtr<T>& ComPtr<T>::operator=(const ComPtr<T>& rhs) +{ + ComPtr(rhs).swap(*this); + return *this; +} + + +template <class T> +inline +ComPtr<T>::~ComPtr() +{ + if (ptr) + ptr->Release(); +} + + +template <class T> +inline +T** ComPtr<T>::init() //get pointer for use with ::CoCreateInstance() +{ + ComPtr<T>().swap(*this); + return &ptr; +} + + +template <class T> +inline +T* ComPtr<T>::get() const +{ + return ptr; +} + + +template <class T> +inline +T* ComPtr<T>::release() //throw() +{ + T* tmp = ptr; + ptr = NULL; + return tmp; +} + + +template <class T> +inline +void ComPtr<T>::swap(ComPtr<T>& rhs) //throw() +{ + std::swap(ptr, rhs.ptr); +} + + +//we cannot specialize std::swap() for a class template and are not allowed to overload it => offer swap in own namespace +template <class T> +inline +void swap(util::ComPtr<T>& lhs, util::ComPtr<T>& rhs) +{ + lhs.swap(rhs); +} + + +template <class T> +inline +T* ComPtr<T>::operator->() const +{ + return ptr; +} + + +template <class T> +inline +ComPtr<T>::operator bool() const +{ + return ptr != NULL; +} + + +template <class S, class T> +inline +ComPtr<S> com_dynamic_cast(const ComPtr<T>& other) //throw() +{ + ComPtr<S> outPtr; + if (other) + other->QueryInterface(IID_PPV_ARGS(outPtr.init())); + return outPtr; +} + +} + + +#endif //SMART_COM_PTR_H
\ No newline at end of file |