#pragma once
#ifndef __HWINCOM_H__
#define __HWINCOM_H__
#include "hwindef.h"
#include "hwinexception.h"
#include "hwinlog.h"
#include "hwinguid.h"
namespace harlinn
{
namespace windows
{
class Unknown
{
protected:
IUnknown* unknown;
public:
typedef IUnknown InterfaceType;
Unknown()
: unknown(nullptr)
{
HWIN_TRACE();
}
explicit Unknown(IUnknown* theUnknown, bool addref = false)
: unknown(theUnknown)
{
HWIN_TRACE();
if( addref && (unknown != nullptr))
{
unknown->AddRef();
}
}
Unknown(REFIID iid, const Unknown& theUnknown, bool throwIfNoInterface = true )
: unknown(nullptr)
{
HWIN_TRACE();
if( theUnknown )
{
IUnknown* pInterface = nullptr;
auto hr = theUnknown.unknown->QueryInterface(iid,(void**)&pInterface);
if(FAILED(hr))
{
if((throwIfNoInterface == false)&&(hr == E_NOINTERFACE))
{
return;
}
CheckHRESULT(hr);
}
unknown = pInterface;
}
}
Unknown(const Unknown& other)
: unknown(other.unknown)
{
HWIN_TRACE();
if(unknown)
{
unknown->AddRef();
}
}
Unknown(Unknown&& other)
: unknown(0)
{
HWIN_TRACE();
if(other.unknown)
{
unknown = other.unknown;
other.unknown = nullptr;
}
}
~Unknown()
{
HWIN_TRACE();
IUnknown* tmp = unknown;
unknown = nullptr;
if(tmp)
{
tmp->Release();
}
}
operator bool() const
{
HWIN_TRACE();
return unknown != nullptr;
}
Unknown& operator = (const Unknown& other)
{
HWIN_TRACE();
if(unknown != other.unknown)
{
if(unknown)
{
IUnknown* tmp = unknown;
unknown = nullptr;
tmp->Release();
}
unknown = other.unknown;
if(unknown)
{
unknown->AddRef();
}
}
return *this;
}
Unknown& operator = (Unknown&& other)
{
HWIN_TRACE();
if (this != &other)
{
IUnknown* tmp = unknown;
unknown = nullptr;
if(tmp)
{
tmp->Release();
}
unknown = other.unknown;
other.unknown = nullptr;
}
return *this;
}
Unknown& Reset(IUnknown* other = nullptr, bool addRef = false)
{
HWIN_TRACE();
if(unknown != other)
{
if(unknown)
{
IUnknown* tmp = unknown;
unknown = nullptr;
tmp->Release();
}
unknown = other;
if( addRef && (unknown != nullptr))
{
unknown->AddRef();
}
}
return *this;
}
template<typename T>
T As() const
{
HWIN_TRACE();
const Unknown& self = *this;
T result(self,false);
return result;
}
template<typename T>
bool Is() const
{
HWIN_TRACE();
if(unknown)
{
T::InterfaceType* pInterface = nullptr;
auto hr = unknown->QueryInterface(__uuidof(T::InterfaceType),(void**)&pInterface);
if(hr == S_OK )
{
pInterface->Release();
return true;
}
}
return false;
}
template<typename T>
T* GetInterfacePointer() const
{
HWIN_TRACE();
if(unknown)
{
return reinterpret_cast<T*>(unknown);
}
return nullptr;
}
template<typename T>
static T CoCreateInstanceFromClassId(const CLSID& clsid, DWORD classContext = CLSCTX_INPROC_SERVER)
{
HWIN_TRACE();
T::InterfaceType* result = nullptr;
auto hr = CoCreateInstance(clsid,NULL,classContext,__uuidof(T::InterfaceType),(void**)&result);
CheckHRESULT(hr);
return T(result);
}
template<typename T>
static T CoCreateInstanceFromClassId(const String& clsid, DWORD classContext = CLSCTX_INPROC_SERVER)
{
HWIN_TRACE();
CLSID CLSID_ = {0,};
auto hr = CLSIDFromString(clsid.c_str(),&CLSID_);
CheckHRESULT(hr);
T::InterfaceType* result = nullptr;
hr = CoCreateInstance(CLSID_,NULL,classContext,__uuidof(T::InterfaceType),(void**)&result);
CheckHRESULT(hr);
return T(result);
}
template<typename T>
static T CoCreateInstanceFromProgId(const String& progId, DWORD classContext = CLSCTX_INPROC_SERVER)
{
HWIN_TRACE();
CLSID CLSID_ = {0,};
auto hr = CLSIDFromProgIDEx(clsid.c_str(),&CLSID_);
CheckHRESULT(hr);
T::InterfaceType* result = nullptr;
hr = CoCreateInstance(CLSID_,NULL,classContext,__uuidof(T::InterfaceType),(void**)&result);
CheckHRESULT(hr);
return T(result);
}
};
#define HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL( classType, baseClassType , interfaceType, baseInterfaceType ) \
public: \
typedef interfaceType InterfaceType; \
typedef baseInterfaceType BaseInterfaceType; \
private: \
InterfaceType * GetInterface() const { HWIN_TRACE();if(!unknown) { ThrowNoInterface(); } return reinterpret_cast< InterfaceType *>( unknown ); } \
public: \
classType () \
: baseClassType ( ) \
{} \
explicit classType (interfaceType * theInterface, bool addref = false ) \
: baseClassType ( reinterpret_cast< baseInterfaceType *>( theInterface ), addref ) \
{ HWIN_TRACE(); } \
protected: \
classType (REFIID iid, const Unknown& theUnknown, bool throwIfNoInterface = true ) \
: baseClassType ( iid, reinterpret_cast< const baseClassType & > (theUnknown), throwIfNoInterface ) \
{ HWIN_TRACE(); } \
public: \
classType ( const Unknown& theUnknown, bool throwIfNoInterface = true ) \
: baseClassType ( __uuidof(interfaceType), reinterpret_cast< const baseClassType & > (theUnknown), throwIfNoInterface ) \
{ HWIN_TRACE(); } \
classType (const classType & other) \
: baseClassType ( reinterpret_cast< const baseClassType & > (other) ) \
{ HWIN_TRACE(); } \
classType (classType && other) \
: baseClassType ( reinterpret_cast< baseClassType && >( other ) ) \
{ HWIN_TRACE(); } \
classType & operator = (const classType & other) \
{ \
HWIN_TRACE(); \
baseClassType :: operator = ( reinterpret_cast< const baseClassType & > (other) ); \
return *this; \
} \
classType & operator = (classType && other) \
{ \
HWIN_TRACE(); \
baseClassType :: operator = ( reinterpret_cast< baseClassType && > (other) ); \
return *this; \
} \
operator interfaceType * ( ) const\
{ \
HWIN_TRACE(); \
return reinterpret_cast< interfaceType * >( unknown ); \
}
template<typename T>
class UnknownPtr : public Unknown
{
public:
typedef Unknown Base;
UnknownPtr()
: Base(nullptr)
{
HWIN_TRACE();
}
explicit UnknownPtr(T* unknown)
: Base(unknown)
{
HWIN_TRACE();
}
UnknownPtr(const UnknownPtr& other)
: Base(other)
{
HWIN_TRACE();
}
UnknownPtr(UnknownPtr&& other)
: Base(other)
{
HWIN_TRACE();
}
UnknownPtr& operator = (const UnknownPtr& other)
{
HWIN_TRACE();
Base::operator=(other);
return *this;
}
UnknownPtr& operator = (UnknownPtr&& other)
{
HWIN_TRACE();
Base::operator=(other);
return *this;
}
T* operator -> () const
{
HWIN_TRACE();
return (T*)unknown;
}
};
template< class InterfaceType >
class IUnknownImplementation : public InterfaceType
{
ULONG referenceCount;
public:
IUnknownImplementation()
: referenceCount(1)
{
HWIN_TRACE();
}
virtual ~IUnknownImplementation()
{
HWIN_TRACE();
}
virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void ** ppvObject )
{
HWIN_TRACE();
if (!ppvObject)
{
return E_INVALIDARG;
}
*ppvObject = NULL;
if (riid == IID_IUnknown )
{
IUnknown* pInterface = this;
*ppvObject = (LPVOID)pInterface;
AddRef();
return NOERROR;
}
else if(riid == __uuidof(InterfaceType))
{
InterfaceType* pInterface = this;
*ppvObject = (LPVOID)pInterface;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef( void )
{
HWIN_TRACE();
ULONG result = InterlockedIncrement(&referenceCount);
return result;
}
virtual ULONG STDMETHODCALLTYPE Release( void )
{
HWIN_TRACE();
ULONG result = InterlockedDecrement(&referenceCount);
if (result == 0)
{
delete this;
}
return result;
}
};
class EnumString : public Unknown
{
public:
typedef Unknown Base;
HARLINN_WINDOWS_COM_STANDARD_METHODS_IMPL(EnumString,Unknown,IEnumString,IUnknown)
HWIN_EXPORT bool Next( String& theResult );
HWIN_EXPORT bool Next( ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched );
HWIN_EXPORT bool Next( ULONG celt, const std::shared_ptr< std::vector<String> >& strings);
HWIN_EXPORT std::shared_ptr< std::vector<String> > All();
HWIN_EXPORT EnumString& Skip( ULONG celt );
HWIN_EXPORT EnumString& Reset( );
HWIN_EXPORT EnumString Clone( );
};
};
};
#endif //__HWINCOM_H__