diff options
Diffstat (limited to 'src/vm')
-rw-r--r-- | src/vm/synchronizationcontextnative.cpp | 41 | ||||
-rw-r--r-- | src/vm/winrtdispatcherqueue.h | 103 |
2 files changed, 144 insertions, 0 deletions
diff --git a/src/vm/synchronizationcontextnative.cpp b/src/vm/synchronizationcontextnative.cpp index ac67f39349..03b289fc95 100644 --- a/src/vm/synchronizationcontextnative.cpp +++ b/src/vm/synchronizationcontextnative.cpp @@ -17,6 +17,7 @@ #ifdef FEATURE_APPX #include <roapi.h> #include <windows.ui.core.h> +#include "winrtdispatcherqueue.h" #endif #include "synchronizationcontextnative.h" @@ -133,6 +134,46 @@ void* QCALLTYPE SynchronizationContextNative::GetWinRTDispatcherForCurrentThread } } + // If we didn't find a CoreDispatcher for the thread, let's see if we can get a DispatcherQueue. + if (result == NULL) + { + SafeComHolderPreemp<Windows::System::IDispatcherQueueStatics> pDispatcherQueueStatics; + { + HRESULT hr = clr::winrt::GetActivationFactory(RuntimeClass_Windows_System_DispatcherQueue, + (Windows::System::IDispatcherQueueStatics**)pDispatcherQueueStatics.GetAddr()); + + // This interface was added in RS3 along with the public DispatcherQueue support. Older + // Windows builds don't support it and will return one of two HRESULTs from the call + // to GetActivationFactory above: + // - Pre-RS2 will return REGDB_E_CLASSNOTREG since Windows.System.DispatcherQueue + // does not exist at all. + // - RS2 will return E_NOINTERFACE since Windows.System.DispatcherQueue does exist + // in a limited fashion, but does not support the interface ID that we want. + // + // We should just return null if we see these two HRESULTs rather than throwing. + if (hr != REGDB_E_CLASSNOTREG && hr != E_NOINTERFACE) + { + IfFailThrow(hr); + } + } + + if (pDispatcherQueueStatics != NULL) + { + // + // Get the current IDispatcherQueue + // + SafeComHolderPreemp<Windows::System::IDispatcherQueue> pDispatcherQueue; + + pDispatcherQueueStatics->GetForCurrentThread(&pDispatcherQueue); + + if (pDispatcherQueue != NULL) + { + pDispatcherQueue.SuppressRelease(); + result = (void*)pDispatcherQueue; + } + } + } + END_QCALL; return result; } diff --git a/src/vm/winrtdispatcherqueue.h b/src/vm/winrtdispatcherqueue.h new file mode 100644 index 0000000000..14f261da2b --- /dev/null +++ b/src/vm/winrtdispatcherqueue.h @@ -0,0 +1,103 @@ +// ==++== +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// ==--== +/*============================================================ +** +** Header: winrtdispatcherqueue.h +** +===========================================================*/ + +#ifndef _WINRTDISPATCHERQUEUE_H +#define _WINRTDISPATCHERQUEUE_H + +#include <inspectable.h> + +// The following definitions were taken from windows.system.h. +// Use windows.system.h from the RS3 SDK instead of this when that SDK is available. +namespace Windows { + namespace System { + /* [v1_enum] */ + enum DispatcherQueuePriority + { + DispatcherQueuePriority_Low = -10, + DispatcherQueuePriority_Normal = 0, + DispatcherQueuePriority_High = 10 + } ; + + MIDL_INTERFACE("DFA2DC9C-1A2D-4917-98F2-939AF1D6E0C8") + IDispatcherQueueHandler : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Invoke( void) = 0; + }; + + MIDL_INTERFACE("5FEABB1D-A31C-4727-B1AC-37454649D56A") + IDispatcherQueueTimer : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Interval( + /* [out][retval] */ __RPC__out ABI::Windows::Foundation::TimeSpan *value) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_Interval( + /* [in] */ ABI::Windows::Foundation::TimeSpan value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsStarted( + /* [out][retval] */ __RPC__out boolean *value) = 0; + + virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_IsRepeating( + /* [out][retval] */ __RPC__out boolean *value) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_IsRepeating( + /* [in] */ boolean value) = 0; + +#if 0 // We don't use these functions + virtual HRESULT STDMETHODCALLTYPE add_Tick( + /* [in] */ __RPC__in_opt __FITypedEventHandler_2_Windows__CSystem__CDispatcherQueueTimer_IInspectable *handler, + /* [out][retval] */ __RPC__out EventRegistrationToken *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE remove_Tick( + /* [in] */ EventRegistrationToken token) = 0; +#endif + }; + + MIDL_INTERFACE("603E88E4-A338-4FFE-A457-A5CFB9CEB899") + IDispatcherQueue : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateTimer( + /* [out][retval] */ __RPC__deref_out_opt Windows::System::IDispatcherQueueTimer **result) = 0; + + virtual HRESULT STDMETHODCALLTYPE TryEnqueue( + /* [in] */ __RPC__in_opt Windows::System::IDispatcherQueueHandler *callback, + /* [out][retval] */ __RPC__out boolean *result) = 0; + + virtual HRESULT STDMETHODCALLTYPE TryEnqueueWithPriority( + /* [in] */ Windows::System::DispatcherQueuePriority priority, + /* [in] */ __RPC__in_opt Windows::System::IDispatcherQueueHandler *callback, + /* [out][retval] */ __RPC__out boolean *result) = 0; + }; + + MIDL_INTERFACE("A96D83D7-9371-4517-9245-D0824AC12C74") + IDispatcherQueueStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE GetForCurrentThread( + /* [out][retval] */ __RPC__deref_out_opt Windows::System::IDispatcherQueue **result) = 0; + }; + + extern const __declspec(selectany) IID & IID_IDispatcherQueueStatics = __uuidof(IDispatcherQueueStatics); + } +} + +#ifndef RUNTIMECLASS_Windows_System_DispatcherQueue_DEFINED +#define RUNTIMECLASS_Windows_System_DispatcherQueue_DEFINED + extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_System_DispatcherQueue[] = L"Windows.System.DispatcherQueue"; +#endif + +#endif // _WINRTDISPATCHERQUEUE_H |