This source file includes following definitions.
- __is_win_class
 
- throw
 
- throw
 
- throw
 
- throw
 
#ifndef _PLATFORM_AGILE_H_
#define _PLATFORM_AGILE_H_
#ifdef _MSC_VER
#pragma once
#endif  
#include <algorithm>
#include <wrl\client.h>
template <typename T, bool TIsNotAgile> class Agile;
template <typename T>
struct UnwrapAgile
{
    static const bool _IsAgile = false;
};
template <typename T>
struct UnwrapAgile<Agile<T, false>>
{
    static const bool _IsAgile = true;
};
template <typename T>
struct UnwrapAgile<Agile<T, true>>
{
    static const bool _IsAgile = true;
};
#define IS_AGILE(T) UnwrapAgile<T>::_IsAgile
#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) 
#define __is_win_interface(T) (std::is_base_of<IUnknown, T>::value || std::is_base_of<IInspectable, T>::value) 
#define __is_win_class(T) (std::is_same<T, HSTRING__>::value || std::is_base_of<Microsoft::WRL::Details::RuntimeClassBase, T>::value) 
    namespace Details
    {
        IUnknown* __stdcall GetObjectContext();
        HRESULT __stdcall GetProxyImpl(IUnknown*, REFIID, IUnknown*, IUnknown**);
        HRESULT __stdcall ReleaseInContextImpl(IUnknown*, IUnknown*);
        template <typename T>
#if _MSC_VER >= 1800
        __declspec(no_refcount) inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy)
#else
        inline HRESULT GetProxy(T *ObjectIn, IUnknown *ContextCallBack, T **Proxy)
#endif
        {
#if _MSC_VER >= 1800
            return GetProxyImpl(*reinterpret_cast<IUnknown**>(&ObjectIn), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy));
#else
            return GetProxyImpl(*reinterpret_cast<IUnknown**>(&const_cast<T*>(ObjectIn)), __uuidof(T*), ContextCallBack, reinterpret_cast<IUnknown**>(Proxy));
#endif
        }
        template <typename T>
        inline HRESULT ReleaseInContext(T *ObjectIn, IUnknown *ContextCallBack)
        {
            return ReleaseInContextImpl(ObjectIn, ContextCallBack);
        }
        template <typename T>
        class AgileHelper
        {
            __abi_IUnknown* _p;
            bool _release;
        public:
            AgileHelper(__abi_IUnknown* p, bool release = true) : _p(p), _release(release)
            {
            }
            AgileHelper(AgileHelper&& other) : _p(other._p), _release(other._release)
            {
                _other._p = nullptr;
                _other._release = true;
            }
            AgileHelper operator=(AgileHelper&& other)
            {
                _p = other._p;
                _release = other._release;
                _other._p = nullptr;
                _other._release = true;
                return *this;
            }
            ~AgileHelper()
            {
                if (_release && _p)
                {
                    _p->__abi_Release();
                }
            }
            __declspec(no_refcount) __declspec(no_release_return)
                T* operator->()
            {
                    return reinterpret_cast<T*>(_p);
            }
            __declspec(no_refcount) __declspec(no_release_return)
                operator T * ()
            {
                    return reinterpret_cast<T*>(_p);
            }
        private:
            AgileHelper(const AgileHelper&);
            AgileHelper operator=(const AgileHelper&);
        };
        template <typename T>
        struct __remove_hat
        {
            typedef T type;
        };
        template <typename T>
        struct __remove_hat<T*>
        {
            typedef T type;
        };
        template <typename T>
        struct AgileTypeHelper
        {
            typename typedef __remove_hat<T>::type type;
            typename typedef __remove_hat<T>::type* agileMemberType;
        };
    } 
