[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / vm / synchronizationcontextnative.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*============================================================
6 **
7 ** Implementation: SynchronizationContextNative.cpp
8 **
9 **
10 ** Purpose: Native methods on System.Threading.SynchronizationContext.
11 **
12 **
13 ===========================================================*/
14
15 #include "common.h"
16
17 #ifdef FEATURE_APPX
18 #include <roapi.h>
19 #include <windows.ui.core.h>
20 #include "winrtdispatcherqueue.h"
21 #include "synchronizationcontextnative.h"
22     
23 Volatile<ABI::Windows::UI::Core::ICoreWindowStatic*> g_pICoreWindowStatic;
24
25 void* QCALLTYPE SynchronizationContextNative::GetWinRTDispatcherForCurrentThread()
26 {
27     QCALL_CONTRACT;
28     void* result = NULL;
29     BEGIN_QCALL;
30
31     _ASSERTE(WinRTSupported());
32
33     //
34     // Get access to ICoreWindow's statics.  We grab just one ICoreWindowStatic for the whole process.
35     //
36     ABI::Windows::UI::Core::ICoreWindowStatic* pICoreWindowStatic = g_pICoreWindowStatic;
37     if (pICoreWindowStatic == NULL)
38     {
39         SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindowStatic> pNewICoreWindowStatic;
40         {
41             HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_UI_Core_CoreWindow, (ABI::Windows::UI::Core::ICoreWindowStatic**)pNewICoreWindowStatic.GetAddr());
42
43             //
44             // Older Windows builds don't support ICoreWindowStatic.  We should just return a null CoreDispatcher 
45             // in that case, rather than throwing.
46             //
47             if (hr != E_NOTIMPL)
48                 IfFailThrow(hr);
49         }
50
51         if (pNewICoreWindowStatic != NULL)
52         {
53             ABI::Windows::UI::Core::ICoreWindowStatic* old = InterlockedCompareExchangeT<ABI::Windows::UI::Core::ICoreWindowStatic*>(&g_pICoreWindowStatic, pNewICoreWindowStatic, NULL);
54             if (old == NULL)
55             {
56                 pNewICoreWindowStatic.SuppressRelease();
57                 pICoreWindowStatic = pNewICoreWindowStatic;
58             }
59             else
60             {
61                 pICoreWindowStatic = old;
62             }
63         }
64     }
65
66
67     if (pICoreWindowStatic != NULL)
68     {
69         //
70         // Get the current ICoreWindow
71         //
72         SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindow> pCoreWindow;
73
74         //
75         // workaround: we're currently ignoring the HRESULT from get_Current, because Windows is returning errors for threads that have no CoreWindow.
76         // A better behavior would be to return S_OK, with a NULL CoreWindow.  If/when Windows does the right thing here, we can change this
77         // back to checking the HRESULT.
78         //
79         pICoreWindowStatic->GetForCurrentThread(&pCoreWindow);
80
81         if (pCoreWindow != NULL)
82         {
83             //
84             // Get the ICoreDispatcher for this window
85             //
86             SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreDispatcher> pCoreDispatcher;
87             IfFailThrow(pCoreWindow->get_Dispatcher(&pCoreDispatcher));
88
89             if (pCoreDispatcher != NULL)
90             {
91                 //
92                 // Does the dispatcher belong to the current thread?
93                 //
94                 boolean hasThreadAccess = FALSE;
95                 IfFailThrow(pCoreDispatcher->get_HasThreadAccess(&hasThreadAccess));
96                 if (hasThreadAccess)
97                 {
98                     //
99                     // This is the dispatcher for the current thread.  Return it.
100                     //
101                     pCoreDispatcher.SuppressRelease();
102                     result = (void*)pCoreDispatcher;
103                 }
104             }
105         }
106     }
107
108     // If we didn't find a CoreDispatcher for the thread, let's see if we can get a DispatcherQueue.
109     if (result == NULL)
110     {
111         SafeComHolderPreemp<Windows::System::IDispatcherQueueStatics> pDispatcherQueueStatics;
112         {
113             HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_System_DispatcherQueue,
114                                                          (Windows::System::IDispatcherQueueStatics**)pDispatcherQueueStatics.GetAddr());
115
116             // This interface was added in RS3 along with the public DispatcherQueue support. Older
117             // Windows builds don't support it and will return one of two HRESULTs from the call
118             // to GetActivationFactory above:
119             //    - Pre-RS2 will return REGDB_E_CLASSNOTREG since Windows.System.DispatcherQueue
120             //      does not exist at all.
121             //    - RS2 will return E_NOINTERFACE since Windows.System.DispatcherQueue does exist
122             //      in a limited fashion, but does not support the interface ID that we want.
123             //
124             // We should just return null if we see these two HRESULTs rather than throwing.
125             if (hr != REGDB_E_CLASSNOTREG && hr != E_NOINTERFACE)
126             {
127                 IfFailThrow(hr);
128             }
129         }
130
131         if (pDispatcherQueueStatics != NULL)
132         {
133             //
134             // Get the current IDispatcherQueue
135             //
136             SafeComHolderPreemp<Windows::System::IDispatcherQueue> pDispatcherQueue;
137
138             pDispatcherQueueStatics->GetForCurrentThread(&pDispatcherQueue);
139
140             if (pDispatcherQueue != NULL)
141             {
142                 pDispatcherQueue.SuppressRelease();
143                 result = (void*)pDispatcherQueue;
144             }
145         }
146     }
147
148     END_QCALL;
149     return result;
150 }
151
152 void SynchronizationContextNative::Cleanup()
153 {
154     CONTRACTL
155     {
156         NOTHROW;
157         GC_TRIGGERS;
158         MODE_ANY;
159     } CONTRACTL_END;
160     
161     if (g_pICoreWindowStatic)
162     {
163         SafeRelease(g_pICoreWindowStatic);
164         g_pICoreWindowStatic = NULL;
165     }
166 }
167
168
169
170 #endif //FEATURE_APPX