wpf: delay-load UIAutomationCore because it's incomplete in RS1 (#15614)

UiaRaiseNotificationEvent is not present on Windows Server 2016, even
though it is documented as being present.
This also removes the cost of loading up UIAutomationCore from the
critical path.
This commit is contained in:
Dustin L. Howett 2023-06-27 16:42:20 -05:00 committed by GitHub
parent 58e1380b8f
commit 99c18ce57e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 2 deletions

View File

@ -29,6 +29,7 @@ Dacl
dataobject
dcomp
DERR
delayimp
dlldata
DNE
DONTADDTORECENT
@ -167,6 +168,7 @@ roundf
RSHIFT
SACL
schandle
SEH
semver
serializer
SETVERSION
@ -214,6 +216,7 @@ UOI
UPDATEINIFILE
userenv
USEROBJECTFLAGS
Vcpp
Viewbox
virtualalloc
vsnwprintf

View File

@ -5,6 +5,7 @@
#include "HwndTerminalAutomationPeer.hpp"
#include "../../types/UiaTracing.h"
#include <UIAutomationCoreApi.h>
#include <delayimp.h>
#pragma warning(suppress : 4471) // We don't control UIAutomationClient
#include <UIAutomationClient.h>
@ -13,6 +14,15 @@ using namespace Microsoft::Console::Types;
static constexpr wchar_t UNICODE_NEWLINE{ L'\n' };
static int CheckDelayedProcException(int exception) noexcept
{
if (exception == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND))
{
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
// Method Description:
// - creates a copy of the provided text with all of the control characters removed
// Arguments:
@ -123,6 +133,12 @@ void HwndTerminalAutomationPeer::SignalCursorChanged()
void HwndTerminalAutomationPeer::NotifyNewOutput(std::wstring_view newOutput)
{
if (_notificationsUnavailable) [[unlikely]]
{
// What if you tried to notify, but God said no
return;
}
// Try to suppress any events (or event data)
// that is just the keypress the user made
auto sanitized{ Sanitize(newOutput) };
@ -155,5 +171,19 @@ void HwndTerminalAutomationPeer::NotifyNewOutput(std::wstring_view newOutput)
const auto sanitizedBstr = wil::make_bstr_nothrow(sanitized.c_str());
static auto activityId = wil::make_bstr_nothrow(L"TerminalTextOutput");
LOG_IF_FAILED(UiaRaiseNotificationEvent(this, NotificationKind_ActionCompleted, NotificationProcessing_All, sanitizedBstr.get(), activityId.get()));
_tryNotify(sanitizedBstr.get(), activityId.get());
}
// This needs to be a separate function because it is using SEH try/except, which
// is incompatible with C++ unwinding
void HwndTerminalAutomationPeer::_tryNotify(BSTR string, BSTR activity)
{
__try
{
LOG_IF_FAILED(UiaRaiseNotificationEvent(this, NotificationKind_ActionCompleted, NotificationProcessing_All, string, activity));
}
__except (CheckDelayedProcException(GetExceptionCode()))
{
_notificationsUnavailable = true;
}
}

View File

@ -38,5 +38,7 @@ public:
void NotifyNewOutput(std::wstring_view newOutput) override;
#pragma endregion
private:
void _tryNotify(BSTR string, BSTR activity);
std::deque<wchar_t> _keyEvents;
bool _notificationsUnavailable{};
};

View File

@ -57,7 +57,8 @@
instead of APISet forwarders for easier Windows 7 compatibility. -->
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>delayimp.lib;Uiautomationcore.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>uiautomationcore.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
</Project>