diff options
Diffstat (limited to 'contrib/DirectX-Headers/include/wsl')
9 files changed, 1180 insertions, 0 deletions
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/OAIdl.h b/contrib/DirectX-Headers/include/wsl/stubs/OAIdl.h new file mode 100644 index 0000000..76f5b5f --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/OAIdl.h | |||
@@ -0,0 +1,5 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub header to satisfy d3d12.h include | ||
5 | #pragma once \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/OCIdl.h b/contrib/DirectX-Headers/include/wsl/stubs/OCIdl.h new file mode 100644 index 0000000..76f5b5f --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/OCIdl.h | |||
@@ -0,0 +1,5 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub header to satisfy d3d12.h include | ||
5 | #pragma once \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/rpc.h b/contrib/DirectX-Headers/include/wsl/stubs/rpc.h new file mode 100644 index 0000000..76f5b5f --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/rpc.h | |||
@@ -0,0 +1,5 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub header to satisfy d3d12.h include | ||
5 | #pragma once \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/rpcndr.h b/contrib/DirectX-Headers/include/wsl/stubs/rpcndr.h new file mode 100644 index 0000000..5b5f2e8 --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/rpcndr.h | |||
@@ -0,0 +1,6 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub header to satisfy d3d12.h include | ||
5 | #pragma once | ||
6 | #define __RPCNDR_H_VERSION__ \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/winapifamily.h b/contrib/DirectX-Headers/include/wsl/stubs/winapifamily.h new file mode 100644 index 0000000..064c4c2 --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/winapifamily.h | |||
@@ -0,0 +1,6 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub header to satisfy d3d12.h include. Unconditionally light up all APIs. | ||
5 | #pragma once | ||
6 | #define WINAPI_FAMILY_PARTITION(Partitions) 1 \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/wrl/client.h b/contrib/DirectX-Headers/include/wsl/stubs/wrl/client.h new file mode 100644 index 0000000..43e7d0b --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/wrl/client.h | |||
@@ -0,0 +1,6 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub to satisfy d3dx12.h include | ||
5 | #pragma once | ||
6 | #include "../wrladapter.h" \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/stubs/wrl/implements.h b/contrib/DirectX-Headers/include/wsl/stubs/wrl/implements.h new file mode 100644 index 0000000..fb2bebc --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/stubs/wrl/implements.h | |||
@@ -0,0 +1,6 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | // Stub to satisfy DML TF runtime includes | ||
5 | #pragma once | ||
6 | #include "wrladapter.h" \ No newline at end of file | ||
diff --git a/contrib/DirectX-Headers/include/wsl/winadapter.h b/contrib/DirectX-Headers/include/wsl/winadapter.h new file mode 100644 index 0000000..8400f4a --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/winadapter.h | |||
@@ -0,0 +1,340 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | // These #defines prevent the idl-generated headers from trying to include | ||
7 | // Windows.h from the SDK rather than this one. | ||
8 | #define RPC_NO_WINDOWS_H | ||
9 | #define COM_NO_WINDOWS_H | ||
10 | |||
11 | // Allcaps type definitions | ||
12 | #include <stddef.h> | ||
13 | #include <stdint.h> | ||
14 | #include <string.h> | ||
15 | #include <limits.h> | ||
16 | |||
17 | // Note: using fixed-width here to match Windows widths | ||
18 | // Specifically this is different for 'long' vs 'LONG' | ||
19 | typedef uint8_t UINT8; | ||
20 | typedef int8_t INT8; | ||
21 | typedef uint16_t UINT16; | ||
22 | typedef int16_t INT16; | ||
23 | typedef uint32_t UINT32, UINT, ULONG, DWORD, BOOL; | ||
24 | typedef int32_t INT32, INT, LONG; | ||
25 | typedef uint64_t UINT64, ULONG_PTR; | ||
26 | typedef int64_t INT64, LONG_PTR; | ||
27 | typedef void VOID, *HANDLE, *RPC_IF_HANDLE, *LPVOID; | ||
28 | typedef const void *LPCVOID; | ||
29 | typedef size_t SIZE_T; | ||
30 | typedef float FLOAT; | ||
31 | typedef double DOUBLE; | ||
32 | typedef unsigned char BYTE; | ||
33 | typedef int HWND; | ||
34 | |||
35 | // Note: WCHAR is not the same between Windows and Linux, to enable | ||
36 | // string manipulation APIs to work with resulting strings. | ||
37 | // APIs to D3D/DXCore will work on Linux wchars, but beware with | ||
38 | // interactions directly with the Windows kernel. | ||
39 | typedef char CHAR, *PSTR, *LPSTR, TCHAR, *PTSTR; | ||
40 | typedef const char *LPCSTR, *PCSTR, *LPCTSTR, *PCTSTR; | ||
41 | typedef wchar_t WCHAR, *PWSTR, *LPWSTR, *PWCHAR; | ||
42 | typedef const wchar_t *LPCWSTR, *PCWSTR; | ||
43 | |||
44 | #undef LONG_MAX | ||
45 | #define LONG_MAX INT_MAX | ||
46 | #undef ULONG_MAX | ||
47 | #define ULONG_MAX UINT_MAX | ||
48 | |||
49 | // Misc defines | ||
50 | #define interface struct | ||
51 | #define MIDL_INTERFACE(x) interface | ||
52 | #define __analysis_assume(x) | ||
53 | #define TRUE 1u | ||
54 | #define FALSE 0u | ||
55 | #define DECLARE_INTERFACE(iface) interface iface | ||
56 | #define PURE = 0 | ||
57 | #define THIS_ | ||
58 | #define DECLSPEC_UUID(x) | ||
59 | #define DECLSPEC_NOVTABLE | ||
60 | #define DECLSPEC_SELECTANY | ||
61 | #define EXTERN_C extern "C" | ||
62 | |||
63 | typedef struct _GUID { | ||
64 | uint32_t Data1; | ||
65 | uint16_t Data2; | ||
66 | uint16_t Data3; | ||
67 | uint8_t Data4[ 8 ]; | ||
68 | } GUID; | ||
69 | |||
70 | #ifdef __cplusplus | ||
71 | #ifdef INITGUID | ||
72 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) extern "C" const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } | ||
73 | #else | ||
74 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) extern "C" const GUID name | ||
75 | #endif | ||
76 | |||
77 | template <typename T> GUID uuidof() = delete; | ||
78 | template <typename T> GUID uuidof(T*) { return uuidof<T>(); } | ||
79 | template <typename T> GUID uuidof(T**) { return uuidof<T>(); } | ||
80 | template <typename T> GUID uuidof(T&) { return uuidof<T>(); } | ||
81 | #define __uuidof(x) uuidof(x) | ||
82 | #else | ||
83 | #ifdef INITGUID | ||
84 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } | ||
85 | #else | ||
86 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) extern const GUID name | ||
87 | #endif | ||
88 | #endif | ||
89 | |||
90 | typedef GUID IID; | ||
91 | typedef GUID UUID; | ||
92 | typedef GUID CLSID; | ||
93 | #ifdef __cplusplus | ||
94 | #define REFGUID const GUID & | ||
95 | #define REFIID const IID & | ||
96 | #define REFCLSID const IID & | ||
97 | |||
98 | __inline int InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2) | ||
99 | { | ||
100 | return ( | ||
101 | ((uint32_t *)&rguid1)[0] == ((uint32_t *)&rguid2)[0] && | ||
102 | ((uint32_t *)&rguid1)[1] == ((uint32_t *)&rguid2)[1] && | ||
103 | ((uint32_t *)&rguid1)[2] == ((uint32_t *)&rguid2)[2] && | ||
104 | ((uint32_t *)&rguid1)[3] == ((uint32_t *)&rguid2)[3]); | ||
105 | } | ||
106 | #else | ||
107 | #define REFGUID const GUID * | ||
108 | #define REFIID const IID * | ||
109 | #define REFCLSID const IID * | ||
110 | #endif | ||
111 | |||
112 | // SAL annotations | ||
113 | #define _In_ | ||
114 | #define _In_z_ | ||
115 | #define _In_opt_ | ||
116 | #define _In_opt_z_ | ||
117 | #define _In_reads_(x) | ||
118 | #define _In_reads_opt_(x) | ||
119 | #define _In_reads_bytes_(x) | ||
120 | #define _In_reads_bytes_opt_(x) | ||
121 | #define _In_range_(x, y) | ||
122 | #define _In_bytecount_(x) | ||
123 | #define _Out_ | ||
124 | #define _Out_opt_ | ||
125 | #define _Outptr_ | ||
126 | #define _Outptr_opt_result_z_ | ||
127 | #define _Outptr_opt_result_bytebuffer_(x) | ||
128 | #define _COM_Outptr_ | ||
129 | #define _COM_Outptr_result_maybenull_ | ||
130 | #define _COM_Outptr_opt_ | ||
131 | #define _COM_Outptr_opt_result_maybenull_ | ||
132 | #define _Out_writes_(x) | ||
133 | #define _Out_writes_z_(x) | ||
134 | #define _Out_writes_opt_(x) | ||
135 | #define _Out_writes_all_(x) | ||
136 | #define _Out_writes_all_opt_(x) | ||
137 | #define _Out_writes_to_opt_(x, y) | ||
138 | #define _Out_writes_bytes_(x) | ||
139 | #define _Out_writes_bytes_all_(x) | ||
140 | #define _Out_writes_bytes_all_opt_(x) | ||
141 | #define _Out_writes_bytes_opt_(x) | ||
142 | #define _Inout_ | ||
143 | #define _Inout_opt_ | ||
144 | #define _Inout_updates_(x) | ||
145 | #define _Inout_updates_bytes_(x) | ||
146 | #define _Field_size_(x) | ||
147 | #define _Field_size_opt_(x) | ||
148 | #define _Field_size_bytes_(x) | ||
149 | #define _Field_size_full_(x) | ||
150 | #define _Field_size_bytes_full_(x) | ||
151 | #define _Field_size_bytes_full_opt_(x) | ||
152 | #define _Field_size_bytes_part_(x, y) | ||
153 | #define _Field_range_(x, y) | ||
154 | #define _Field_z_ | ||
155 | #define _Check_return_ | ||
156 | #define _IRQL_requires_(x) | ||
157 | #define _IRQL_requires_min_(x) | ||
158 | #define _IRQL_requires_max_(x) | ||
159 | #define _At_(x, y) | ||
160 | #define _Always_(x) | ||
161 | #define _Return_type_success_(x) | ||
162 | #define _Translates_Win32_to_HRESULT_(x) | ||
163 | #define _Maybenull_ | ||
164 | #define _Outptr_result_maybenull_ | ||
165 | #define _Outptr_result_nullonfailure_ | ||
166 | #define _Analysis_assume_(x) | ||
167 | #define _Success_(x) | ||
168 | #define _In_count_(x) | ||
169 | #define _In_opt_count_(x) | ||
170 | #define _Use_decl_annotations_ | ||
171 | |||
172 | // Calling conventions | ||
173 | #define __cdecl | ||
174 | #define __stdcall | ||
175 | #define STDMETHODCALLTYPE | ||
176 | #define STDAPICALLTYPE | ||
177 | #define STDAPI extern "C" HRESULT STDAPICALLTYPE | ||
178 | #define WINAPI | ||
179 | #define STDMETHOD(name) virtual HRESULT name | ||
180 | #define STDMETHOD_(type,name) virtual type name | ||
181 | #define IFACEMETHOD(method) /*__override*/ STDMETHOD(method) | ||
182 | #define IFACEMETHOD_(type, method) /*__override*/ STDMETHOD_(type, method) | ||
183 | |||
184 | // Error codes | ||
185 | typedef LONG HRESULT; | ||
186 | #define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) | ||
187 | #define FAILED(hr) (((HRESULT)(hr)) < 0) | ||
188 | #define S_OK ((HRESULT)0L) | ||
189 | #define S_FALSE ((HRESULT)1L) | ||
190 | #define E_NOTIMPL ((HRESULT)0x80000001L) | ||
191 | #define E_OUTOFMEMORY ((HRESULT)0x80000002L) | ||
192 | #define E_INVALIDARG ((HRESULT)0x80000003L) | ||
193 | #define E_NOINTERFACE ((HRESULT)0x80000004L) | ||
194 | #define E_POINTER ((HRESULT)0x80000005L) | ||
195 | #define E_HANDLE ((HRESULT)0x80000006L) | ||
196 | #define E_ABORT ((HRESULT)0x80000007L) | ||
197 | #define E_FAIL ((HRESULT)0x80000008L) | ||
198 | #define E_ACCESSDENIED ((HRESULT)0x80000009L) | ||
199 | #define E_UNEXPECTED ((HRESULT)0x8000FFFFL) | ||
200 | #define DXGI_ERROR_DEVICE_HUNG ((HRESULT)0x887A0006L) | ||
201 | #define DXGI_ERROR_DEVICE_REMOVED ((HRESULT)0x887A0005L) | ||
202 | #define DXGI_ERROR_DEVICE_RESET ((HRESULT)0x887A0007L) | ||
203 | #define DXGI_ERROR_DRIVER_INTERNAL_ERROR ((HRESULT)0x887A0020L) | ||
204 | #define DXGI_ERROR_INVALID_CALL ((HRESULT)0x887A0001L) | ||
205 | |||
206 | typedef struct _LUID | ||
207 | { | ||
208 | ULONG LowPart; | ||
209 | LONG HighPart; | ||
210 | } LUID; | ||
211 | |||
212 | struct RECT | ||
213 | { | ||
214 | int left; | ||
215 | int top; | ||
216 | int right; | ||
217 | int bottom; | ||
218 | }; | ||
219 | |||
220 | typedef union _LARGE_INTEGER { | ||
221 | struct { | ||
222 | uint32_t LowPart; | ||
223 | uint32_t HighPart; | ||
224 | } u; | ||
225 | int64_t QuadPart; | ||
226 | } LARGE_INTEGER; | ||
227 | |||
228 | typedef union _ULARGE_INTEGER { | ||
229 | struct { | ||
230 | uint32_t LowPart; | ||
231 | uint32_t HighPart; | ||
232 | } u; | ||
233 | uint64_t QuadPart; | ||
234 | } ULARGE_INTEGER; | ||
235 | |||
236 | struct SECURITY_ATTRIBUTES; | ||
237 | struct STATSTG; | ||
238 | |||
239 | #ifdef __cplusplus | ||
240 | // ENUM_FLAG_OPERATORS | ||
241 | // Define operator overloads to enable bit operations on enum values that are | ||
242 | // used to define flags. Use DEFINE_ENUM_FLAG_OPERATORS(YOUR_TYPE) to enable these | ||
243 | // operators on YOUR_TYPE. | ||
244 | extern "C++" { | ||
245 | template <size_t S> | ||
246 | struct _ENUM_FLAG_INTEGER_FOR_SIZE; | ||
247 | |||
248 | template <> | ||
249 | struct _ENUM_FLAG_INTEGER_FOR_SIZE<1> | ||
250 | { | ||
251 | typedef int8_t type; | ||
252 | }; | ||
253 | |||
254 | template <> | ||
255 | struct _ENUM_FLAG_INTEGER_FOR_SIZE<2> | ||
256 | { | ||
257 | typedef int16_t type; | ||
258 | }; | ||
259 | |||
260 | template <> | ||
261 | struct _ENUM_FLAG_INTEGER_FOR_SIZE<4> | ||
262 | { | ||
263 | typedef int32_t type; | ||
264 | }; | ||
265 | |||
266 | template <> | ||
267 | struct _ENUM_FLAG_INTEGER_FOR_SIZE<8> | ||
268 | { | ||
269 | typedef int64_t type; | ||
270 | }; | ||
271 | |||
272 | // used as an approximation of std::underlying_type<T> | ||
273 | template <class T> | ||
274 | struct _ENUM_FLAG_SIZED_INTEGER | ||
275 | { | ||
276 | typedef typename _ENUM_FLAG_INTEGER_FOR_SIZE<sizeof(T)>::type type; | ||
277 | }; | ||
278 | |||
279 | } | ||
280 | #define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \ | ||
281 | extern "C++" { \ | ||
282 | inline constexpr ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) | ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
283 | inline ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) |= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
284 | inline constexpr ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) & ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
285 | inline ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) &= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
286 | inline constexpr ENUMTYPE operator ~ (ENUMTYPE a) { return ENUMTYPE(~((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a)); } \ | ||
287 | inline constexpr ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) ^ ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
288 | inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) ^= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \ | ||
289 | } | ||
290 | #endif | ||
291 | |||
292 | // D3DX12 uses these | ||
293 | #include <stdlib.h> | ||
294 | #define HeapAlloc(heap, flags, size) malloc(size) | ||
295 | #define HeapFree(heap, flags, ptr) free(ptr) | ||
296 | |||
297 | #ifdef __cplusplus | ||
298 | // IUnknown | ||
299 | |||
300 | interface DECLSPEC_UUID("00000000-0000-0000-C000-000000000046") DECLSPEC_NOVTABLE IUnknown | ||
301 | { | ||
302 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) = 0; | ||
303 | virtual ULONG STDMETHODCALLTYPE AddRef() = 0; | ||
304 | virtual ULONG STDMETHODCALLTYPE Release() = 0; | ||
305 | |||
306 | template <class Q> HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp) { | ||
307 | return QueryInterface(uuidof<Q>(), (void **)pp); | ||
308 | } | ||
309 | }; | ||
310 | |||
311 | template <> constexpr GUID uuidof<IUnknown>() | ||
312 | { | ||
313 | return { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; | ||
314 | } | ||
315 | |||
316 | extern "C++" | ||
317 | { | ||
318 | template<typename T> void** IID_PPV_ARGS_Helper(T** pp) | ||
319 | { | ||
320 | static_cast<IUnknown*>(*pp); | ||
321 | return reinterpret_cast<void**>(pp); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | #define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType) | ||
326 | #endif | ||
327 | |||
328 | #if defined(lint) | ||
329 | // Note: lint -e530 says don't complain about uninitialized variables for | ||
330 | // this variable. Error 527 has to do with unreachable code. | ||
331 | // -restore restores checking to the -save state | ||
332 | #define UNREFERENCED_PARAMETER(P) \ | ||
333 | /*lint -save -e527 -e530 */ \ | ||
334 | { \ | ||
335 | (P) = (P); \ | ||
336 | } \ | ||
337 | /*lint -restore */ | ||
338 | #else | ||
339 | #define UNREFERENCED_PARAMETER(P) (P) | ||
340 | #endif | ||
diff --git a/contrib/DirectX-Headers/include/wsl/wrladapter.h b/contrib/DirectX-Headers/include/wsl/wrladapter.h new file mode 100644 index 0000000..883ecab --- /dev/null +++ b/contrib/DirectX-Headers/include/wsl/wrladapter.h | |||
@@ -0,0 +1,801 @@ | |||
1 | // Copyright (c) Microsoft Corporation. | ||
2 | // Licensed under the MIT License. | ||
3 | |||
4 | #pragma once | ||
5 | |||
6 | #include "winadapter.h" | ||
7 | |||
8 | // defined by winadapter.h and needed by some windows headers, but conflicts | ||
9 | // with some libc++ implementation headers | ||
10 | #ifdef __in | ||
11 | #undef __in | ||
12 | #endif | ||
13 | #ifdef __out | ||
14 | #undef __out | ||
15 | #endif | ||
16 | |||
17 | #include <type_traits> | ||
18 | #include <atomic> | ||
19 | #include <memory> | ||
20 | #include <climits> | ||
21 | #include <cassert> | ||
22 | |||
23 | namespace Microsoft | ||
24 | { | ||
25 | namespace WRL | ||
26 | { | ||
27 | namespace Details | ||
28 | { | ||
29 | struct BoolStruct { int Member; }; | ||
30 | typedef int BoolStruct::* BoolType; | ||
31 | |||
32 | template <typename T> // T should be the ComPtr<T> or a derived type of it, not just the interface | ||
33 | class ComPtrRefBase | ||
34 | { | ||
35 | public: | ||
36 | typedef typename T::InterfaceType InterfaceType; | ||
37 | |||
38 | operator IUnknown**() const throw() | ||
39 | { | ||
40 | static_assert(__is_base_of(IUnknown, InterfaceType), "Invalid cast: InterfaceType does not derive from IUnknown"); | ||
41 | return reinterpret_cast<IUnknown**>(ptr_->ReleaseAndGetAddressOf()); | ||
42 | } | ||
43 | |||
44 | protected: | ||
45 | T* ptr_; | ||
46 | }; | ||
47 | |||
48 | template <typename T> | ||
49 | class ComPtrRef : public Details::ComPtrRefBase<T> // T should be the ComPtr<T> or a derived type of it, not just the interface | ||
50 | { | ||
51 | using Super = Details::ComPtrRefBase<T>; | ||
52 | using InterfaceType = typename Super::InterfaceType; | ||
53 | public: | ||
54 | ComPtrRef(_In_opt_ T* ptr) throw() | ||
55 | { | ||
56 | this->ptr_ = ptr; | ||
57 | } | ||
58 | |||
59 | // Conversion operators | ||
60 | operator void**() const throw() | ||
61 | { | ||
62 | return reinterpret_cast<void**>(this->ptr_->ReleaseAndGetAddressOf()); | ||
63 | } | ||
64 | |||
65 | // This is our operator ComPtr<U> (or the latest derived class from ComPtr (e.g. WeakRef)) | ||
66 | operator T*() throw() | ||
67 | { | ||
68 | *this->ptr_ = nullptr; | ||
69 | return this->ptr_; | ||
70 | } | ||
71 | |||
72 | // We define operator InterfaceType**() here instead of on ComPtrRefBase<T>, since | ||
73 | // if InterfaceType is IUnknown or IInspectable, having it on the base will collide. | ||
74 | operator InterfaceType**() throw() | ||
75 | { | ||
76 | return this->ptr_->ReleaseAndGetAddressOf(); | ||
77 | } | ||
78 | |||
79 | // This is used for IID_PPV_ARGS in order to do __uuidof(**(ppType)). | ||
80 | // It does not need to clear ptr_ at this point, it is done at IID_PPV_ARGS_Helper(ComPtrRef&) later in this file. | ||
81 | InterfaceType* operator *() throw() | ||
82 | { | ||
83 | return this->ptr_->Get(); | ||
84 | } | ||
85 | |||
86 | // Explicit functions | ||
87 | InterfaceType* const * GetAddressOf() const throw() | ||
88 | { | ||
89 | return this->ptr_->GetAddressOf(); | ||
90 | } | ||
91 | |||
92 | InterfaceType** ReleaseAndGetAddressOf() throw() | ||
93 | { | ||
94 | return this->ptr_->ReleaseAndGetAddressOf(); | ||
95 | } | ||
96 | }; | ||
97 | } | ||
98 | |||
99 | template <typename T> | ||
100 | class ComPtr | ||
101 | { | ||
102 | public: | ||
103 | typedef T InterfaceType; | ||
104 | |||
105 | protected: | ||
106 | InterfaceType *ptr_; | ||
107 | template<class U> friend class ComPtr; | ||
108 | |||
109 | void InternalAddRef() const throw() | ||
110 | { | ||
111 | if (ptr_ != nullptr) | ||
112 | { | ||
113 | ptr_->AddRef(); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | unsigned long InternalRelease() throw() | ||
118 | { | ||
119 | unsigned long ref = 0; | ||
120 | T* temp = ptr_; | ||
121 | |||
122 | if (temp != nullptr) | ||
123 | { | ||
124 | ptr_ = nullptr; | ||
125 | ref = temp->Release(); | ||
126 | } | ||
127 | |||
128 | return ref; | ||
129 | } | ||
130 | |||
131 | public: | ||
132 | ComPtr() throw() : ptr_(nullptr) | ||
133 | { | ||
134 | } | ||
135 | |||
136 | ComPtr(decltype(nullptr)) throw() : ptr_(nullptr) | ||
137 | { | ||
138 | } | ||
139 | |||
140 | template<class U> | ||
141 | ComPtr(_In_opt_ U *other) throw() : ptr_(other) | ||
142 | { | ||
143 | InternalAddRef(); | ||
144 | } | ||
145 | |||
146 | ComPtr(const ComPtr& other) throw() : ptr_(other.ptr_) | ||
147 | { | ||
148 | InternalAddRef(); | ||
149 | } | ||
150 | |||
151 | // copy constructor that allows to instantiate class when U* is convertible to T* | ||
152 | template<class U> | ||
153 | ComPtr(const ComPtr<U> &other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() : | ||
154 | ptr_(other.ptr_) | ||
155 | { | ||
156 | InternalAddRef(); | ||
157 | } | ||
158 | |||
159 | ComPtr(_Inout_ ComPtr &&other) throw() : ptr_(nullptr) | ||
160 | { | ||
161 | if (this != reinterpret_cast<ComPtr*>(&reinterpret_cast<unsigned char&>(other))) | ||
162 | { | ||
163 | Swap(other); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | // Move constructor that allows instantiation of a class when U* is convertible to T* | ||
168 | template<class U> | ||
169 | ComPtr(_Inout_ ComPtr<U>&& other, typename std::enable_if<std::is_convertible<U*, T*>::value, void *>::type * = 0) throw() : | ||
170 | ptr_(other.ptr_) | ||
171 | { | ||
172 | other.ptr_ = nullptr; | ||
173 | } | ||
174 | |||
175 | ~ComPtr() throw() | ||
176 | { | ||
177 | InternalRelease(); | ||
178 | } | ||
179 | |||
180 | ComPtr& operator=(decltype(nullptr)) throw() | ||
181 | { | ||
182 | InternalRelease(); | ||
183 | return *this; | ||
184 | } | ||
185 | |||
186 | ComPtr& operator=(_In_opt_ T *other) throw() | ||
187 | { | ||
188 | if (ptr_ != other) | ||
189 | { | ||
190 | ComPtr(other).Swap(*this); | ||
191 | } | ||
192 | return *this; | ||
193 | } | ||
194 | |||
195 | template <typename U> | ||
196 | ComPtr& operator=(_In_opt_ U *other) throw() | ||
197 | { | ||
198 | ComPtr(other).Swap(*this); | ||
199 | return *this; | ||
200 | } | ||
201 | |||
202 | ComPtr& operator=(const ComPtr &other) throw() | ||
203 | { | ||
204 | if (ptr_ != other.ptr_) | ||
205 | { | ||
206 | ComPtr(other).Swap(*this); | ||
207 | } | ||
208 | return *this; | ||
209 | } | ||
210 | |||
211 | template<class U> | ||
212 | ComPtr& operator=(const ComPtr<U>& other) throw() | ||
213 | { | ||
214 | ComPtr(other).Swap(*this); | ||
215 | return *this; | ||
216 | } | ||
217 | |||
218 | ComPtr& operator=(_Inout_ ComPtr &&other) throw() | ||
219 | { | ||
220 | ComPtr(static_cast<ComPtr&&>(other)).Swap(*this); | ||
221 | return *this; | ||
222 | } | ||
223 | |||
224 | template<class U> | ||
225 | ComPtr& operator=(_Inout_ ComPtr<U>&& other) throw() | ||
226 | { | ||
227 | ComPtr(static_cast<ComPtr<U>&&>(other)).Swap(*this); | ||
228 | return *this; | ||
229 | } | ||
230 | |||
231 | void Swap(_Inout_ ComPtr&& r) throw() | ||
232 | { | ||
233 | T* tmp = ptr_; | ||
234 | ptr_ = r.ptr_; | ||
235 | r.ptr_ = tmp; | ||
236 | } | ||
237 | |||
238 | void Swap(_Inout_ ComPtr& r) throw() | ||
239 | { | ||
240 | T* tmp = ptr_; | ||
241 | ptr_ = r.ptr_; | ||
242 | r.ptr_ = tmp; | ||
243 | } | ||
244 | |||
245 | operator Details::BoolType() const throw() | ||
246 | { | ||
247 | return Get() != nullptr ? &Details::BoolStruct::Member : nullptr; | ||
248 | } | ||
249 | |||
250 | T* Get() const throw() | ||
251 | { | ||
252 | return ptr_; | ||
253 | } | ||
254 | |||
255 | InterfaceType* operator->() const throw() | ||
256 | { | ||
257 | return ptr_; | ||
258 | } | ||
259 | |||
260 | Details::ComPtrRef<ComPtr<T>> operator&() throw() | ||
261 | { | ||
262 | return Details::ComPtrRef<ComPtr<T>>(this); | ||
263 | } | ||
264 | |||
265 | const Details::ComPtrRef<const ComPtr<T>> operator&() const throw() | ||
266 | { | ||
267 | return Details::ComPtrRef<const ComPtr<T>>(this); | ||
268 | } | ||
269 | |||
270 | T* const* GetAddressOf() const throw() | ||
271 | { | ||
272 | return &ptr_; | ||
273 | } | ||
274 | |||
275 | T** GetAddressOf() throw() | ||
276 | { | ||
277 | return &ptr_; | ||
278 | } | ||
279 | |||
280 | T** ReleaseAndGetAddressOf() throw() | ||
281 | { | ||
282 | InternalRelease(); | ||
283 | return &ptr_; | ||
284 | } | ||
285 | |||
286 | T* Detach() throw() | ||
287 | { | ||
288 | T* ptr = ptr_; | ||
289 | ptr_ = nullptr; | ||
290 | return ptr; | ||
291 | } | ||
292 | |||
293 | void Attach(_In_opt_ InterfaceType* other) throw() | ||
294 | { | ||
295 | if (ptr_ != nullptr) | ||
296 | { | ||
297 | auto ref = ptr_->Release(); | ||
298 | // DBG_UNREFERENCED_LOCAL_VARIABLE(ref); | ||
299 | // Attaching to the same object only works if duplicate references are being coalesced. Otherwise | ||
300 | // re-attaching will cause the pointer to be released and may cause a crash on a subsequent dereference. | ||
301 | assert(ref != 0 || ptr_ != other); | ||
302 | } | ||
303 | |||
304 | ptr_ = other; | ||
305 | } | ||
306 | |||
307 | unsigned long Reset() | ||
308 | { | ||
309 | return InternalRelease(); | ||
310 | } | ||
311 | |||
312 | // Previously, unsafe behavior could be triggered when 'this' is ComPtr<IInspectable> or ComPtr<IUnknown> and CopyTo is used to copy to another type U. | ||
313 | // The user will use operator& to convert the destination into a ComPtrRef, which can then implicit cast to IInspectable** and IUnknown**. | ||
314 | // If this overload of CopyTo is not present, it will implicitly cast to IInspectable or IUnknown and match CopyTo(InterfaceType**) instead. | ||
315 | // A valid polymoprhic downcast requires run-time type checking via QueryInterface, so CopyTo(InterfaceType**) will break type safety. | ||
316 | // This overload matches ComPtrRef before the implicit cast takes place, preventing the unsafe downcast. | ||
317 | template <typename U> | ||
318 | HRESULT CopyTo(Details::ComPtrRef<ComPtr<U>> ptr, typename std::enable_if< | ||
319 | (std::is_same<T, IUnknown>::value) | ||
320 | && !std::is_same<U*, T*>::value, void *>::type * = 0) const throw() | ||
321 | { | ||
322 | return ptr_->QueryInterface(uuidof<U>(), ptr); | ||
323 | } | ||
324 | |||
325 | HRESULT CopyTo(_Outptr_result_maybenull_ InterfaceType** ptr) const throw() | ||
326 | { | ||
327 | InternalAddRef(); | ||
328 | *ptr = ptr_; | ||
329 | return S_OK; | ||
330 | } | ||
331 | |||
332 | HRESULT CopyTo(REFIID riid, _Outptr_result_nullonfailure_ void** ptr) const throw() | ||
333 | { | ||
334 | return ptr_->QueryInterface(riid, ptr); | ||
335 | } | ||
336 | |||
337 | template<typename U> | ||
338 | HRESULT CopyTo(_Outptr_result_nullonfailure_ U** ptr) const throw() | ||
339 | { | ||
340 | return ptr_->QueryInterface(uuidof<U>(), reinterpret_cast<void**>(ptr)); | ||
341 | } | ||
342 | |||
343 | // query for U interface | ||
344 | template<typename U> | ||
345 | HRESULT As(_Inout_ Details::ComPtrRef<ComPtr<U>> p) const throw() | ||
346 | { | ||
347 | return ptr_->QueryInterface(uuidof<U>(), p); | ||
348 | } | ||
349 | |||
350 | // query for U interface | ||
351 | template<typename U> | ||
352 | HRESULT As(_Out_ ComPtr<U>* p) const throw() | ||
353 | { | ||
354 | return ptr_->QueryInterface(uuidof<U>(), reinterpret_cast<void**>(p->ReleaseAndGetAddressOf())); | ||
355 | } | ||
356 | |||
357 | // query for riid interface and return as IUnknown | ||
358 | HRESULT AsIID(REFIID riid, _Out_ ComPtr<IUnknown>* p) const throw() | ||
359 | { | ||
360 | return ptr_->QueryInterface(riid, reinterpret_cast<void**>(p->ReleaseAndGetAddressOf())); | ||
361 | } | ||
362 | |||
363 | }; // ComPtr | ||
364 | |||
365 | |||
366 | namespace Details | ||
367 | { | ||
368 | // Empty struct used as default template parameter | ||
369 | class Nil | ||
370 | { | ||
371 | }; | ||
372 | |||
373 | // Empty struct used for validating template parameter types in Implements | ||
374 | struct ImplementsBase | ||
375 | { | ||
376 | }; | ||
377 | |||
378 | class RuntimeClassBase | ||
379 | { | ||
380 | protected: | ||
381 | template<typename T> | ||
382 | static HRESULT AsIID(_In_ T* implements, REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) noexcept | ||
383 | { | ||
384 | *ppvObject = nullptr; | ||
385 | bool isRefDelegated = false; | ||
386 | // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. | ||
387 | if (InlineIsEqualGUID(riid, uuidof<IUnknown>())) | ||
388 | { | ||
389 | *ppvObject = implements->CastToUnknown(); | ||
390 | static_cast<IUnknown*>(*ppvObject)->AddRef(); | ||
391 | return S_OK; | ||
392 | } | ||
393 | |||
394 | HRESULT hr = implements->CanCastTo(riid, ppvObject, &isRefDelegated); | ||
395 | if (SUCCEEDED(hr) && !isRefDelegated) | ||
396 | { | ||
397 | static_cast<IUnknown*>(*ppvObject)->AddRef(); | ||
398 | } | ||
399 | |||
400 | #ifdef _MSC_VER | ||
401 | #pragma warning(push) | ||
402 | #pragma warning(disable: 6102) // '*ppvObject' is used but may not be initialized | ||
403 | #endif | ||
404 | _Analysis_assume_(SUCCEEDED(hr) || (*ppvObject == nullptr)); | ||
405 | #ifdef _MSC_VER | ||
406 | #pragma warning(pop) | ||
407 | #endif | ||
408 | return hr; | ||
409 | } | ||
410 | |||
411 | public: | ||
412 | HRESULT RuntimeClassInitialize() noexcept | ||
413 | { | ||
414 | return S_OK; | ||
415 | } | ||
416 | }; | ||
417 | |||
418 | // Interface traits provides casting and filling iids methods helpers | ||
419 | template<typename I0> | ||
420 | struct InterfaceTraits | ||
421 | { | ||
422 | typedef I0 Base; | ||
423 | |||
424 | template<typename T> | ||
425 | static Base* CastToBase(_In_ T* ptr) noexcept | ||
426 | { | ||
427 | return static_cast<Base*>(ptr); | ||
428 | } | ||
429 | |||
430 | template<typename T> | ||
431 | static IUnknown* CastToUnknown(_In_ T* ptr) noexcept | ||
432 | { | ||
433 | return static_cast<IUnknown*>(static_cast<Base*>(ptr)); | ||
434 | } | ||
435 | |||
436 | template <typename T> | ||
437 | _Success_(return == true) | ||
438 | static bool CanCastTo(_In_ T* ptr, REFIID riid, _Outptr_ void **ppv) noexcept | ||
439 | { | ||
440 | // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. | ||
441 | if (InlineIsEqualGUID(riid, uuidof<Base>())) | ||
442 | { | ||
443 | *ppv = static_cast<Base*>(ptr); | ||
444 | return true; | ||
445 | } | ||
446 | |||
447 | return false; | ||
448 | } | ||
449 | }; | ||
450 | |||
451 | // Specialization for Nil parameter | ||
452 | template<> | ||
453 | struct InterfaceTraits<Nil> | ||
454 | { | ||
455 | typedef Nil Base; | ||
456 | |||
457 | template <typename T> | ||
458 | _Success_(return == true) | ||
459 | static bool CanCastTo(_In_ T*, REFIID, _Outptr_ void **) noexcept | ||
460 | { | ||
461 | return false; | ||
462 | } | ||
463 | }; | ||
464 | |||
465 | // ChainInterfaces - template allows specifying a derived COM interface along with its class hierarchy to allow QI for the base interfaces | ||
466 | template <typename I0, typename I1, typename I2 = Nil, typename I3 = Nil, | ||
467 | typename I4 = Nil, typename I5 = Nil, typename I6 = Nil, | ||
468 | typename I7 = Nil, typename I8 = Nil, typename I9 = Nil> | ||
469 | struct ChainInterfaces : I0 | ||
470 | { | ||
471 | protected: | ||
472 | HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) throw() | ||
473 | { | ||
474 | typename InterfaceTraits<I0>::Base* ptr = InterfaceTraits<I0>::CastToBase(this); | ||
475 | |||
476 | return (InterfaceTraits<I0>::CanCastTo(this, riid, ppv) || | ||
477 | InterfaceTraits<I1>::CanCastTo(ptr, riid, ppv) || | ||
478 | InterfaceTraits<I2>::CanCastTo(ptr, riid, ppv) || | ||
479 | InterfaceTraits<I3>::CanCastTo(ptr, riid, ppv) || | ||
480 | InterfaceTraits<I4>::CanCastTo(ptr, riid, ppv) || | ||
481 | InterfaceTraits<I5>::CanCastTo(ptr, riid, ppv) || | ||
482 | InterfaceTraits<I6>::CanCastTo(ptr, riid, ppv) || | ||
483 | InterfaceTraits<I7>::CanCastTo(ptr, riid, ppv) || | ||
484 | InterfaceTraits<I8>::CanCastTo(ptr, riid, ppv) || | ||
485 | InterfaceTraits<I9>::CanCastTo(ptr, riid, ppv)) ? S_OK : E_NOINTERFACE; | ||
486 | } | ||
487 | |||
488 | IUnknown* CastToUnknown() throw() | ||
489 | { | ||
490 | return InterfaceTraits<I0>::CastToUnknown(this); | ||
491 | } | ||
492 | }; | ||
493 | |||
494 | // Helper template used by Implements. This template traverses a list of interfaces and adds them as base class and information | ||
495 | // to enable QI. | ||
496 | template <typename ...TInterfaces> | ||
497 | struct ImplementsHelper; | ||
498 | |||
499 | template <typename T> | ||
500 | struct ImplementsMarker | ||
501 | {}; | ||
502 | |||
503 | template <typename I0, bool isImplements> | ||
504 | struct MarkImplements; | ||
505 | |||
506 | template <typename I0> | ||
507 | struct MarkImplements<I0, false> | ||
508 | { | ||
509 | typedef I0 Type; | ||
510 | }; | ||
511 | |||
512 | template <typename I0> | ||
513 | struct MarkImplements<I0, true> | ||
514 | { | ||
515 | typedef ImplementsMarker<I0> Type; | ||
516 | }; | ||
517 | |||
518 | // AdjustImplements pre-processes the type list for more efficient builds. | ||
519 | template <typename ...Bases> | ||
520 | struct AdjustImplements; | ||
521 | |||
522 | template <typename I0, typename ...Bases> | ||
523 | struct AdjustImplements<I0, Bases...> | ||
524 | { | ||
525 | typedef ImplementsHelper<typename MarkImplements<I0, std::is_base_of<ImplementsBase, I0>::value>::Type, Bases...> Type; | ||
526 | }; | ||
527 | |||
528 | // Use AdjustImplements to remove instances of "Nil" from the type list. | ||
529 | template <typename ...Bases> | ||
530 | struct AdjustImplements<Nil, Bases...> | ||
531 | { | ||
532 | typedef typename AdjustImplements<Bases...>::Type Type; | ||
533 | }; | ||
534 | |||
535 | template <> | ||
536 | struct AdjustImplements<> | ||
537 | { | ||
538 | typedef ImplementsHelper<> Type; | ||
539 | }; | ||
540 | |||
541 | // Specialization handles unadorned interfaces | ||
542 | template <typename I0, typename ...TInterfaces> | ||
543 | struct ImplementsHelper<I0, TInterfaces...> : | ||
544 | I0, | ||
545 | AdjustImplements<TInterfaces...>::Type | ||
546 | { | ||
547 | template <typename ...> friend struct ImplementsHelper; | ||
548 | friend class RuntimeClassBase; | ||
549 | |||
550 | protected: | ||
551 | |||
552 | HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept | ||
553 | { | ||
554 | // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. | ||
555 | if (InlineIsEqualGUID(riid, uuidof<I0>())) | ||
556 | { | ||
557 | *ppv = reinterpret_cast<I0*>(reinterpret_cast<void*>(this)); | ||
558 | return S_OK; | ||
559 | } | ||
560 | return AdjustImplements<TInterfaces...>::Type::CanCastTo(riid, ppv, pRefDelegated); | ||
561 | } | ||
562 | |||
563 | IUnknown* CastToUnknown() noexcept | ||
564 | { | ||
565 | return reinterpret_cast<I0*>(reinterpret_cast<void*>(this)); | ||
566 | } | ||
567 | }; | ||
568 | |||
569 | |||
570 | // Selector is used to "tag" base interfaces to be used in casting, since a runtime class may indirectly derive from | ||
571 | // the same interface or Implements<> template multiple times | ||
572 | template <typename base, typename disciminator> | ||
573 | struct Selector : public base | ||
574 | { | ||
575 | }; | ||
576 | |||
577 | // Specialization handles types that derive from ImplementsHelper (e.g. nested Implements). | ||
578 | template <typename I0, typename ...TInterfaces> | ||
579 | struct ImplementsHelper<ImplementsMarker<I0>, TInterfaces...> : | ||
580 | Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>>, | ||
581 | Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> | ||
582 | { | ||
583 | template <typename ...> friend struct ImplementsHelper; | ||
584 | friend class RuntimeClassBase; | ||
585 | |||
586 | protected: | ||
587 | typedef Selector<I0, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> CurrentType; | ||
588 | typedef Selector<typename AdjustImplements<TInterfaces...>::Type, ImplementsHelper<ImplementsMarker<I0>, TInterfaces...>> BaseType; | ||
589 | |||
590 | HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept | ||
591 | { | ||
592 | HRESULT hr = CurrentType::CanCastTo(riid, ppv); | ||
593 | if (hr == E_NOINTERFACE) | ||
594 | { | ||
595 | hr = BaseType::CanCastTo(riid, ppv, pRefDelegated); | ||
596 | } | ||
597 | return hr; | ||
598 | } | ||
599 | |||
600 | IUnknown* CastToUnknown() noexcept | ||
601 | { | ||
602 | // First in list wins. | ||
603 | return CurrentType::CastToUnknown(); | ||
604 | } | ||
605 | }; | ||
606 | |||
607 | // terminal case specialization. | ||
608 | template <> | ||
609 | struct ImplementsHelper<> | ||
610 | { | ||
611 | template <typename ...> friend struct ImplementsHelper; | ||
612 | friend class RuntimeClassBase; | ||
613 | |||
614 | protected: | ||
615 | HRESULT CanCastTo(_In_ REFIID /*riid*/, _Outptr_ void ** /*ppv*/, bool * /*pRefDelegated*/ = nullptr) noexcept | ||
616 | { | ||
617 | return E_NOINTERFACE; | ||
618 | } | ||
619 | |||
620 | // IUnknown* CastToUnknown() noexcept; // not defined for terminal case. | ||
621 | }; | ||
622 | |||
623 | // Specialization handles chaining interfaces | ||
624 | template <typename C0, typename C1, typename C2, typename C3, typename C4, typename C5, typename C6, typename C7, typename C8, typename C9, typename ...TInterfaces> | ||
625 | struct ImplementsHelper<ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, TInterfaces...> : | ||
626 | ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>, | ||
627 | AdjustImplements<TInterfaces...>::Type | ||
628 | { | ||
629 | template <typename ...> friend struct ImplementsHelper; | ||
630 | friend class RuntimeClassBase; | ||
631 | |||
632 | protected: | ||
633 | typedef typename AdjustImplements<TInterfaces...>::Type BaseType; | ||
634 | |||
635 | HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv, bool *pRefDelegated = nullptr) noexcept | ||
636 | { | ||
637 | HRESULT hr = ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CanCastTo(riid, ppv); | ||
638 | if (FAILED(hr)) | ||
639 | { | ||
640 | hr = BaseType::CanCastTo(riid, ppv, pRefDelegated); | ||
641 | } | ||
642 | |||
643 | return hr; | ||
644 | } | ||
645 | |||
646 | IUnknown* CastToUnknown() noexcept | ||
647 | { | ||
648 | return ChainInterfaces<C0, C1, C2, C3, C4, C5, C6, C7, C8, C9>::CastToUnknown(); | ||
649 | } | ||
650 | }; | ||
651 | |||
652 | // Implements - template implementing QI using the information provided through its template parameters | ||
653 | // Each template parameter has to be one of the following: | ||
654 | // * COM Interface | ||
655 | // * A class that implements one or more COM interfaces | ||
656 | // * ChainInterfaces template | ||
657 | template <typename I0, typename ...TInterfaces> | ||
658 | struct Implements : | ||
659 | AdjustImplements<I0, TInterfaces...>::Type, | ||
660 | ImplementsBase | ||
661 | { | ||
662 | public: | ||
663 | typedef I0 FirstInterface; | ||
664 | protected: | ||
665 | typedef typename AdjustImplements<I0, TInterfaces...>::Type BaseType; | ||
666 | template <typename ...> friend struct ImplementsHelper; | ||
667 | friend class RuntimeClassBase; | ||
668 | |||
669 | HRESULT CanCastTo(REFIID riid, _Outptr_ void **ppv) noexcept | ||
670 | { | ||
671 | return BaseType::CanCastTo(riid, ppv); | ||
672 | } | ||
673 | |||
674 | IUnknown* CastToUnknown() noexcept | ||
675 | { | ||
676 | return BaseType::CastToUnknown(); | ||
677 | } | ||
678 | }; | ||
679 | |||
680 | // Used on RuntimeClass to protect it from being constructed with new | ||
681 | class DontUseNewUseMake | ||
682 | { | ||
683 | private: | ||
684 | void* operator new(size_t) noexcept | ||
685 | { | ||
686 | assert(false); | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | public: | ||
691 | void* operator new(size_t, _In_ void* placement) noexcept | ||
692 | { | ||
693 | return placement; | ||
694 | } | ||
695 | }; | ||
696 | |||
697 | template <typename ...TInterfaces> | ||
698 | class RuntimeClassImpl : | ||
699 | public AdjustImplements<TInterfaces...>::Type, | ||
700 | public RuntimeClassBase, | ||
701 | public DontUseNewUseMake | ||
702 | { | ||
703 | public: | ||
704 | STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) | ||
705 | { | ||
706 | return Super::AsIID(this, riid, ppvObject); | ||
707 | } | ||
708 | |||
709 | STDMETHOD_(ULONG, AddRef)() | ||
710 | { | ||
711 | return InternalAddRef(); | ||
712 | } | ||
713 | |||
714 | STDMETHOD_(ULONG, Release)() | ||
715 | { | ||
716 | ULONG ref = InternalRelease(); | ||
717 | if (ref == 0) | ||
718 | { | ||
719 | delete this; | ||
720 | } | ||
721 | |||
722 | return ref; | ||
723 | } | ||
724 | |||
725 | protected: | ||
726 | using Super = RuntimeClassBase; | ||
727 | static const LONG c_lProtectDestruction = -(LONG_MAX / 2); | ||
728 | |||
729 | RuntimeClassImpl() noexcept = default; | ||
730 | |||
731 | virtual ~RuntimeClassImpl() noexcept | ||
732 | { | ||
733 | // Set refcount_ to -(LONG_MAX/2) to protect destruction and | ||
734 | // also catch mismatched Release in debug builds | ||
735 | refcount_ = static_cast<ULONG>(c_lProtectDestruction); | ||
736 | } | ||
737 | |||
738 | ULONG InternalAddRef() noexcept | ||
739 | { | ||
740 | return ++refcount_; | ||
741 | } | ||
742 | |||
743 | ULONG InternalRelease() noexcept | ||
744 | { | ||
745 | return --refcount_; | ||
746 | } | ||
747 | |||
748 | unsigned long GetRefCount() const noexcept | ||
749 | { | ||
750 | return refcount_; | ||
751 | } | ||
752 | |||
753 | std::atomic<ULONG> refcount_{1}; | ||
754 | }; | ||
755 | } | ||
756 | |||
757 | template <typename ...TInterfaces> | ||
758 | class Base : public Details::RuntimeClassImpl<TInterfaces...> | ||
759 | { | ||
760 | Base(const Base&) = delete; | ||
761 | Base& operator=(const Base&) = delete; | ||
762 | |||
763 | protected: | ||
764 | HRESULT CustomQueryInterface(REFIID /*riid*/, _Outptr_result_nullonfailure_ void** /*ppvObject*/, _Out_ bool *handled) | ||
765 | { | ||
766 | *handled = false; | ||
767 | return S_OK; | ||
768 | } | ||
769 | |||
770 | public: | ||
771 | Base() throw() = default; | ||
772 | typedef Base RuntimeClassT; | ||
773 | }; | ||
774 | |||
775 | // Creates a Nano-COM object wrapped in a smart pointer. | ||
776 | template <typename T, typename ...TArgs> | ||
777 | ComPtr<T> Make(TArgs&&... args) | ||
778 | { | ||
779 | ComPtr<T> object; | ||
780 | |||
781 | std::unique_ptr<unsigned char[]> buffer(new unsigned char[sizeof(T)]); | ||
782 | if (buffer) | ||
783 | { | ||
784 | T* ptr = new (buffer.get())T(std::forward<TArgs>(args)...); | ||
785 | object.Attach(ptr); | ||
786 | buffer.release(); | ||
787 | } | ||
788 | |||
789 | return object; | ||
790 | } | ||
791 | |||
792 | using Details::ChainInterfaces; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | // Overloaded global function to provide to IID_PPV_ARGS that support Details::ComPtrRef | ||
797 | template<typename T> | ||
798 | void** IID_PPV_ARGS_Helper(Microsoft::WRL::Details::ComPtrRef<T> pp) throw() | ||
799 | { | ||
800 | return pp; | ||
801 | } \ No newline at end of file | ||