#pragma warning(push)
#pragma warning(disable: 4451) 
    template <
        typename T,
        bool TIsNotAgile = (__is_win_class(typename Details::AgileTypeHelper<T>::type) && !__is_winrt_agile(typename Details::AgileTypeHelper<T>::type)) ||
        __is_win_interface(typename Details::AgileTypeHelper<T>::type)
    >
    class Agile
    {
        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");
        typename typedef Details::AgileTypeHelper<T>::agileMemberType TypeT;
        TypeT _object;
        ::Microsoft::WRL::ComPtr<IUnknown> _contextCallback;
        ULONG_PTR _contextToken;
#if _MSC_VER >= 1800
        enum class AgileState
        {
            NonAgilePointer = 0,
            AgilePointer = 1,
            Unknown = 2
        };
        AgileState _agileState;
#endif
        void CaptureContext()
        {
            _contextCallback = Details::GetObjectContext();
            __abi_ThrowIfFailed(CoGetContextToken(&_contextToken));
        }
        void SetObject(TypeT object)
        {
            
            
            Release();
            if (object != nullptr)
            {
                ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile;
                HRESULT hr = reinterpret_cast<IUnknown*>(object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile);
                
                if (hr != S_OK)
                {
#if _MSC_VER >= 1800
                    _agileState = AgileState::NonAgilePointer;
#endif
                    CaptureContext();
                }
#if _MSC_VER >= 1800
                else
                {
                    _agileState = AgileState::AgilePointer;
                }
#endif
            }
            _object = object;
        }
    public:
        Agile() throw() : _object(nullptr), _contextToken(0)
#if _MSC_VER >= 1800
            , _agileState(AgileState::Unknown)
#endif
        {
        }
        Agile(nullptr_t) throw() : _object(nullptr), _contextToken(0)
#if _MSC_VER >= 1800
            , _agileState(AgileState::Unknown)
#endif
        {
        }
        explicit Agile(TypeT object) throw() : _object(nullptr), _contextToken(0)
#if _MSC_VER >= 1800
            , _agileState(AgileState::Unknown)
#endif
        {
            
            SetObject(object);
        }
        Agile(const Agile& object) throw() : _object(nullptr), _contextToken(0)
#if _MSC_VER >= 1800
            , _agileState(AgileState::Unknown)
#endif
        {
            
            SetObject(object.Get());
        }
        Agile(Agile&& object) throw() : _object(nullptr), _contextToken(0)
#if _MSC_VER >= 1800
            , _agileState(AgileState::Unknown)
#endif
        {
            
            Swap(object);
        }
        ~Agile() throw()
        {
            Release();
        }
        TypeT Get() const
        {
            
#if _MSC_VER >= 1800
            if (_agileState == AgileState::AgilePointer || _object == nullptr)
#else
            if (_contextToken == 0 || _contextCallback == nullptr || _object == nullptr)
#endif
            {
                return _object;
            }
            
            ULONG_PTR currentContextToken;
            __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken));
            if (currentContextToken == _contextToken)
            {
                return _object;
            }
#if _MSC_VER >= 1800
            
            
            TypeT localObject;
            __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject));
            if (_agileState == AgileState::Unknown)
#else
            
            
            if (_object != nullptr)
#endif
            {
#if _MSC_VER >= 1800
                
                
                ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile;
                HRESULT hr = reinterpret_cast<IUnknown*>(localObject)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile);
#else
                ::Microsoft::WRL::ComPtr<IAgileObject> checkIfAgile;
                HRESULT hr = reinterpret_cast<IUnknown*>(_object)->QueryInterface(__uuidof(IAgileObject), &checkIfAgile);
#endif
                if (hr == S_OK)
                {
                    auto pThis = const_cast<Agile*>(this);
#if _MSC_VER >= 1800
                    pThis->_agileState = AgileState::AgilePointer;
#endif
                    pThis->_contextToken = 0;
                    pThis->_contextCallback = nullptr;
                    return _object;
                }
#if _MSC_VER >= 1800
                else
                {
                    auto pThis = const_cast<Agile*>(this);
                    pThis->_agileState = AgileState::NonAgilePointer;
                }
#endif
            }
#if _MSC_VER < 1800
            
            
            TypeT localObject;
            __abi_ThrowIfFailed(Details::GetProxy(_object, _contextCallback.Get(), &localObject));
#endif
            return localObject;
        }
        TypeT* GetAddressOf() throw()
        {
            Release();
            CaptureContext();
            return &_object;
        }
        TypeT* GetAddressOfForInOut() throw()
        {
            CaptureContext();
            return &_object;
        }
        TypeT operator->() const throw()
        {
            return Get();
        }
        Agile& operator=(nullptr_t) throw()
        {
            Release();
            return *this;
        }
        Agile& operator=(TypeT object) throw()
        {
            Agile(object).Swap(*this);
            return *this;
        }
        Agile& operator=(Agile object) throw()
        {
            
            object.Swap(*this);
            return *this;
        }
