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.
5 /*============================================================
7 ** Implementation: SynchronizationContextNative.cpp
10 ** Purpose: Native methods on System.Threading.SynchronizationContext.
13 ===========================================================*/
19 #include <windows.ui.core.h>
20 #include "winrtdispatcherqueue.h"
21 #include "synchronizationcontextnative.h"
23 Volatile<ABI::Windows::UI::Core::ICoreWindowStatic*> g_pICoreWindowStatic;
25 void* QCALLTYPE SynchronizationContextNative::GetWinRTDispatcherForCurrentThread()
31 _ASSERTE(WinRTSupported());
34 // Get access to ICoreWindow's statics. We grab just one ICoreWindowStatic for the whole process.
36 ABI::Windows::UI::Core::ICoreWindowStatic* pICoreWindowStatic = g_pICoreWindowStatic;
37 if (pICoreWindowStatic == NULL)
39 SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindowStatic> pNewICoreWindowStatic;
41 HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_UI_Core_CoreWindow, (ABI::Windows::UI::Core::ICoreWindowStatic**)pNewICoreWindowStatic.GetAddr());
44 // Older Windows builds don't support ICoreWindowStatic. We should just return a null CoreDispatcher
45 // in that case, rather than throwing.
51 if (pNewICoreWindowStatic != NULL)
53 ABI::Windows::UI::Core::ICoreWindowStatic* old = InterlockedCompareExchangeT<ABI::Windows::UI::Core::ICoreWindowStatic*>(&g_pICoreWindowStatic, pNewICoreWindowStatic, NULL);
56 pNewICoreWindowStatic.SuppressRelease();
57 pICoreWindowStatic = pNewICoreWindowStatic;
61 pICoreWindowStatic = old;
67 if (pICoreWindowStatic != NULL)
70 // Get the current ICoreWindow
72 SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreWindow> pCoreWindow;
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.
79 pICoreWindowStatic->GetForCurrentThread(&pCoreWindow);
81 if (pCoreWindow != NULL)
84 // Get the ICoreDispatcher for this window
86 SafeComHolderPreemp<ABI::Windows::UI::Core::ICoreDispatcher> pCoreDispatcher;
87 IfFailThrow(pCoreWindow->get_Dispatcher(&pCoreDispatcher));
89 if (pCoreDispatcher != NULL)
92 // Does the dispatcher belong to the current thread?
94 boolean hasThreadAccess = FALSE;
95 IfFailThrow(pCoreDispatcher->get_HasThreadAccess(&hasThreadAccess));
99 // This is the dispatcher for the current thread. Return it.
101 pCoreDispatcher.SuppressRelease();
102 result = (void*)pCoreDispatcher;
108 // If we didn't find a CoreDispatcher for the thread, let's see if we can get a DispatcherQueue.
111 SafeComHolderPreemp<Windows::System::IDispatcherQueueStatics> pDispatcherQueueStatics;
113 HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_System_DispatcherQueue,
114 (Windows::System::IDispatcherQueueStatics**)pDispatcherQueueStatics.GetAddr());
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.
124 // We should just return null if we see these two HRESULTs rather than throwing.
125 if (hr != REGDB_E_CLASSNOTREG && hr != E_NOINTERFACE)
131 if (pDispatcherQueueStatics != NULL)
134 // Get the current IDispatcherQueue
136 SafeComHolderPreemp<Windows::System::IDispatcherQueue> pDispatcherQueue;
138 pDispatcherQueueStatics->GetForCurrentThread(&pDispatcherQueue);
140 if (pDispatcherQueue != NULL)
142 pDispatcherQueue.SuppressRelease();
143 result = (void*)pDispatcherQueue;
152 void SynchronizationContextNative::Cleanup()
161 if (g_pICoreWindowStatic)
163 SafeRelease(g_pICoreWindowStatic);
164 g_pICoreWindowStatic = NULL;
170 #endif //FEATURE_APPX