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(&currentContextToken));
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(&currentContextToken));
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