aboutsummaryrefslogtreecommitdiff
path: root/contrib/DirectX-Headers/include/wsl
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/DirectX-Headers/include/wsl')
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/OAIdl.h5
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/OCIdl.h5
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/rpc.h5
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/rpcndr.h6
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/winapifamily.h6
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/wrl/client.h6
-rw-r--r--contrib/DirectX-Headers/include/wsl/stubs/wrl/implements.h6
-rw-r--r--contrib/DirectX-Headers/include/wsl/winadapter.h340
-rw-r--r--contrib/DirectX-Headers/include/wsl/wrladapter.h801
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'
19typedef uint8_t UINT8;
20typedef int8_t INT8;
21typedef uint16_t UINT16;
22typedef int16_t INT16;
23typedef uint32_t UINT32, UINT, ULONG, DWORD, BOOL;
24typedef int32_t INT32, INT, LONG;
25typedef uint64_t UINT64, ULONG_PTR;
26typedef int64_t INT64, LONG_PTR;
27typedef void VOID, *HANDLE, *RPC_IF_HANDLE, *LPVOID;
28typedef const void *LPCVOID;
29typedef size_t SIZE_T;
30typedef float FLOAT;
31typedef double DOUBLE;
32typedef unsigned char BYTE;
33typedef 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.
39typedef char CHAR, *PSTR, *LPSTR, TCHAR, *PTSTR;
40typedef const char *LPCSTR, *PCSTR, *LPCTSTR, *PCTSTR;
41typedef wchar_t WCHAR, *PWSTR, *LPWSTR, *PWCHAR;
42typedef 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
63typedef 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
77template <typename T> GUID uuidof() = delete;
78template <typename T> GUID uuidof(T*) { return uuidof<T>(); }
79template <typename T> GUID uuidof(T**) { return uuidof<T>(); }
80template <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
90typedef GUID IID;
91typedef GUID UUID;
92typedef 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
185typedef 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
206typedef struct _LUID
207{
208 ULONG LowPart;
209 LONG HighPart;
210} LUID;
211
212struct RECT
213{
214 int left;
215 int top;
216 int right;
217 int bottom;
218};
219
220typedef union _LARGE_INTEGER {
221 struct {
222 uint32_t LowPart;
223 uint32_t HighPart;
224 } u;
225 int64_t QuadPart;
226} LARGE_INTEGER;
227
228typedef union _ULARGE_INTEGER {
229 struct {
230 uint32_t LowPart;
231 uint32_t HighPart;
232 } u;
233 uint64_t QuadPart;
234} ULARGE_INTEGER;
235
236struct SECURITY_ATTRIBUTES;
237struct 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.
244extern "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) \
281extern "C++" { \
282inline constexpr ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) | ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
283inline ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) |= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
284inline constexpr ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) & ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
285inline ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) &= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
286inline constexpr ENUMTYPE operator ~ (ENUMTYPE a) { return ENUMTYPE(~((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a)); } \
287inline constexpr ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) ^ ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
288inline 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
300interface 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
311template <> constexpr GUID uuidof<IUnknown>()
312{
313 return { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
314}
315
316extern "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
23namespace Microsoft
24{
25namespace 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
797template<typename T>
798void** IID_PPV_ARGS_Helper(Microsoft::WRL::Details::ComPtrRef<T> pp) throw()
799{
800 return pp;
801} \ No newline at end of file