-
Notifications
You must be signed in to change notification settings - Fork 1
/
Object.h
93 lines (82 loc) · 1.99 KB
/
Object.h
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
#pragma once
#include <objbase.h>
#include <atomic>
#include "Module.h"
#include "Dispatch.h"
#include "InterfaceList.h"
namespace Com
{
template <typename Type, const CLSID* Clsid, typename... Interfaces>
class Object : public Dispatch<InterfaceList<Interfaces...>>, public ISupportErrorInfo
{
protected:
std::atomic<int> referenceCount = 0;
public:
Object()
{
Module::GetInstance().AddRef();
}
Object(const Object<Type, Clsid, Interfaces...>& rhs) = delete;
virtual ~Object()
{
Module::GetInstance().Release();
}
Object<Type, Clsid, Interfaces...>& operator=(const Object<Type, Clsid, Interfaces...>& rhs) = delete;
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) final
{
if (ppvObject == nullptr)
return E_POINTER;
if (riid == IID_IUnknown)
*ppvObject = static_cast<IUnknown*>(static_cast<PrimaryInterface*>(this));
else if (SupportsDispatch && riid == IID_IDispatch)
*ppvObject = GetDispatchInterface();
else if (riid == IID_ISupportErrorInfo)
*ppvObject = static_cast<ISupportErrorInfo*>(this);
else if (!QueryInterfaceInternal(riid, ppvObject))
return E_NOINTERFACE;
++referenceCount;
return S_OK;
}
ULONG __stdcall AddRef() final
{
return ++referenceCount;
}
ULONG __stdcall Release() final
{
auto result = --referenceCount;
if (result == 0)
{
OnFinalRelease();
delete this;
}
return result;
}
HRESULT __stdcall InterfaceSupportsErrorInfo(REFIID riid)
{
return S_OK;
}
virtual HRESULT OnFinalConstruct()
{
return S_OK;
}
virtual void OnFinalRelease()
{
}
static HRESULT TryCreateInstance(REFIID riid, void** ppvObject)
{
if (ppvObject == nullptr)
return E_POINTER;
auto object = new Type();
auto hr = object->OnFinalConstruct();
if (SUCCEEDED(hr))
hr = object->QueryInterface(riid, ppvObject);
if (FAILED(hr))
delete object;
return hr;
}
static bool Is(REFCLSID rclsid)
{
return Clsid != nullptr && rclsid == *Clsid;
}
};
}