diff --git a/OpenConsole.sln b/OpenConsole.sln
index 60c2f7682..843d866cc 100644
--- a/OpenConsole.sln
+++ b/OpenConsole.sln
@@ -397,6 +397,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Control", "src\ca
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", "src\cascadia\WindowsTerminal_UIATests\WindowsTerminal.UIA.Tests.csproj", "{F19DACD5-0C6E-40DC-B6E4-767A3200542C}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
AuditMode|Any CPU = AuditMode|Any CPU
@@ -3292,6 +3294,50 @@ Global
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x64.Build.0 = Release|x64
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.ActiveCfg = Release|Win32
{F19DACD5-0C6E-40DC-B6E4-767A3200542C}.Release|x86.Build.0 = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.ActiveCfg = AuditMode|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x64.Build.0 = AuditMode|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.ActiveCfg = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.AuditMode|x86.Build.0 = AuditMode|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM.ActiveCfg = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|ARM64.Build.0 = Debug|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.ActiveCfg = Debug|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x64Test.Build.0 = Debug|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|DotNet_x86Test.Build.0 = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.ActiveCfg = Debug|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x64.Build.0 = Debug|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.ActiveCfg = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Debug|x86.Build.0 = Debug|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x64.Build.0 = Fuzzing|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Fuzzing|x86.Build.0 = Fuzzing|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|Any CPU.ActiveCfg = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM.ActiveCfg = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.ActiveCfg = Release|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|ARM64.Build.0 = Release|ARM64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.ActiveCfg = Release|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x64Test.Build.0 = Release|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|DotNet_x86Test.Build.0 = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.ActiveCfg = Release|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3390,6 +3436,7 @@ Global
{05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
diff --git a/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj b/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj
new file mode 100644
index 000000000..54a0c0e79
--- /dev/null
+++ b/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj
@@ -0,0 +1,27 @@
+
+
+
+ 16.0
+ Win32Proj
+ {9cf74355-f018-4c19-81ad-9dc6b7f2c6f5}
+ apimswincoresynchl120
+ DynamicLibrary
+
+
+
+
+
+
+
+
+
+
+
+ NotUsing
+
+
+ kernel32.lib
+ definitions.def
+
+
+
\ No newline at end of file
diff --git a/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj.filters b/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj.filters
new file mode 100644
index 000000000..163db3010
--- /dev/null
+++ b/src/api-ms-win-core-synch-l1-2-0/api-ms-win-core-synch-l1-2-0.vcxproj.filters
@@ -0,0 +1,30 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/src/api-ms-win-core-synch-l1-2-0/definitions.def b/src/api-ms-win-core-synch-l1-2-0/definitions.def
new file mode 100644
index 000000000..5eae42b4d
--- /dev/null
+++ b/src/api-ms-win-core-synch-l1-2-0/definitions.def
@@ -0,0 +1,19 @@
+LIBRARY
+EXPORTS
+ DeleteSynchronizationBarrier = kernel32.DeleteSynchronizationBarrier
+ EnterSynchronizationBarrier = kernel32.EnterSynchronizationBarrier
+ InitOnceBeginInitialize = kernel32.InitOnceBeginInitialize
+ InitOnceComplete = kernel32.InitOnceComplete
+ InitOnceExecuteOnce = kernel32.InitOnceExecuteOnce
+ InitOnceInitialize = kernel32.InitOnceInitialize
+ InitializeConditionVariable = kernel32.InitializeConditionVariable
+ InitializeSynchronizationBarrier = kernel32.InitializeSynchronizationBarrier
+ SignalObjectAndWait = kernel32.SignalObjectAndWait
+ Sleep = kernel32.Sleep
+ SleepConditionVariableCS = kernel32.SleepConditionVariableCS
+ SleepConditionVariableSRW = kernel32.SleepConditionVariableSRW
+ WaitOnAddress
+ WakeAllConditionVariable = kernel32.WakeAllConditionVariable
+ WakeByAddressAll
+ WakeByAddressSingle
+ WakeConditionVariable = kernel32.WakeConditionVariable
diff --git a/src/api-ms-win-core-synch-l1-2-0/main.cpp b/src/api-ms-win-core-synch-l1-2-0/main.cpp
new file mode 100644
index 000000000..7bbc50ac7
--- /dev/null
+++ b/src/api-ms-win-core-synch-l1-2-0/main.cpp
@@ -0,0 +1,189 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+//
+// The code in this file was adapted from the STL on the 2021-07-05. Commit:
+// https://github.com/microsoft/STL/blob/e745bad3b1d05b5b19ec652d68abb37865ffa454/stl/src/atomic_wait.cpp
+//
+// It backports the following Windows 8 functions to Windows 7:
+// * WaitOnAddress
+// * WakeByAddressSingle
+// * WakeByAddressAll
+//
+
+#include
+#include
+
+#include
+#define _WIN32_WINNT 0x0601
+#include
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include
+#include
+
+namespace
+{
+ class [[nodiscard]] SRWLockGuard
+ {
+ public:
+ explicit SRWLockGuard(SRWLOCK & lock) noexcept :
+ _lock(&lock)
+ {
+ AcquireSRWLockExclusive(_lock);
+ }
+
+ ~SRWLockGuard()
+ {
+ ReleaseSRWLockExclusive(_lock);
+ }
+
+ SRWLockGuard(const SRWLockGuard&) = delete;
+ SRWLockGuard& operator=(const SRWLockGuard&) = delete;
+
+ SRWLockGuard(SRWLockGuard &&) = delete;
+ SRWLockGuard& operator=(SRWLockGuard&&) = delete;
+
+ private:
+ SRWLOCK* _lock;
+ };
+
+ struct WaitContext
+ {
+ const volatile void* address;
+ WaitContext* next;
+ WaitContext* prev;
+ CONDITION_VARIABLE cv;
+ };
+
+ struct [[nodiscard]] GuardedWaitContext : WaitContext
+ {
+ GuardedWaitContext(const volatile void* storage, WaitContext* head) noexcept :
+ WaitContext{ storage, head, head->prev, CONDITION_VARIABLE_INIT }
+ {
+ prev->next = this;
+ next->prev = this;
+ }
+
+ ~GuardedWaitContext()
+ {
+ const auto n = next;
+ const auto p = prev;
+ next->prev = p;
+ prev->next = n;
+ }
+
+ GuardedWaitContext(const GuardedWaitContext&) = delete;
+ GuardedWaitContext& operator=(const GuardedWaitContext&) = delete;
+
+ GuardedWaitContext(GuardedWaitContext &&) = delete;
+ GuardedWaitContext& operator=(GuardedWaitContext&&) = delete;
+ };
+
+#pragma warning(push)
+#pragma warning(disable : 4324) // structure was padded due to alignment specifier
+ struct alignas(std::hardware_destructive_interference_size) WaitTableEntry
+ {
+ SRWLOCK lock = SRWLOCK_INIT;
+ WaitContext head = { nullptr, &head, &head, CONDITION_VARIABLE_INIT };
+ };
+#pragma warning(pop)
+
+ [[nodiscard]] WaitTableEntry& GetWaitTableEntry(const volatile void* const storage) noexcept
+ {
+ // A prime number for the hash table size was chosen to prevent collisions.
+ constexpr size_t size = 251;
+ constexpr std::hash hasher;
+
+ static WaitTableEntry table[size];
+#pragma warning(suppress : 26446) // Prefer to use gsl::at() instead of unchecked subscript operator
+#pragma warning(suppress : 26482) // Only index into arrays using constant expressions
+#pragma warning(suppress : 26490) // Don't use reinterpret_cast
+ return table[hasher(reinterpret_cast(storage)) % size];
+ }
+
+#pragma warning(suppress : 26429) // Symbol 'comparand' is never tested for nullness, it can be marked as not_null
+ bool AreEqual(const volatile void* storage, const void* comparand, size_t size) noexcept
+ {
+ switch (size)
+ {
+ case 1:
+ return __iso_volatile_load8(static_cast(storage)) == *static_cast(comparand);
+ case 2:
+ return __iso_volatile_load16(static_cast(storage)) == *static_cast(comparand);
+ case 4:
+ return __iso_volatile_load32(static_cast(storage)) == *static_cast(comparand);
+ case 8:
+ return __iso_volatile_load64(static_cast(storage)) == *static_cast(comparand);
+ default:
+ abort();
+ }
+ }
+} // unnamed namespace
+
+extern "C" BOOL WINAPI WaitOnAddress(_In_reads_bytes_(AddressSize) volatile VOID* Address, _In_reads_bytes_(AddressSize) PVOID CompareAddress, _In_ SIZE_T AddressSize, _In_opt_ DWORD dwMilliseconds)
+{
+ auto& entry = GetWaitTableEntry(Address);
+
+ SRWLockGuard guard{ entry.lock };
+ GuardedWaitContext context{ Address, &entry.head };
+
+ for (;;)
+ {
+ // NOTE: under lock to prevent lost wakes
+ if (!AreEqual(Address, CompareAddress, AddressSize))
+ {
+ return TRUE;
+ }
+
+ if (!SleepConditionVariableSRW(&context.cv, &entry.lock, dwMilliseconds, 0))
+ {
+#ifndef NDEBUG
+ if (GetLastError() != ERROR_TIMEOUT)
+ {
+ abort();
+ }
+#endif
+ return FALSE;
+ }
+
+ if (dwMilliseconds != INFINITE)
+ {
+ // spurious wake to recheck the clock
+ return TRUE;
+ }
+ }
+}
+
+extern "C" VOID WINAPI WakeByAddressSingle(_In_ PVOID Address)
+{
+ auto& entry = GetWaitTableEntry(Address);
+ SRWLockGuard guard(entry.lock);
+
+ for (auto context = entry.head.next; context != &entry.head; context = context->next)
+ {
+ if (context->address == Address)
+ {
+ // Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
+ WakeAllConditionVariable(&context->cv);
+ // This break; is the difference between WakeByAddressSingle and WakeByAddressAll
+ break;
+ }
+ }
+}
+
+extern "C" VOID WINAPI WakeByAddressAll(_In_ PVOID Address)
+{
+ auto& entry = GetWaitTableEntry(Address);
+ SRWLockGuard guard(entry.lock);
+
+ for (auto context = entry.head.next; context != &entry.head; context = context->next)
+ {
+ if (context->address == Address)
+ {
+ // Can't move wake outside SRWLOCKed section: SRWLOCK also protects the context itself
+ WakeAllConditionVariable(&context->cv);
+ }
+ }
+}
diff --git a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj
index c1507c070..1665034e1 100644
--- a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj
+++ b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj
@@ -8,7 +8,6 @@
PublicTerminalCore
DynamicLibrary
-
@@ -21,27 +20,24 @@
-
+
{1cf55140-ef6a-4736-a403-957e4f7430bb}
-
+
{ca5cad1a-abcd-429c-b551-8562ec954746}
-
+
{18D09A24-8240-42D6-8CB6-236EEE820263}
-
- {0cf235bd-2da0-407e-90ee-c467e8bbc714}
-
-
+
{af0a096a-8b3a-4949-81ef-7df8f0fee91f}
-
- {3ae13314-1939-4dfa-9c14-38ca0834050c}
-
-
+
{48d21369-3d7b-4431-9967-24e81292cf62}
+
+ {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}
+