1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#pragma once
#include <type_traits>
#include "../comLightClient.h"
#include "../utils/typeTraits.hpp"
#include "../Exception.hpp"
namespace ComLight
{
namespace details
{
GENERATE_HAS_MEMBER( implQueryInterface );
GENERATE_HAS_MEMBER( implAddRef );
GENERATE_HAS_MEMBER( implRelease );
}
// Outer class of objects, implements IUnknown methods, also the class factory. The type argument must be your class implementing your interfaces, inherited from ObjectRoot<I>
template<class T>
class Object : public T
{
public:
Object() = default;
template<typename ... Args>
Object( Args&& ... args ) : T{ std::forward<Args>( args )... } {};
inline virtual ~Object() override { }
// Implement IUnknown methods
HRESULT COMLIGHTCALL QueryInterface( REFIID riid, void** ppvObject ) override
{
static_assert( details::has_member_implQueryInterface<T>::value, "Your object class must inherit from ComLight::ObjectRoot" );
if( nullptr == ppvObject )
return E_POINTER;
if( T::implQueryInterface( riid, ppvObject ) )
return S_OK;
if( T::queryExtraInterfaces( riid, ppvObject ) )
return S_OK;
if( riid == IUnknown::iid() )
{
ComLight::IUnknown* unk = T::getUnknown();
unk->AddRef();
*ppvObject = unk;
return S_OK;
}
return E_NOINTERFACE;
}
uint32_t COMLIGHTCALL AddRef() override
{
static_assert( details::has_member_implAddRef<T>::value, "Your object class must inherit from ComLight::ObjectRoot" );
return T::implAddRef();
}
uint32_t COMLIGHTCALL Release() override
{
static_assert( details::has_member_implRelease<T>::value, "Your object class must inherit from ComLight::ObjectRoot" );
const uint32_t ret = T::implRelease();
if( 0 == ret )
{
T::FinalRelease();
delete this;
}
return ret;
}
// Create a new object on the heap, store in smart pointer
static inline HRESULT create( CComPtr<Object<T>>& result )
{
CComPtr<Object<T>> ptr;
try
{
ptr = new Object<T>(); // The RefCounter constructor creates it with ref.counter 0. But then CComPtr constructor calls AddRef so we have RC=1 after this line.
HRESULT hr = ptr->internalFinalConstruct();
if( FAILED( hr ) )
return hr;
hr = ptr->FinalConstruct();
if( FAILED( hr ) )
return hr;
ptr.swap( result );
return S_OK;
}
catch( const Exception& ex )
{
return ex.code();
}
}
// Create a new object on the heap, store in smart pointer
template<typename ... Args>
static inline HRESULT create( CComPtr<Object<T>>& result, Args&& ... args )
{
CComPtr<Object<T>> ptr;
try
{
ptr = new Object<T>( std::forward<Args>( args )... );
HRESULT hr = ptr->internalFinalConstruct();
if( FAILED( hr ) )
return hr;
hr = ptr->FinalConstruct();
if( FAILED( hr ) )
return hr;
ptr.swap( result );
return S_OK;
}
catch( const Exception& ex )
{
return ex.code();
}
catch( HRESULT hr )
{
return hr;
}
}
// Create a new object on the heap, return one of it's interfaces. The caller is assumed to take ownership of the new object.
template<class I>
static inline HRESULT create( I** pp )
{
if( pp == nullptr )
return E_POINTER;
static_assert( details::pointersAssignable<I, T>(), "Object::create can't cast object to the requested interface" );
CComPtr<Object<T>> ptr;
CHECK( create( ptr ) );
ptr.detach( pp );
return S_OK;
}
};
}
|