Skip to content

Commit

Permalink
wpf: delay-load UIAutomationCore because it's incomplete in RS1 (#15614)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
DHowett authored Jun 27, 2023
1 parent 58e1380 commit 99c18ce
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 2 deletions.
3 changes: 3 additions & 0 deletions .github/actions/spelling/allow/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Dacl
dataobject
dcomp
DERR
delayimp
dlldata
DNE
DONTADDTORECENT
Expand Down Expand Up @@ -167,6 +168,7 @@ roundf
RSHIFT
SACL
schandle
SEH
semver
serializer
SETVERSION
Expand Down Expand Up @@ -214,6 +216,7 @@ UOI
UPDATEINIFILE
userenv
USEROBJECTFLAGS
Vcpp
Viewbox
virtualalloc
vsnwprintf
Expand Down
32 changes: 31 additions & 1 deletion src/cascadia/PublicTerminalCore/HwndTerminalAutomationPeer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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:
Expand Down Expand Up @@ -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) };
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,7 @@ class HwndTerminalAutomationPeer :
void NotifyNewOutput(std::wstring_view newOutput) override;
#pragma endregion
private:
void _tryNotify(BSTR string, BSTR activity);
std::deque<wchar_t> _keyEvents;
bool _notificationsUnavailable{};
};
3 changes: 2 additions & 1 deletion src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>

0 comments on commit 99c18ce

Please sign in to comment.