#if _MSC_VER < 1800
        Agile& operator=(IUnknown* lp) throw()
        {
            
            ::Microsoft::WRL::ComPtr<IUnknown> spObject(lp);
            
            Platform::Object object;
            *(IUnknown**)(&object) = spObject.Detach();
            SetObject(object);
            return *this;
        }
#endif
        void Swap(Agile& object)
        {
            std::swap(_object, object._object);
            std::swap(_contextCallback, object._contextCallback);
            std::swap(_contextToken, object._contextToken);
#if _MSC_VER >= 1800
            std::swap(_agileState, object._agileState);
#endif
        }
        
        void Release() throw()
        {
            if (_object)
            {
                
                IUnknown* pObject = *(IUnknown**)(&_object);
                
                *(IUnknown**)(&_object) = nullptr;
                ULONG_PTR currentContextToken;
                __abi_ThrowIfFailed(CoGetContextToken(¤tContextToken));
                if (_contextToken == 0 || _contextCallback == nullptr || _contextToken == currentContextToken)
                {
                    pObject->Release();
                }
                else
                {
                    Details::ReleaseInContext(pObject, _contextCallback.Get());
                }
                _contextCallback = nullptr;
                _contextToken = 0;
#if _MSC_VER >= 1800
                _agileState = AgileState::Unknown;
#endif
            }
        }
        bool operator==(nullptr_t) const throw()
        {
            return _object == nullptr;
        }
        bool operator==(const Agile& other) const throw()
        {
            return _object == other._object && _contextToken == other._contextToken;
        }
        bool operator<(const Agile& other) const throw()
        {
            if (reinterpret_cast<void*>(_object) < reinterpret_cast<void*>(other._object))
            {
                return true;
            }
            return _object == other._object && _contextToken < other._contextToken;
        }
    };
    template <typename T>
    class Agile<T, false>
    {
        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");
        typename typedef Details::AgileTypeHelper<T>::agileMemberType TypeT;
        TypeT _object;
    public:
        Agile() throw() : _object(nullptr)
        {
        }
        Agile(nullptr_t) throw() : _object(nullptr)
        {
        }
        explicit Agile(TypeT object) throw() : _object(object)
        {
        }
        Agile(const Agile& object) throw() : _object(object._object)
        {
        }
        Agile(Agile&& object) throw() : _object(nullptr)
        {
            Swap(object);
        }
        ~Agile() throw()
        {
            Release();
        }
        TypeT Get() const
        {
            return _object;
        }
        TypeT* GetAddressOf() throw()
        {
            Release();
            return &_object;
        }
        TypeT* GetAddressOfForInOut() throw()
        {
            return &_object;
        }
        TypeT operator->() const throw()
        {
            return Get();
        }
        Agile& operator=(nullptr_t) throw()
        {
            Release();
            return *this;
        }
        Agile& operator=(TypeT object) throw()
        {
            if (_object != object)
            {
                _object = object;
            }
            return *this;
        }
        Agile& operator=(Agile object) throw()
        {
            object.Swap(*this);
            return *this;
        }
#if _MSC_VER < 1800
        Agile& operator=(IUnknown* lp) throw()
        {
            Release();
            
            ::Microsoft::WRL::ComPtr<IUnknown> spObject(lp);
            
            Platform::Object object;
            *(IUnknown**)(&object) = spObject.Detach();
            _object = object;
            return *this;
        }
#endif
        
        void Release() throw()
        {
            _object = nullptr;
        }
        void Swap(Agile& object)
        {
            std::swap(_object, object._object);
        }
        bool operator==(nullptr_t) const throw()
        {
            return _object == nullptr;
        }
        bool operator==(const Agile& other) const throw()
        {
            return _object == other._object;
        }
        bool operator<(const Agile& other) const throw()
        {
            return reinterpret_cast<void*>(_object) < reinterpret_cast<void*>(other._object);
        }
    };
#pragma warning(pop)
    template<class U>
    bool operator==(nullptr_t, const Agile<U>& a) throw()
    {
        return a == nullptr;
    }
    template<class U>
    bool operator!=(const Agile<U>& a, nullptr_t) throw()
    {
        return !(a == nullptr);
    }
    template<class U>
    bool operator!=(nullptr_t, const Agile<U>& a) throw()
    {
        return !(a == nullptr);
    }
    template<class U>
    bool operator!=(const Agile<U>& a, const Agile<U>& b) throw()
    {
        return !(a == b);
    }
#endif