1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) Microsoft Corporation 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// All rights reserved. 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Modified for native C++ WRL support by Gregory Morse 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Code in Details namespace is for internal usage within the library code 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifndef _PLATFORM_AGILE_H_ 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define _PLATFORM_AGILE_H_ 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifdef _MSC_VER 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#pragma once 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif // _MSC_VER 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <algorithm> 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <wrl\client.h> 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertemplate <typename T, bool TIsNotAgile> class Agile; 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertemplate <typename T> 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct UnwrapAgile 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static const bool _IsAgile = false; 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertemplate <typename T> 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct UnwrapAgile<Agile<T, false>> 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static const bool _IsAgile = true; 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertemplate <typename T> 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstruct UnwrapAgile<Agile<T, true>> 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static const bool _IsAgile = true; 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define IS_AGILE(T) UnwrapAgile<T>::_IsAgile 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define __is_winrt_agile(T) (std::is_same<T, HSTRING__>::value || std::is_base_of<Microsoft::WRL::FtmBase, T>::value || std::is_base_of<IAgileObject, T>::value) //derived from Microsoft::WRL::FtmBase or IAgileObject 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define __is_win_interface(T) (std::is_base_of<IUnknown, T>::value || std::is_base_of<IInspectable, T>::value) //derived from IUnknown or IInspectable 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define __is_win_class(T) (std::is_same<T, HSTRING__>::value || std::is_base_of<Microsoft::WRL::Details::RuntimeClassBase, T>::value) //derived from Microsoft::WRL::RuntimeClass or HSTRING 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler namespace Details 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler IUnknown* __stdcall GetObjectContext(); 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HRESULT __stdcall GetProxyImpl(IUnknown*, REFIID, IUnknown*, IUnknown**); 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HRESULT __stdcall ReleaseInContextImpl(IUnknown*, IUnknown*); 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __declspec(no_refcount) inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy) 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return GetProxyImpl(*reinterpret_cast<IUnknown**>(&ObjectIn), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy)); 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return GetProxyImpl(*reinterpret_cast<IUnknown**>(&const_cast<T*>(ObjectIn)), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy)); 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inline HRESULT ReleaseInContext(T *ObjectIn, IUnknown *ContextCallBack) 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return ReleaseInContextImpl(ObjectIn, ContextCallBack); 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler class AgileHelper 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_IUnknown* _p; 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool _release; 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileHelper(__abi_IUnknown* p, bool release = true) : _p(p), _release(release) 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileHelper(AgileHelper&& other) : _p(other._p), _release(other._release) 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _other._p = nullptr; 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _other._release = true; 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileHelper operator=(AgileHelper&& other) 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _p = other._p; 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _release = other._release; 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _other._p = nullptr; 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _other._release = true; 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~AgileHelper() 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_release && _p) 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _p->__abi_Release(); 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __declspec(no_refcount) __declspec(no_release_return) 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler T* operator->() 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return reinterpret_cast<T*>(_p); 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __declspec(no_refcount) __declspec(no_release_return) 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler operator T * () 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return reinterpret_cast<T*>(_p); 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler private: 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileHelper(const AgileHelper&); 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileHelper operator=(const AgileHelper&); 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct __remove_hat 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typedef T type; 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct __remove_hat<T*> 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typedef T type; 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct AgileTypeHelper 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typename typedef __remove_hat<T>::type type; 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typename typedef __remove_hat<T>::type* agileMemberType; 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } // namespace Details 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#pragma warning(push) 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#pragma warning(disable: 4451) // Usage of ref class inside this context can lead to invalid marshaling of object across contexts 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template < 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typename T, 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool TIsNotAgile = (__is_win_class(typename Details::AgileTypeHelper<T>::type) && !__is_winrt_agile(typename Details::AgileTypeHelper<T>::type)) || 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __is_win_interface(typename Details::AgileTypeHelper<T>::type) 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler > 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler class Agile 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_assert(__is_win_class(typename Details::AgileTypeHelper<T>::type) || __is_win_interface(typename Details::AgileTypeHelper<T>::type), "Agile can only be used with ref class or interface class types"); 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typename typedef Details::AgileTypeHelper<T>::agileMemberType TypeT; 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT _object; 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IUnknown> _contextCallback; 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ULONG_PTR _contextToken; 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler enum class AgileState 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler NonAgilePointer = 0, 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgilePointer = 1, 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Unknown = 2 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler AgileState _agileState; 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void CaptureContext() 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _contextCallback = Details::GetObjectContext(); 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_ThrowIfFailed(CoGetContextToken(&_contextToken)); 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void SetObject(TypeT object) 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Capture context before setting the pointer 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // If context capture fails then nothing to cleanup 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (object != nullptr) 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile; 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HRESULT hr = reinterpret_cast<IUnknown*>(object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Don't Capture context if object is agile 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (hr != S_OK) 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _agileState = AgileState::NonAgilePointer; 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CaptureContext(); 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _agileState = AgileState::AgilePointer; 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _object = object; 192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile() throw() : _object(nullptr), _contextToken(0) 196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler , _agileState(AgileState::Unknown) 198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(nullptr_t) throw() : _object(nullptr), _contextToken(0) 203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler , _agileState(AgileState::Unknown) 205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler explicit Agile(TypeT object) throw() : _object(nullptr), _contextToken(0) 210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler , _agileState(AgileState::Unknown) 212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Assumes that the source object is from the current context 215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SetObject(object); 216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(const Agile& object) throw() : _object(nullptr), _contextToken(0) 219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler , _agileState(AgileState::Unknown) 221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Get returns pointer valid for current context 224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SetObject(object.Get()); 225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(Agile&& object) throw() : _object(nullptr), _contextToken(0) 228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler , _agileState(AgileState::Unknown) 230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Assumes that the source object is from the current context 233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Swap(object); 234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~Agile() throw() 237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT Get() const 242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Agile object, no proxy required 244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_agileState == AgileState::AgilePointer || _object == nullptr) 246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_contextToken == 0 || _contextCallback == nullptr || _object == nullptr) 248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object; 251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Do the check for same context 254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ULONG_PTR currentContextToken; 255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); 256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (currentContextToken == _contextToken) 257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object; 259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Different context and holding on to a non agile object 263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Do the costly work of getting a proxy 264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT localObject; 265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); 266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_agileState == AgileState::Unknown) 268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Object is agile if it implements IAgileObject 270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // GetAddressOf captures the context with out knowing the type of object that it will hold 271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_object != nullptr) 272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Object is agile if it implements IAgileObject 276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // GetAddressOf captures the context with out knowing the type of object that it will hold 277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile; 278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HRESULT hr = reinterpret_cast<IUnknown*>(localObject)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); 279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile; 281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HRESULT hr = reinterpret_cast<IUnknown*>(_object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile); 282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (hr == S_OK) 284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler auto pThis = const_cast<Agile*>(this); 286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pThis->_agileState = AgileState::AgilePointer; 288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pThis->_contextToken = 0; 290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pThis->_contextCallback = nullptr; 291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object; 292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler auto pThis = const_cast<Agile*>(this); 297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pThis->_agileState = AgileState::NonAgilePointer; 298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER < 1800 303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Different context and holding on to a non agile object 304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Do the costly work of getting a proxy 305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT localObject; 306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject)); 307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return localObject; 309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT* GetAddressOf() throw() 312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CaptureContext(); 315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return &_object; 316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT* GetAddressOfForInOut() throw() 319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler CaptureContext(); 321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return &_object; 322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT operator->() const throw() 325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return Get(); 327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(nullptr_t) throw() 330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(TypeT object) throw() 336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(object).Swap(*this); 338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(Agile object) throw() 342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // parameter is by copy which gets pointer valid for current context 344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler object.Swap(*this); 345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER < 1800 349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(IUnknown* lp) throw() 350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // bump ref count 352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IUnknown> spObject(lp); 353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // put it into Platform Object 355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Platform::Object object; 356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *(IUnknown**)(&object) = spObject.Detach(); 357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SetObject(object); 359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void Swap(Agile& object) 364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(_object, object._object); 366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(_contextCallback, object._contextCallback); 367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(_contextToken, object._contextToken); 368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(_agileState, object._agileState); 370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Release the interface and set to NULL 374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void Release() throw() 375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_object) 377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Cast to IInspectable (no QI) 379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler IUnknown* pObject = *(IUnknown**)(&_object); 380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Set * to null without release 381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *(IUnknown**)(&_object) = nullptr; 382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ULONG_PTR currentContextToken; 384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken)); 385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_contextToken == 0 || _contextCallback == nullptr || _contextToken == currentContextToken) 386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pObject->Release(); 388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Details::ReleaseInContext(pObject, _contextCallback.Get()); 392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _contextCallback = nullptr; 394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _contextToken = 0; 395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER >= 1800 396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _agileState = AgileState::Unknown; 397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator==(nullptr_t) const throw() 402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object == nullptr; 404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator==(const Agile& other) const throw() 407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object == other._object && _contextToken == other._contextToken; 409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator<(const Agile& other) const throw() 412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (reinterpret_cast<void*>(_object) < reinterpret_cast<void*>(other._object)) 414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return true; 416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object == other._object && _contextToken < other._contextToken; 419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template <typename T> 423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler class Agile<T, false> 424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler static_assert(__is_win_class(typename Details::AgileTypeHelper<T>::type) || __is_win_interface(typename Details::AgileTypeHelper<T>::type), "Agile can only be used with ref class or interface class types"); 426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler typename typedef Details::AgileTypeHelper<T>::agileMemberType TypeT; 427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT _object; 428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile() throw() : _object(nullptr) 431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(nullptr_t) throw() : _object(nullptr) 435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler explicit Agile(TypeT object) throw() : _object(object) 439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(const Agile& object) throw() : _object(object._object) 443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile(Agile&& object) throw() : _object(nullptr) 447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Swap(object); 449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ~Agile() throw() 452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT Get() const 457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object; 459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT* GetAddressOf() throw() 462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return &_object; 465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT* GetAddressOfForInOut() throw() 468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return &_object; 470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler TypeT operator->() const throw() 473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return Get(); 475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(nullptr_t) throw() 478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(TypeT object) throw() 484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (_object != object) 486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _object = object; 488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(Agile object) throw() 493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler object.Swap(*this); 495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if _MSC_VER < 1800 499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Agile& operator=(IUnknown* lp) throw() 500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Release(); 502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // bump ref count 503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ::Microsoft::WRL::ComPtr<IUnknown> spObject(lp); 504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // put it into Platform Object 506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Platform::Object object; 507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *(IUnknown**)(&object) = spObject.Detach(); 508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _object = object; 510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return *this; 511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler // Release the interface and set to NULL 515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void Release() throw() 516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler _object = nullptr; 518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void Swap(Agile& object) 521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler std::swap(_object, object._object); 523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator==(nullptr_t) const throw() 526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object == nullptr; 528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator==(const Agile& other) const throw() 531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return _object == other._object; 533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator<(const Agile& other) const throw() 536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return reinterpret_cast<void*>(_object) < reinterpret_cast<void*>(other._object); 538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler }; 540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#pragma warning(pop) 542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template<class U> 544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator==(nullptr_t, const Agile<U>& a) throw() 545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return a == nullptr; 547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template<class U> 550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator!=(const Agile<U>& a, nullptr_t) throw() 551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return !(a == nullptr); 553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template<class U> 556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator!=(nullptr_t, const Agile<U>& a) throw() 557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return !(a == nullptr); 559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler template<class U> 562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler bool operator!=(const Agile<U>& a, const Agile<U>& b) throw() 563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler { 564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler return !(a == b); 565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif // _PLATFORM_AGILE_H_ 569