From 005b8cc5e0c655e89db78dd35fb688da6b8e0a6f Mon Sep 17 00:00:00 2001 From: John Stephens Date: Fri, 26 Mar 2021 09:10:57 -0700 Subject: [PATCH 01/56] Link to WinMM.Lib for PlaySound with 19041 (#9624) The PlaySound functions were removed from OneCoreUAP_apiset.Lib in Windows 10 SDK 19041 because they did not actually belong there. Link to WinMM.Lib for PlaySoundW. ### Validation Steps Performed * Built for x64 from repository root with: `MSBuild.exe -property:TargetPlatformVersion=10.0.19041.0` * Installed CascadiaPackage_0.0.1.0_x64_Debug.msix and launched on 19042.867 --- src/cascadia/TerminalApp/dll/TerminalApp.vcxproj | 2 +- src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj | 2 +- src/host/exe/Host.EXE.vcxproj | 1 + src/host/ut_host/Host.UnitTests.vcxproj | 3 +++ .../Interactivity.Win32.UnitTests.vcxproj | 3 +++ 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index c1ed497580..6b7d2df3aa 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -104,7 +104,7 @@ $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); - User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) + User32.lib;WindowsApp.lib;shell32.lib;WinMM.Lib;%(AdditionalDependencies) /INCLUDE:_DllMain@12 /INCLUDE:DllMain diff --git a/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj b/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj index 59a1b747b3..a2f900ef74 100644 --- a/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj +++ b/src/cascadia/UnitTests_TerminalCore/UnitTests.vcxproj @@ -92,7 +92,7 @@ pch.h - WindowsApp.lib;%(AdditionalDependencies) + WindowsApp.lib;WinMM.Lib;%(AdditionalDependencies) diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index ca5cd3f865..42bafc2ab3 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -84,6 +84,7 @@ true + WinMM.Lib;%(AdditionalDependencies) diff --git a/src/host/ut_host/Host.UnitTests.vcxproj b/src/host/ut_host/Host.UnitTests.vcxproj index 98fe1dc3ab..486965b2fb 100644 --- a/src/host/ut_host/Host.UnitTests.vcxproj +++ b/src/host/ut_host/Host.UnitTests.vcxproj @@ -102,6 +102,9 @@ ..;$(SolutionDir)src\inc;$(SolutionDir)src\inc\test;%(AdditionalIncludeDirectories) + + WinMM.Lib;%(AdditionalDependencies) + diff --git a/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj b/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj index 293e04a215..2330bee3aa 100644 --- a/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj +++ b/src/interactivity/win32/ut_interactivity_win32/Interactivity.Win32.UnitTests.vcxproj @@ -69,6 +69,9 @@ ..;$(SolutionDir)src\inc;$(Solutiondir)src\inc\test;%(AdditionalIncludeDirectories) + + WinMM.Lib;%(AdditionalDependencies) + From 690fbbbc27a73e1e4be222f7bea14ab2e033d803 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Fri, 26 Mar 2021 09:46:14 -0700 Subject: [PATCH 02/56] Add a WPR profile containing all of Terminal's ETW providers (#9630) --- src/Terminal.wprp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/Terminal.wprp diff --git a/src/Terminal.wprp b/src/Terminal.wprp new file mode 100644 index 0000000000..d1a2b64ae2 --- /dev/null +++ b/src/Terminal.wprp @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 906edf7002b8ccf4d819fcc6f45a68f7815b3252 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 26 Mar 2021 15:09:49 -0700 Subject: [PATCH 03/56] Implement Default Terminal (#7489) - Implements the default application behavior and handoff mechanisms between console and terminal. The inbox portion is done already. This adds the ability for our OpenConsole.exe to accept the incoming server connection from the Windows OS, stand up a PTY session, start the Windows Terminal as a listener for an incoming connection, and then send it the incoming PTY connection for it to launch a tab. - The tab is launched with default settings at the moment. - You must configure the default application using the `conhost.exe` propsheet or with the registry keys. Finishing the setting inside Windows Terminal will be a todo after this is complete. The OS Settings panel work to surface this setting is a dependency delivered by another team and you will not see it here. ## Validation Steps Performed - [x] Manual adjust of registry keys to the delegation conhost/terminal behavior - [x] Adjustment of the delegation options with the propsheet - [x] Launching things from the run box manually and watching them show in Terminal - [x] Launching things from shortcuts and watching them show in the Terminal Documentation on how it works will be a TODO post completion in #9462 References #7414 - Default Terminal spec Closes #492 --- .github/actions/spelling/dictionary/apis.txt | 6 + .github/actions/spelling/expect/expect.txt | 2 + .vscode/tasks.json | 17 +- OpenConsole.sln | 70 ++-- .../CascadiaPackage/CascadiaPackage.wapproj | 1 + .../CascadiaPackage/Package-Dev.appxmanifest | 36 +- .../CascadiaPackage/Package-Pre.appxmanifest | 35 ++ .../CascadiaPackage/Package.appxmanifest | 36 +- .../TerminalApp/AppCommandlineArgs.cpp | 48 ++- src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 + src/cascadia/TerminalApp/AppLogic.cpp | 11 + .../Resources/en-US/Resources.resw | 54 +-- src/cascadia/TerminalApp/TerminalPage.cpp | 73 +++- src/cascadia/TerminalApp/TerminalPage.h | 9 +- .../TerminalConnection/CTerminalHandoff.cpp | 108 ++++++ .../TerminalConnection/CTerminalHandoff.h | 56 +++ .../TerminalConnection/ConptyConnection.cpp | 61 +++- .../TerminalConnection/ConptyConnection.h | 13 + .../TerminalConnection/ConptyConnection.idl | 10 +- .../ITerminalConnection.idl | 2 + .../TerminalConnection.vcxproj | 7 +- .../TerminalConnection.vcxproj.filters | 6 +- .../TerminalSettingsEditor/Launch.cpp | 17 + src/cascadia/TerminalSettingsEditor/Launch.h | 4 + .../TerminalSettingsEditor/Launch.idl | 4 +- .../TerminalSettingsEditor/Launch.xaml | 10 + .../Resources/en-US/Resources.resw | 8 + src/host/ConsoleArguments.cpp | 19 + src/host/ConsoleArguments.hpp | 14 +- src/host/exe/CConsoleHandoff.cpp | 62 ++++ src/host/exe/CConsoleHandoff.h | 42 +++ src/host/exe/Host.EXE.vcxproj | 8 +- src/host/exe/Host.EXE.vcxproj.filters | 8 +- src/host/exe/exemain.cpp | 334 ++++++++++++++++++ src/host/exe/sources | 3 +- src/host/exemain.cpp | 227 ------------ src/host/globals.h | 1 + src/host/host-common.vcxitems | 2 +- src/host/lib/hostlib.vcxproj | 2 +- src/host/lib/hostlib.vcxproj.filters | 32 +- src/host/proxy/Host.Proxy.vcxproj | 43 ++- src/host/proxy/Host.Proxy.vcxproj.filters | 25 +- src/host/proxy/IConsoleHandoff.idl | 4 + src/host/proxy/ITerminalHandoff.idl | 16 + src/host/proxy/OpenConsoleProxy.def | 8 + src/host/srvinit.cpp | 176 ++++++++- src/host/srvinit.h | 4 + src/host/ut_host/ConsoleArgumentsTests.cpp | 150 +++++--- src/internal/stubs.cpp | 6 +- src/server/IoDispatchers.cpp | 14 + 50 files changed, 1483 insertions(+), 423 deletions(-) create mode 100644 src/cascadia/TerminalConnection/CTerminalHandoff.cpp create mode 100644 src/cascadia/TerminalConnection/CTerminalHandoff.h create mode 100644 src/host/exe/CConsoleHandoff.cpp create mode 100644 src/host/exe/CConsoleHandoff.h create mode 100644 src/host/exe/exemain.cpp delete mode 100644 src/host/exemain.cpp create mode 100644 src/host/proxy/ITerminalHandoff.idl create mode 100644 src/host/proxy/OpenConsoleProxy.def diff --git a/.github/actions/spelling/dictionary/apis.txt b/.github/actions/spelling/dictionary/apis.txt index e6c7a19576..378c6786ba 100644 --- a/.github/actions/spelling/dictionary/apis.txt +++ b/.github/actions/spelling/dictionary/apis.txt @@ -11,6 +11,7 @@ CYICON D2DERR_SHADER_COMPILE_FAILED dataobject DERR +dlldata environstrings EXPCMDFLAGS EXPCMDSTATE @@ -83,6 +84,7 @@ schandle semver serializer shobjidl +SINGLEUSE SHOWMINIMIZED SIZENS smoothstep @@ -93,6 +95,8 @@ spsc sregex STDCPP strchr +STDMETHOD +Stubless Subheader Subpage UPDATEINIFILE @@ -108,8 +112,10 @@ UPDATEINIFILE userenv wcsstr wcstoui +winmain wpc wsregex +wwinmain XDocument XElement xlocmes diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index c3aba85a2c..148e470807 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -433,6 +433,7 @@ cstring cstyle csv CSwitch +CTerminal CText ctime ctl @@ -571,6 +572,7 @@ defaultsettings DEFAULTTONEAREST DEFAULTTONULL DEFAULTTOPRIMARY +DEFCON defectdefs DEFERERASE deff diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 827e4c4076..e9942e0bb6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,7 +16,9 @@ "${workspaceFolder}\\OpenConsole.sln", "/p:Configuration=${input:configChoice}", "/p:Platform=${input:platformChoice}", + "/p:AppxSymbolPackageEnabled=false", // This takes a long time, so false if we don't really need it. "/t:$target", + "/m", // Parallel builds "/verbosity:minimal" ], "problemMatcher": ["$msCompile"], @@ -46,8 +48,7 @@ ], "problemMatcher": ["$msCompile"], "group": { - "kind": "build", - "isDefault": true + "kind": "build" } }, { @@ -57,6 +58,18 @@ "args": [ ], "problemMatcher": ["$msCompile"], + }, + { + "type": "process", + "label": "Run Code Format", + "command": "powershell.exe", + "args": [ + "-Command", + "Import-Module ${workspaceFolder}\\tools\\OpenConsole.psm1;", + "Set-MsBuildDevEnvironment;", + "Invoke-CodeFormat", + ], + "problemMatcher": ["$msCompile"], } ], "inputs":[ diff --git a/OpenConsole.sln b/OpenConsole.sln index 71bc8ce925..0cdb34c7ef 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -12,7 +12,9 @@ Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "CascadiaPackage", "src\casc EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.EXE", "src\host\exe\Host.EXE.vcxproj", "{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714} + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239} = {5D23E8E1-3C64-4CC1-A8F7-6861677F7239} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PropertiesLibrary", "src\propslib\propslib.vcxproj", "{345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}" @@ -64,6 +66,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host", "src\host\lib\hostlib.vcxproj", "{06EC74CB-9A12-429C-B551-8562EC954746}" ProjectSection(ProjectDependencies) = postProject {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714} EndProjectSection EndProject @@ -104,6 +107,9 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build Common", "_Build Common", "{04170EEF-983A-4195-BFEF-2321E5E38A1E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "src\server\lib\server.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820262}" + ProjectSection(ProjectDependencies) = postProject + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Host.Tests.UIA", "src\host\ft_uia\Host.Tests.UIA.csproj", "{C17E1BF3-9D34-4779-9458-A8EF98CC5662}" ProjectSection(ProjectDependencies) = postProject @@ -369,7 +375,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_Remoting", "src\c EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wpf", "wpf", "{4DAF0299-495E-4CD1-A982-9BAC16A45932}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenConsoleProxy", "src\host\proxy\Host.Proxy.vcxproj", "{E437B604-3E98-4F40-A927-E173E818EA4B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenConsoleProxy", "src\host\proxy\Host.Proxy.vcxproj", "{71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Window", "Window", "{2D17E75D-2DDC-42C4-AD70-704D95A937AE}" EndProject @@ -2580,36 +2586,36 @@ Global {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x64.Build.0 = Release|x64 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.ActiveCfg = Release|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.Build.0 = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.ActiveCfg = AuditMode|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.Build.0 = AuditMode|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.ActiveCfg = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.Build.0 = AuditMode|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.Build.0 = Debug|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.ActiveCfg = Debug|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.Build.0 = Debug|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.ActiveCfg = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.Build.0 = Debug|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|Any CPU.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.ActiveCfg = Release|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.Build.0 = Release|ARM64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.ActiveCfg = Release|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.Build.0 = Release|x64 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.ActiveCfg = Release|Win32 - {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.Build.0 = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|x64.Build.0 = AuditMode|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|x86.Build.0 = AuditMode|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|ARM.ActiveCfg = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|ARM64.Build.0 = Debug|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x64.ActiveCfg = Debug|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x64.Build.0 = Debug|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x86.ActiveCfg = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x86.Build.0 = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|Any CPU.ActiveCfg = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|ARM.ActiveCfg = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|ARM64.ActiveCfg = Release|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|ARM64.Build.0 = Release|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x64.ActiveCfg = Release|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x64.Build.0 = Release|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x86.ActiveCfg = Release|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2701,7 +2707,7 @@ Global {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {2D17E75D-2DDC-42C4-AD70-704D95A937AE} {68A10CD3-AA64-465B-AF5F-ED4E9700543C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {4DAF0299-495E-4CD1-A982-9BAC16A45932} = {59840756-302F-44DF-AA47-441A9D673202} - {E437B604-3E98-4F40-A927-E173E818EA4B} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} {2D17E75D-2DDC-42C4-AD70-704D95A937AE} = {59840756-302F-44DF-AA47-441A9D673202} {77875138-BB08-49F9-8BB1-409C2150E0E1} = {59840756-302F-44DF-AA47-441A9D673202} {9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202} diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj index b10a887323..865774f321 100644 --- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj +++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj @@ -70,6 +70,7 @@ + diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index a257a803ab..ee36644e25 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -74,9 +74,43 @@ com.microsoft.windows.terminal.settings - + + + + {1F9F2BF5-5BC3-4F17-B0E6-912413F1F451} + + + + + + + {051F34EE-C1FD-4B19-AF75-9BA54648434C} + + + + + + + + + + + + + + + + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 11a093d952..aac5b64f31 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -75,8 +75,43 @@ Enabled="false" DisplayName="ms-resource:AppNamePre" /> + + + + {06EC847C-C0A5-46B8-92CB-7C92F6E35CD5} + + + + + + + {86633F1F-6454-40EC-89CE-DA4EBA977EE2} + + + + + + + + + + + + + + + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index e6a4d70528..b7953a3e08 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -75,9 +75,43 @@ Enabled="false" DisplayName="ms-resource:AppName" /> - + + diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 67b7590684..6e68084e87 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -684,6 +684,18 @@ std::vector& AppCommandlineArgs::GetStartupActions() return _startupActions; } +// Method Description: +// - Returns whether we should start listening for inbound PTY connections +// coming from the operating system default application feature. +// Arguments: +// - +// Return Value: +// - True if the listener should be started. False otherwise. +bool AppCommandlineArgs::IsHandoffListener() const noexcept +{ + return _isHandoffListener; +} + // Method Description: // - Get the string of text that should be displayed to the user on exit. This // is usually helpful for cases where the user entered some sort of invalid @@ -726,17 +738,23 @@ bool AppCommandlineArgs::ShouldExitEarly() const noexcept // - void AppCommandlineArgs::ValidateStartupCommands() { - // If we parsed no commands, or the first command we've parsed is not a new - // tab action, prepend a new-tab command to the front of the list. - if (_startupActions.empty() || - _startupActions.front().Action() != ShortcutAction::NewTab) + // Only check over the actions list for the potential to add a new-tab + // command if we are not starting for the purposes of receiving an inbound + // handoff connection from the operating system. + if (!_isHandoffListener) { - // Build the NewTab action from the values we've parsed on the commandline. - NewTerminalArgs newTerminalArgs{}; - NewTabArgs args{ newTerminalArgs }; - ActionAndArgs newTabAction{ ShortcutAction::NewTab, args }; - // push the arg onto the front - _startupActions.insert(_startupActions.begin(), 1, newTabAction); + // If we parsed no commands, or the first command we've parsed is not a new + // tab action, prepend a new-tab command to the front of the list. + if (_startupActions.empty() || + _startupActions.front().Action() != ShortcutAction::NewTab) + { + // Build the NewTab action from the values we've parsed on the commandline. + NewTerminalArgs newTerminalArgs{}; + NewTabArgs args{ newTerminalArgs }; + ActionAndArgs newTabAction{ ShortcutAction::NewTab, args }; + // push the arg onto the front + _startupActions.insert(_startupActions.begin(), 1, newTabAction); + } } } @@ -760,6 +778,15 @@ std::optional AppComman // - 0 if the commandline was successfully parsed int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { + for (const auto& arg : args) + { + if (arg == L"-Embedding") + { + _isHandoffListener = true; + return 0; + } + } + auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args); for (auto& cmdBlob : commands) @@ -864,6 +891,7 @@ void AppCommandlineArgs::FullResetState() _startupActions.clear(); _exitMessage = ""; _shouldExitEarly = false; + _isHandoffListener = false; _windowTarget = {}; } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 4c3456932e..bc3d56f16d 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -35,6 +35,7 @@ public: void ValidateStartupCommands(); std::vector& GetStartupActions(); + bool IsHandoffListener() const noexcept; const std::string& GetExitMessage(); bool ShouldExitEarly() const noexcept; @@ -104,6 +105,7 @@ private: const Commandline* _currentCommandline{ nullptr }; std::optional _launchMode{ std::nullopt }; + bool _isHandoffListener{ false }; std::vector _startupActions; std::string _exitMessage; bool _shouldExitEarly{ false }; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index e7a10b3e4c..fecccc7503 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1166,6 +1166,17 @@ namespace winrt::TerminalApp::implementation _hasCommandLineArguments = args.size() > 1; _appArgs.ValidateStartupCommands(); _root->SetStartupActions(_appArgs.GetStartupActions()); + + // Check if we were started as a COM server for inbound connections of console sessions + // coming out of the operating system default application feature. If so, + // tell TerminalPage to start the listener as we have to make sure it has the chance + // to register a handler to hear about the requests first and is all ready to receive + // them before the COM server registers itself. Otherwise, the request might come + // in and be routed to an event with no handlers or a non-ready Page. + if (_appArgs.IsHandoffListener()) + { + _root->SetInboundListener(); + } } return result; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 51b011c464..68dcb0da86 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 0eefa036f8..0475725751 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -194,6 +194,9 @@ namespace winrt::TerminalApp::implementation // Hookup our event handlers to the ShortcutActionDispatch _RegisterActionCallbacks(); + // Hook up inbound connection event handler + TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection }); + //Event Bindings (Early) _newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) { if (auto page{ weakThis.get() }) @@ -351,15 +354,29 @@ namespace winrt::TerminalApp::implementation if (_startupState == StartupState::NotInitialized) { _startupState = StartupState::InStartup; - if (_startupActions.Size() == 0) - { - _OpenNewTab(nullptr); + ProcessStartupActions(_startupActions, true); - _CompleteInitialization(); - } - else + // If we were told that the COM server needs to be started to listen for incoming + // default application connections, start it now. + // This MUST be done after we've registered the event listener for the new connections + // or the COM server might start receiving requests on another thread and dispatch + // them to nowhere. + if (_shouldStartInboundListener) { - ProcessStartupActions(_startupActions, true); + try + { + winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + } + // If we failed to start the listener, it will throw. + // We should fail fast here or the Terminal will be in a very strange state. + // We only start the listener if the Terminal was started with the COM server + // `-Embedding` flag and we make no tabs as a result. + // Therefore, if the listener cannot start itself up to make that tab with + // the inbound connection that caused the COM activation in the first place... + // we would be left with an empty terminal frame with no tabs. + // Instead, crash out so COM sees the server die and things unwind + // without a weird empty frame window. + CATCH_FAIL_FAST() } } } @@ -382,11 +399,6 @@ namespace winrt::TerminalApp::implementation const bool initial, const winrt::hstring cwd) { - // If there are no actions left, do nothing. - if (actions.Size() == 0) - { - return; - } auto weakThis{ get_weak() }; // Handle it on a subsequent pass of the UI thread. @@ -757,13 +769,16 @@ namespace winrt::TerminalApp::implementation // - newTerminalArgs: An object that may contain a blob of parameters to // control which profile is created and with possible other // configurations. See TerminalSettings::CreateWithNewTerminalArgs for more details. - void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs) + // - existingConnection: An optional connection that is already established to a PTY + // for this tab to host instead of creating one. + // If not defined, the tab will create the connection. + void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) try { const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) }; const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) }; - _CreateNewTabFromSettings(profileGuid, settings); + _CreateNewTabFromSettings(profileGuid, settings, existingConnection); const uint32_t tabCount = _tabs.Size(); const bool usedManualProfile = (newTerminalArgs != nullptr) && @@ -804,13 +819,14 @@ namespace winrt::TerminalApp::implementation // - Creates a new tab with the given settings. If the tab bar is not being // currently displayed, it will be shown. // Arguments: + // - profileGuid: ID to use to lookup profile settings for this connection // - settings: the TerminalSettings object to use to create the TerminalControl with. - void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings) + // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one + void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, TerminalConnection::ITerminalConnection existingConnection) { // Initialize the new tab - - // Create a connection based on the values in our settings object. - auto connection = _CreateConnectionFromSettings(profileGuid, settings); + // Create a connection based on the values in our settings object if we weren't given one. + auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); TerminalConnection::ITerminalConnection debugConnection{ nullptr }; if (_settings.GlobalSettings().DebugFeaturesEnabled()) @@ -2723,6 +2739,19 @@ namespace winrt::TerminalApp::implementation _startupActions = winrt::single_threaded_vector(std::move(listCopy)); } + // Routine Description: + // - Notifies this Terminal Page that it should start the incoming connection + // listener for command-line tools attempting to join this Terminal + // through the default application channel. + // Arguments: + // - - Implicitly sets to true. Default page state is false. + // Return Value: + // - + void TerminalPage::SetInboundListener() + { + _shouldStartInboundListener = true; + } + winrt::TerminalApp::IDialogPresenter TerminalPage::DialogPresenter() const { return _dialogPresenter.get(); @@ -3033,6 +3062,7 @@ namespace winrt::TerminalApp::implementation { return _isFullscreen; } + // Method Description: // - Returns true if we're currently in "Always on top" mode. When we're in // always on top mode, the window should be on top of all other windows. @@ -3047,6 +3077,12 @@ namespace winrt::TerminalApp::implementation return _isAlwaysOnTop; } + void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection) + { + // TODO: GH 9458 will give us more context so we can try to choose a better profile. + _OpenNewTab(nullptr, connection); + } + // Method Description: // - Updates all tabs with their current index in _tabs. // Arguments: @@ -3155,7 +3191,6 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: // Method Description: // - Computes the delta for scrolling the tab's viewport. // Arguments: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 2f6348a4fd..bb830b9770 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -66,6 +66,7 @@ namespace winrt::TerminalApp::implementation bool AlwaysOnTop() const; void SetStartupActions(std::vector& actions); + void SetInboundListener(); static std::vector ConvertExecuteCommandlineToActions(const Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args); winrt::TerminalApp::IDialogPresenter DialogPresenter() const; @@ -138,6 +139,7 @@ namespace winrt::TerminalApp::implementation StartupState _startupState{ StartupState::NotInitialized }; Windows::Foundation::Collections::IVector _startupActions; + bool _shouldStartInboundListener{ false }; void _ShowAboutDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowCloseWarningDialog(); @@ -147,8 +149,8 @@ namespace winrt::TerminalApp::implementation void _CreateNewTabFlyout(); void _OpenNewTabDropdown(); - void _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs); - void _CreateNewTabFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::Model::TerminalSettings settings); + void _OpenNewTab(const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); + void _CreateNewTabFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::Model::TerminalSettings settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, Microsoft::Terminal::Settings::Model::TerminalSettings settings); winrt::fire_and_forget _OpenNewWindow(const bool elevate, const Microsoft::Terminal::Settings::Model::NewTerminalArgs newTerminalArgs); @@ -275,6 +277,8 @@ namespace winrt::TerminalApp::implementation void _HidePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); void _RestorePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); + void _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp void _HandleOpenNewTabDropdown(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args); @@ -322,6 +326,7 @@ namespace winrt::TerminalApp::implementation void _HandleFindMatch(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args); void _HandleTogglePaneReadOnly(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args); void _HandleNewWindow(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args); + void _HandleToggleInboundPty(const IInspectable& sender, const Microsoft::Terminal::Settings::Model::ActionEventArgs& args); // Make sure to hook new actions up in _RegisterActionCallbacks! #pragma endregion diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp new file mode 100644 index 0000000000..2761119031 --- /dev/null +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" + +#include "CTerminalHandoff.h" + +using namespace Microsoft::WRL; + +// The callback function when a connection is received +static NewHandoffFunction _pfnHandoff = nullptr; +// The registration ID of the class object for clean up later +static DWORD g_cTerminalHandoffRegistration = 0; + +// Routine Description: +// - Starts listening for TerminalHandoff requests by registering +// our class and interface with COM. +// Arguments: +// - pfnHandoff - Function to callback when a handoff is received +// Return Value: +// - S_OK, E_NOT_VALID_STATE (start called when already started) or relevant COM registration error. +HRESULT CTerminalHandoff::s_StartListening(NewHandoffFunction pfnHandoff) noexcept +try +{ + RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); + + const auto classFactory = Make>(); + + RETURN_IF_NULL_ALLOC(classFactory); + + ComPtr unk; + RETURN_IF_FAILED(classFactory.As(&unk)); + + RETURN_IF_FAILED(CoRegisterClassObject(__uuidof(CTerminalHandoff), unk.Get(), CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &g_cTerminalHandoffRegistration)); + + _pfnHandoff = pfnHandoff; + + return S_OK; +} +CATCH_RETURN() + +// Routine Description: +// - Stops listening for TerminalHandoff requests by revoking the registration +// our class and interface with COM +// Arguments: +// - +// Return Value: +// - S_OK, E_NOT_VALID_STATE (stop called when not started), or relevant COM class revoke error +HRESULT CTerminalHandoff::s_StopListening() noexcept +{ + RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff); + + _pfnHandoff = nullptr; + + if (g_cTerminalHandoffRegistration) + { + RETURN_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); + g_cTerminalHandoffRegistration = 0; + } + + return S_OK; +} + +// Routine Description: +// - Helper to duplicate a handle to ourselves so we can keep holding onto it +// after the caller frees the original one. +// Arguments: +// - in - Handle to duplicate +// - out - Where to place the duplicated value +// Return Value: +// - S_OK or Win32 error from `::DuplicateHandle` +static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept +{ + RETURN_IF_WIN32_BOOL_FALSE(::DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &out, 0, FALSE, DUPLICATE_SAME_ACCESS)); + return S_OK; +} + +// Routine Description: +// - Receives the terminal handoff via COM from the other process, +// duplicates handles as COM will free those given on the way out, +// then fires off an event notifying the rest of the terminal that +// a connection is on its way in. +// Arguments: +// - in - PTY input handle that we will read from +// - out - PTY output handle that we will write to +// - signal - PTY signal handle for out of band messaging +// - process - Process handle to client so we can track its lifetime and exit appropriately +// Return Value: +// - E_NOT_VALID_STATE if a event handler is not registered before calling. `::DuplicateHandle` +// error codes if we cannot manage to make our own copy of handles to retain. Or S_OK/error +// from the registered handler event function. +HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept +{ + // Report an error if no one registered a handoff function before calling this. + RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff); + + // Duplicate the handles from what we received. + // The contract with COM specifies that any HANDLEs we receive from the caller belong + // to the caller and will be freed when we leave the scope of this method. + // Making our own duplicate copy ensures they hang around in our lifetime. + RETURN_IF_FAILED(_duplicateHandle(in, in)); + RETURN_IF_FAILED(_duplicateHandle(out, out)); + RETURN_IF_FAILED(_duplicateHandle(signal, signal)); + RETURN_IF_FAILED(_duplicateHandle(process, process)); + + // Call registered handler from when we started listening. + return _pfnHandoff(in, out, signal, process); +} diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h new file mode 100644 index 0000000000..396f4a095f --- /dev/null +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -0,0 +1,56 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- CTerminalHandoff.h + +Abstract: +- This module receives an incoming request to host a terminal UX + for a console mode application already started and attached to a PTY. + +Author(s): +- Michael Niksa (MiNiksa) 31-Aug-2020 + +--*/ + +#pragma once + +#include "ITerminalHandoff.h" + +#if defined(WT_BRANDING_RELEASE) +#define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" +#elif defined(WT_BRANDING_PREVIEW) +#define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" +#else +#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" +#endif + +using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE); + +struct __declspec(uuid(__CLSID_CTerminalHandoff)) + CTerminalHandoff : public Microsoft::WRL::RuntimeClass, ITerminalHandoff> +{ +#pragma region ITerminalHandoff + STDMETHODIMP EstablishPtyHandoff(HANDLE in, + HANDLE out, + HANDLE signal, + HANDLE process) noexcept override; + +#pragma endregion + + static HRESULT s_StartListening(NewHandoffFunction pfnHandoff) noexcept; + static HRESULT s_StopListening() noexcept; +}; + +// Disable warnings from the CoCreatableClass macro as the value it provides for +// automatic COM class registration is of much greater value than the nits from +// the static analysis warnings. +#pragma warning(push) + +#pragma warning(disable : 26477) // Macro uses 0/NULL over nullptr. +#pragma warning(disable : 26476) // Macro uses naked union over variant. + +CoCreatableClass(CTerminalHandoff); + +#pragma warning(pop) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 1b96cc92c1..f7e5b7e819 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -9,6 +9,7 @@ #include #include "ConptyConnection.g.cpp" +#include "CTerminalHandoff.h" #include "../../types/inc/utils.hpp" #include "../../types/inc/Environment.hpp" @@ -190,6 +191,32 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation } CATCH_RETURN(); + ConptyConnection::ConptyConnection(const HANDLE hSig, + const HANDLE hIn, + const HANDLE hOut, + const HANDLE hClientProcess) : + _initialRows{ 25 }, + _initialCols{ 80 }, + _commandline{ L"" }, + _startingDirectory{ L"" }, + _startingTitle{ L"" }, + _environment{ nullptr }, + _guid{}, + _u8State{}, + _u16Str{}, + _buffer{}, + _inPipe{ hIn }, + _outPipe{ hOut } + { + hSig; // TODO: GH 9464 this needs to be packed into the hpcon + if (_guid == guid{}) + { + _guid = Utils::CreateGuid(); + } + + _piClient.hProcess = hClientProcess; + } + ConptyConnection::ConptyConnection(const hstring& commandline, const hstring& startingDirectory, const hstring& startingTitle, @@ -222,9 +249,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation void ConptyConnection::Start() try { - const COORD dimensions{ gsl::narrow_cast(_initialCols), gsl::narrow_cast(_initialRows) }; - THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(dimensions, PSEUDOCONSOLE_RESIZE_QUIRK | PSEUDOCONSOLE_WIN32_INPUT_MODE, &_inPipe, &_outPipe, &_hPC)); - THROW_IF_FAILED(_LaunchAttachedClient()); + if (!_inPipe) + { + const COORD dimensions{ gsl::narrow_cast(_initialCols), gsl::narrow_cast(_initialRows) }; + THROW_IF_FAILED(_CreatePseudoConsoleAndPipes(dimensions, PSEUDOCONSOLE_RESIZE_QUIRK | PSEUDOCONSOLE_WIN32_INPUT_MODE, &_inPipe, &_outPipe, &_hPC)); + THROW_IF_FAILED(_LaunchAttachedClient()); + } _startTime = std::chrono::high_resolution_clock::now(); @@ -451,6 +481,31 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation return 0; } + static winrt::event _newConnectionHandlers; + + winrt::event_token ConptyConnection::NewConnection(NewConnectionHandler const& handler) { return _newConnectionHandlers.add(handler); }; + void ConptyConnection::NewConnection(winrt::event_token const& token) { _newConnectionHandlers.remove(token); }; + + HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept + try + { + auto conn = winrt::make(signal, in, out, process); + _newConnectionHandlers(conn); + + return S_OK; + } + CATCH_RETURN() + + void ConptyConnection::StartInboundListener() + { + THROW_IF_FAILED(CTerminalHandoff::s_StartListening(&ConptyConnection::NewHandoff)); + } + + void ConptyConnection::StopInboundListener() + { + THROW_IF_FAILED(CTerminalHandoff::s_StopListening()); + } + // Function Description: // - This function will be called (by C++/WinRT) after the final outstanding reference to // any given connection instance is released. diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 557fb4969e..3eee9fc8d0 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -19,6 +19,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { struct ConptyConnection : ConptyConnectionT, ConnectionStateHolder { + ConptyConnection(const HANDLE hSig, + const HANDLE hIn, + const HANDLE hOut, + const HANDLE hClientProcess); + ConptyConnection( const hstring& cmdline, const hstring& startingDirectory, @@ -36,6 +41,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation winrt::guid Guid() const noexcept; + static void StartInboundListener(); + static void StopInboundListener(); + + static winrt::event_token NewConnection(NewConnectionHandler const& handler); + static void NewConnection(winrt::event_token const& token); + WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler); private: @@ -43,6 +54,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation void _indicateExitWithStatus(unsigned int status) noexcept; void _ClientTerminated() noexcept; + static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept; + uint32_t _initialRows{}; uint32_t _initialCols{}; hstring _commandline; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.idl b/src/cascadia/TerminalConnection/ConptyConnection.idl index fc53f368b6..766c7263a5 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.idl +++ b/src/cascadia/TerminalConnection/ConptyConnection.idl @@ -5,11 +5,13 @@ import "ITerminalConnection.idl"; namespace Microsoft.Terminal.TerminalConnection { - [default_interface] - runtimeclass ConptyConnection : ITerminalConnection + [default_interface] runtimeclass ConptyConnection : ITerminalConnection { - ConptyConnection(String cmdline, String startingDirectory, String startingTitle, IMapView environment, UInt32 rows, UInt32 columns, Guid guid); + ConptyConnection(String cmdline, String startingDirectory, String startingTitle, IMapView environment, UInt32 rows, UInt32 columns, Guid guid); Guid Guid { get; }; - }; + static event NewConnectionHandler NewConnection; + static void StartInboundListener(); + static void StopInboundListener(); + }; } diff --git a/src/cascadia/TerminalConnection/ITerminalConnection.idl b/src/cascadia/TerminalConnection/ITerminalConnection.idl index 398724cd88..e485cc06db 100644 --- a/src/cascadia/TerminalConnection/ITerminalConnection.idl +++ b/src/cascadia/TerminalConnection/ITerminalConnection.idl @@ -27,4 +27,6 @@ namespace Microsoft.Terminal.TerminalConnection event Windows.Foundation.TypedEventHandler StateChanged; ConnectionState State { get; }; }; + + delegate void NewConnectionHandler(ITerminalConnection connection); } diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj index 958593eae5..6254845235 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj @@ -15,6 +15,7 @@ AzureConnection.idl + ConptyConnection.idl @@ -24,6 +25,7 @@ + AzureConnection.idl @@ -77,9 +79,12 @@ + + $(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) + $(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies) - + \ No newline at end of file diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters index 91e6af3f51..12a9cc6c44 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters @@ -18,12 +18,14 @@ + + @@ -38,8 +40,6 @@ - - Resources\en-US - + \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsEditor/Launch.cpp b/src/cascadia/TerminalSettingsEditor/Launch.cpp index b2bbaedd4b..3b86bb3d39 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.cpp +++ b/src/cascadia/TerminalSettingsEditor/Launch.cpp @@ -37,4 +37,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation const auto profile{ winrt::unbox_value(value) }; _State.Settings().GlobalSettings().DefaultProfile(profile.Guid()); } + + // TODO GH#9463 - Complete hookup of Terminal UX to choose defapp. + Windows::Foundation::Collections::IObservableVector Launch::DefaultTerminals() + { + Windows::Foundation::Collections::IObservableVector vec; + return vec; + } + + IInspectable Launch::CurrentDefaultTerminal() + { + return nullptr; + } + + void Launch::CurrentDefaultTerminal(const IInspectable& value) + { + value; + } } diff --git a/src/cascadia/TerminalSettingsEditor/Launch.h b/src/cascadia/TerminalSettingsEditor/Launch.h index 8219939e06..3009e2c367 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.h +++ b/src/cascadia/TerminalSettingsEditor/Launch.h @@ -28,6 +28,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation IInspectable CurrentDefaultProfile(); void CurrentDefaultProfile(const IInspectable& value); + Windows::Foundation::Collections::IObservableVector DefaultTerminals(); + IInspectable CurrentDefaultTerminal(); + void CurrentDefaultTerminal(const IInspectable& value); + WINRT_PROPERTY(Editor::LaunchPageNavigationState, State, nullptr); GETSET_BINDABLE_ENUM_SETTING(LaunchMode, Model::LaunchMode, State().Settings().GlobalSettings, LaunchMode); diff --git a/src/cascadia/TerminalSettingsEditor/Launch.idl b/src/cascadia/TerminalSettingsEditor/Launch.idl index e2a1382e0d..62e6ba9292 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.idl +++ b/src/cascadia/TerminalSettingsEditor/Launch.idl @@ -17,10 +17,12 @@ namespace Microsoft.Terminal.Settings.Editor IInspectable CurrentDefaultProfile; + IInspectable CurrentDefaultTerminal; + IObservableVector DefaultTerminals { get; }; + IInspectable CurrentLaunchMode; IObservableVector LaunchModeList { get; }; - IInspectable CurrentWindowingBehavior; IObservableVector WindowingBehaviorList { get; }; } diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml index ab0b60d186..eed1b60391 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -67,6 +67,16 @@ the MIT License. See LICENSE in the project root for license information. --> + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index c5b305d949..505d56fbc2 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -221,6 +221,14 @@ Profile that opens when clicking the '+' icon or by typing the new tab key binding. A description for what the default profile is and when it's used. + + Default terminal + Header for a drop down that permits the user to select which installed Terminal application will launch when command line tools like CMD are run from the Windows Explorer run box or start menu or anywhere else that they do not already have a graphical window assigned. + + + The terminal application that launches when a command-line application is run without an existing session, like from the Start Menu or Run dialog. + A description to clarify that the dropdown choice for default terminal will tell the operating system which Terminal application (Windows Terminal, the preview build, the legacy inbox window, or a 3rd party one) to use when starting a command line tool like CMD or Powershell that does not already have a window. + Redraw entire screen when display updates Header for a control to toggle the "force full repaint" setting. When enabled, the app renders new content between screen frames. diff --git a/src/host/ConsoleArguments.cpp b/src/host/ConsoleArguments.cpp index 41c07c79ba..7bd34b8392 100644 --- a/src/host/ConsoleArguments.cpp +++ b/src/host/ConsoleArguments.cpp @@ -22,6 +22,7 @@ const std::wstring_view ConsoleArguments::RESIZE_QUIRK = L"--resizeQuirk"; const std::wstring_view ConsoleArguments::WIN32_INPUT_MODE = L"--win32input"; const std::wstring_view ConsoleArguments::FEATURE_ARG = L"--feature"; const std::wstring_view ConsoleArguments::FEATURE_PTY_ARG = L"pty"; +const std::wstring_view ConsoleArguments::COM_SERVER_ARG = L"-Embedding"; std::wstring EscapeArgument(std::wstring_view ac) { @@ -109,6 +110,7 @@ ConsoleArguments::ConsoleArguments(const std::wstring& commandline, _clientCommandline = L""; _vtMode = L""; _headless = false; + _runAsComServer = false; _createServerHandle = true; _serverHandle = 0; _signalHandle = 0; @@ -141,6 +143,7 @@ ConsoleArguments& ConsoleArguments::operator=(const ConsoleArguments& other) _height = other._height; _inheritCursor = other._inheritCursor; _receivedEarlySizeChange = other._receivedEarlySizeChange; + _runAsComServer = other._runAsComServer; } return *this; @@ -446,6 +449,12 @@ void ConsoleArguments::s_ConsumeArg(_Inout_ std::vector& args, _In s_ConsumeArg(args, i); hr = S_OK; } + else if (arg == COM_SERVER_ARG) + { + _runAsComServer = true; + s_ConsumeArg(args, i); + hr = S_OK; + } else if (arg.substr(0, FILEPATH_LEADER_PREFIX.length()) == FILEPATH_LEADER_PREFIX) { // beginning of command line -- includes file path @@ -576,6 +585,11 @@ bool ConsoleArguments::ShouldCreateServerHandle() const return _createServerHandle; } +bool ConsoleArguments::ShouldRunAsComServer() const +{ + return _runAsComServer; +} + HANDLE ConsoleArguments::GetServerHandle() const { return ULongToHandle(_serverHandle); @@ -596,6 +610,11 @@ HANDLE ConsoleArguments::GetVtOutHandle() const return _vtOutHandle; } +std::wstring ConsoleArguments::GetOriginalCommandLine() const +{ + return _commandline; +} + std::wstring ConsoleArguments::GetClientCommandline() const { return _clientCommandline; diff --git a/src/host/ConsoleArguments.hpp b/src/host/ConsoleArguments.hpp index e2e7cad2d1..86c43be056 100644 --- a/src/host/ConsoleArguments.hpp +++ b/src/host/ConsoleArguments.hpp @@ -35,6 +35,7 @@ public: bool InConptyMode() const noexcept; bool IsHeadless() const; bool ShouldCreateServerHandle() const; + bool ShouldRunAsComServer() const; HANDLE GetServerHandle() const; HANDLE GetVtInHandle() const; @@ -43,6 +44,7 @@ public: bool HasSignalHandle() const; HANDLE GetSignalHandle() const; + std::wstring GetOriginalCommandLine() const; std::wstring GetClientCommandline() const; std::wstring GetVtMode() const; bool GetForceV1() const; @@ -74,6 +76,7 @@ public: static const std::wstring_view WIN32_INPUT_MODE; static const std::wstring_view FEATURE_ARG; static const std::wstring_view FEATURE_PTY_ARG; + static const std::wstring_view COM_SERVER_ARG; private: #ifdef UNIT_TESTING @@ -90,7 +93,8 @@ private: const bool createServerHandle, const DWORD serverHandle, const DWORD signalHandle, - const bool inheritCursor) : + const bool inheritCursor, + const bool runAsComServer) : _commandline(commandline), _clientCommandline(clientCommandline), _vtInHandle(vtInHandle), @@ -107,7 +111,8 @@ private: _resizeQuirk(false), _receivedEarlySizeChange{ false }, _originalWidth{ -1 }, - _originalHeight{ -1 } + _originalHeight{ -1 }, + _runAsComServer{ runAsComServer } { } #endif @@ -128,6 +133,7 @@ private: short _width; short _height; + bool _runAsComServer; bool _createServerHandle; DWORD _serverHandle; DWORD _signalHandle; @@ -186,6 +192,7 @@ namespace WEX L"Use Signal Handle: '%ws'\r\n" L"Signal Handle: '0x%x'\r\n", L"Inherit Cursor: '%ws'\r\n", + L"Run As Com Server: '%ws'\r\n", ci.GetClientCommandline().c_str(), s_ToBoolString(ci.HasVtHandles()), ci.GetVtInHandle(), @@ -199,7 +206,8 @@ namespace WEX ci.GetServerHandle(), s_ToBoolString(ci.HasSignalHandle()), ci.GetSignalHandle(), - s_ToBoolString(ci.GetInheritCursor())); + s_ToBoolString(ci.GetInheritCursor()), + s_ToBoolString(ci.ShouldRunAsComServer())); } private: diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp new file mode 100644 index 0000000000..20ac3c6e80 --- /dev/null +++ b/src/host/exe/CConsoleHandoff.cpp @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" + +#include "CConsoleHandoff.h" + +#include "srvinit.h" + +// Routine Description: +// - Helper to duplicate a handle to ourselves so we can keep holding onto it +// after the caller frees the original one. +// Arguments: +// - in - Handle to duplicate +// - out - Where to place the duplicated value +// Return Value: +// - S_OK or Win32 error from `::DuplicateHandle` +static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) +{ + RETURN_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &out, 0, FALSE, DUPLICATE_SAME_ACCESS)); + return S_OK; +} + +// Routine Description: +// - Takes the incoming information from COM and and prepares a console hosting session in this process. +// Arguments: +// - server - Console driver server handle +// - inputEvent - Event already established that we signal when new input data is available in case the driver is waiting on us +// - msg - Portable attach message containing just enough descriptor payload to get us started in servicing it +HRESULT CConsoleHandoff::EstablishHandoff(HANDLE server, + HANDLE inputEvent, + PCCONSOLE_PORTABLE_ATTACH_MSG msg) +try +{ + // Fill the descriptor portion of a fresh api message with the received data. + // The descriptor portion is the "received" packet from the last ask of the driver. + // The other portions are unnecessary as they track the other buffer state, error codes, + // and the return portion of the api message. + // We will re-retrieve the connect information (title, window state, etc.) when the + // new console session begins servicing this. + CONSOLE_API_MSG apiMsg{}; + apiMsg.Descriptor.Identifier.HighPart = msg->IdHighPart; + apiMsg.Descriptor.Identifier.LowPart = msg->IdLowPart; + apiMsg.Descriptor.Process = static_cast(msg->Process); + apiMsg.Descriptor.Object = static_cast(msg->Object); + apiMsg.Descriptor.Function = msg->Function; + apiMsg.Descriptor.InputSize = msg->InputSize; + apiMsg.Descriptor.OutputSize = msg->OutputSize; + + // Duplicate the handles from what we received. + // The contract with COM specifies that any HANDLEs we receive from the caller belong + // to the caller and will be freed when we leave the scope of this method. + // Making our own duplicate copy ensures they hang around in our lifetime. + RETURN_IF_FAILED(_duplicateHandle(server, server)); + RETURN_IF_FAILED(_duplicateHandle(inputEvent, inputEvent)); + + // Now perform the handoff. + RETURN_IF_FAILED(ConsoleEstablishHandoff(server, inputEvent, &apiMsg)); + + return S_OK; +} +CATCH_RETURN(); diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h new file mode 100644 index 0000000000..e2d2e14d89 --- /dev/null +++ b/src/host/exe/CConsoleHandoff.h @@ -0,0 +1,42 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- CConsoleHandoff.h + +Abstract: +- This module receives a console session handoff from the operating system to + an out-of-band, out-of-box console host. + +Author(s): +- Michael Niksa (MiNiksa) 31-Aug-2020 + +--*/ + +#pragma once + +#include "IConsoleHandoff.h" + +#if defined(WT_BRANDING_RELEASE) +#define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" +#elif defined(WT_BRANDING_PREVIEW) +#define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" +#else +#define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" +#endif + +using namespace Microsoft::WRL; + +struct __declspec(uuid(__CLSID_CConsoleHandoff)) + CConsoleHandoff : public RuntimeClass, IConsoleHandoff> +{ +#pragma region IConsoleHandoff + STDMETHODIMP EstablishHandoff(HANDLE server, + HANDLE inputEvent, + PCCONSOLE_PORTABLE_ATTACH_MSG msg); + +#pragma endregion +}; + +CoCreatableClass(CConsoleHandoff); diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index 42bafc2ab3..c43679ab67 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -8,9 +8,10 @@ OpenConsole Application - + + @@ -18,7 +19,8 @@ Create ProgramDatabase - + + @@ -80,7 +82,7 @@ - ..;%(AdditionalIncludeDirectories) + ..;$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) true diff --git a/src/host/exe/Host.EXE.vcxproj.filters b/src/host/exe/Host.EXE.vcxproj.filters index 2c339a909e..3b33223f7e 100644 --- a/src/host/exe/Host.EXE.vcxproj.filters +++ b/src/host/exe/Host.EXE.vcxproj.filters @@ -21,12 +21,18 @@ Header Files + + Header Files + Source Files - + + Source Files + + Source Files diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp new file mode 100644 index 0000000000..d955edfa8d --- /dev/null +++ b/src/host/exe/exemain.cpp @@ -0,0 +1,334 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" + +#include "ConsoleArguments.hpp" +#include "srvinit.h" +#include "CConsoleHandoff.h" +#include "../server/Entrypoints.h" +#include "../interactivity/inc/ServiceLocator.hpp" +#include "../inc/conint.h" + +// Define TraceLogging provider +TRACELOGGING_DEFINE_PROVIDER( + g_ConhostLauncherProvider, + "Microsoft.Windows.Console.Launcher", + // {770aa552-671a-5e97-579b-151709ec0dbd} + (0x770aa552, 0x671a, 0x5e97, 0x57, 0x9b, 0x15, 0x17, 0x09, 0xec, 0x0d, 0xbd), + TraceLoggingOptionMicrosoftTelemetry()); + +// Define a specialization of WRL::Module so we can specify a REGCLS_SINGLEUSE type server. +// We would like to use all the conveniences afforded to us by WRL::Module, but it only +// creates REGCLS_MULTIPLEUSE with no override. This makes an override for it by taking advantage +// of its existing virtual declarations. +#pragma region Single Use Out of Proc Specialization +template +class DefaultOutOfProcModuleWithRegistrationFlag; + +template> +class OutOfProcModuleWithRegistrationFlag : public Microsoft::WRL::Module +{ + using Elsewhere = Module; + using Super = Details::OutOfProcModuleBase; + +public: + STDMETHOD(RegisterCOMObject) + (_In_opt_z_ const wchar_t* serverName, _In_reads_(count) IID* clsids, _In_reads_(count) IClassFactory** factories, _Inout_updates_(count) DWORD* cookies, unsigned int count) + { + return Microsoft::WRL::Details::RegisterCOMObject(serverName, clsids, factories, cookies, count); + } +}; + +template +class DefaultOutOfProcModuleWithRegistrationFlag : public OutOfProcModuleWithRegistrationFlag> +{ +}; +#pragma endregion + +// Holds the wwinmain open until COM tells us there are no more server connections +wil::unique_event _comServerExitEvent; + +static bool ConhostV2ForcedInRegistry() +{ + // If the registry value doesn't exist, or exists and is non-zero, we should default to using the v2 console. + // Otherwise, in the case of an explicit value of 0, we should use the legacy console. + bool fShouldUseConhostV2 = true; + PCSTR pszErrorDescription = nullptr; + bool fIgnoreError = false; + + // open HKCU\Console + wil::unique_hkey hConsoleSubKey; + LONG lStatus = NTSTATUS_FROM_WIN32(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hConsoleSubKey)); + if (ERROR_SUCCESS == lStatus) + { + // now get the value of the ForceV2 reg value, if it exists + DWORD dwValue; + DWORD dwType; + DWORD cbValue = sizeof(dwValue); + lStatus = RegQueryValueExW(hConsoleSubKey.get(), + L"ForceV2", + nullptr, + &dwType, + (PBYTE)&dwValue, + &cbValue); + + if (ERROR_SUCCESS == lStatus && + dwType == REG_DWORD && // response is a DWORD + cbValue == sizeof(dwValue)) // response data exists + { + // Value exists. If non-zero use v2 console. + fShouldUseConhostV2 = dwValue != 0; + } + else + { + pszErrorDescription = "RegQueryValueKey Failed"; + fIgnoreError = lStatus == ERROR_FILE_NOT_FOUND; + } + } + else + { + pszErrorDescription = "RegOpenKey Failed"; + // ignore error caused by RegOpenKey if it's a simple case of the key not being found + fIgnoreError = lStatus == ERROR_FILE_NOT_FOUND; + } + + return fShouldUseConhostV2; +} + +[[nodiscard]] static HRESULT ValidateServerHandle(const HANDLE handle) +{ + // Make sure this is a console file. + FILE_FS_DEVICE_INFORMATION DeviceInformation; + IO_STATUS_BLOCK IoStatusBlock; + NTSTATUS const Status = NtQueryVolumeInformationFile(handle, &IoStatusBlock, &DeviceInformation, sizeof(DeviceInformation), FileFsDeviceInformation); + if (!NT_SUCCESS(Status)) + { + RETURN_NTSTATUS(Status); + } + else if (DeviceInformation.DeviceType != FILE_DEVICE_CONSOLE) + { + return E_INVALIDARG; + } + else + { + return S_OK; + } +} + +static bool ShouldUseLegacyConhost(const ConsoleArguments& args) +{ + if (args.InConptyMode()) + { + return false; + } + + if (args.GetForceV1()) + { + return true; + } + + // Per the documentation in ConhostV2ForcedInRegistry, it checks the value + // of HKCU\Console:ForceV2. If it's *not found* or nonzero, "v2" is forced. + return !ConhostV2ForcedInRegistry(); +} + +[[nodiscard]] static HRESULT ActivateLegacyConhost(const HANDLE handle) +{ + HRESULT hr = S_OK; + + // TraceLog that we're using the legacy console. We won't log new console + // because there's already a count of how many total processes were launched. + // Total - legacy = new console. + // We expect legacy launches to be infrequent enough to not cause an issue. + TraceLoggingWrite(g_ConhostLauncherProvider, "IsLegacyLoaded", TraceLoggingBool(true, "ConsoleLegacy"), TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY)); + + const PCWSTR pszConhostDllName = L"ConhostV1.dll"; + + // Load our implementation, and then Load/Launch the IO thread. + wil::unique_hmodule hConhostBin(LoadLibraryExW(pszConhostDllName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); + if (hConhostBin.get() != nullptr) + { + typedef NTSTATUS (*PFNCONSOLECREATEIOTHREAD)(__in HANDLE Server); + + PFNCONSOLECREATEIOTHREAD pfnConsoleCreateIoThread = (PFNCONSOLECREATEIOTHREAD)GetProcAddress(hConhostBin.get(), "ConsoleCreateIoThread"); + if (pfnConsoleCreateIoThread != nullptr) + { + hr = HRESULT_FROM_NT(pfnConsoleCreateIoThread(handle)); + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } + } + else + { + // setup status error + hr = HRESULT_FROM_WIN32(GetLastError()); + } + + if (SUCCEEDED(hr)) + { + hConhostBin.release(); + } + + return hr; +} + +// Routine Description: +// - Called back when COM says there is nothing left for our server to do and we can tear down. +static void _releaseNotifier() noexcept +{ + _comServerExitEvent.SetEvent(); +} + +// Routine Description: +// - Main entry point for EXE version of console launching. +// This can be used as a debugging/diagnostics tool as well as a method of testing the console without +// replacing the system binary. +// Arguments: +// - hInstance - This module instance pointer is saved for resource lookups. +// - hPrevInstance - Unused pointer to the module instances. See wWinMain definitions @ MSDN for more details. +// - pwszCmdLine - Unused variable. We will look up the command line using GetCommandLineW(). +// - nCmdShow - Unused variable specifying window show/hide state for Win32 mode applications. +// Return value: +// - [[noreturn]] - This function will not return. It will kill the thread we were called from and the console server threads will take over. +int CALLBACK wWinMain( + _In_ HINSTANCE hInstance, + _In_ HINSTANCE /*hPrevInstance*/, + _In_ PWSTR /*pwszCmdLine*/, + _In_ int /*nCmdShow*/) +{ + Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInstance = hInstance; + + ConsoleCheckDebug(); + + // Set up OutOfProc COM server stuff in case we become one. + // WRL Module gets going right before winmain is called, so if we don't + // set this up appropriately... other things using WRL that aren't us + // could get messed up by the singleton module and cause unexpected errors. + _comServerExitEvent.create(); + + // We will use a single use server to ensure that each out-of-box console that + // gets activated to take over a session from the OS console will only be responsible + // for ONE console server session. This ensures that we, as the handoff target, are + // responsible for only one session and one server handle to the driver and we maintain + // the one-to-one relationship between console sessions and servers just like the inbox + // one. Theoretically we could combine them if we had any way of keeping track of all + // of the console state separately per server connection... but that's not how this is + // all designed (so many globals) and it would potentially risk one session's crash + // taking down some completely unrelated command-line clients. + // ---- + // The general flow is... + // 1. The in-box console looks up the registered delegation console + // 2. An OpenConsole.exe is typically found which is a newer version of the + // same code that is in-box and may have more bug fixes or features (especially + // an improved VT dialect or something of that ilk). + // 3. By activating the registered CLSID, the in-box console will be starting `openconsole.exe -Embedding` + // through the OutOfProc COM server infrastructure. + // 4. The `openconsole.exe -Embedding` that starts will come through right here and register + // `CConsoleHandoff` to accept ONE connection. + // 5. The in-box console will then receive an `IConsoleHandoff` to this `CConsoleHandoff` and the registration + // immediately expires, letting no one else in. The next caller will start another new `openconsole.exe -Embedding` process. + // 6. The in-box console invokes the handoff method on the interface and it transfers some data into `CConsoleHandoff` + // of the `OpenConsole.exe` which will then stand up its own server IO thread and handle all console server session + // messages going forward. + // 7. The out-of-box `OpenConsole.exe` can then attempt to lookup and invoke a `CTerminalHandoff` to ask a registered + // Terminal to become the UI. This OpenConsole.exe will put itself in PTY mode and let the Terminal handle user interaction. + auto& module = OutOfProcModuleWithRegistrationFlag::Create(&_releaseNotifier); + + // Register Trace provider by GUID + TraceLoggingRegister(g_ConhostLauncherProvider); + + // Pass command line and standard handles at this point in time as + // potential preferences for execution that were passed on process creation. + ConsoleArguments args(GetCommandLineW(), + GetStdHandle(STD_INPUT_HANDLE), + GetStdHandle(STD_OUTPUT_HANDLE)); + + HRESULT hr = args.ParseCommandline(); + if (SUCCEEDED(hr)) + { + // Only try to register as a handoff target if we are NOT a part of Windows. +#ifndef __INSIDE_WINDOWS + bool defAppEnabled = false; + if (args.ShouldRunAsComServer() && SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(defAppEnabled)) && defAppEnabled) + { + try + { + // OK we have to do this here and not in another method because + // we would either have to store the module ref above in some accessible + // variable (which would be awful because of the gigantic template name) + // or we would have to come up with some creativity to extract it out + // of the singleton module base without accidentally having WRL + // think we're recreating it (and then assert because it's already created.) + // + // Also this is all a problem because the decrementing count of used objects + // in this module in WRL::Module base doesn't null check the release notifier + // callback function in the OutOfProc variant in the 18362 SDK. So if anything + // else uses WRL directly or indirectly, it'll crash if the refcount + // ever hits 0. + // It does in the 19041 SDK so this can be cleaned into its own class if + // we ever build with 19041 or later. + auto comScope{ wil::CoInitializeEx(COINIT_MULTITHREADED) }; + + RETURN_IF_FAILED(module.RegisterObjects()); + _comServerExitEvent.wait(); + RETURN_IF_FAILED(module.UnregisterObjects()); + } + CATCH_RETURN() + } + else +#endif + { + if (ShouldUseLegacyConhost(args)) + { + if (args.ShouldCreateServerHandle()) + { + hr = E_INVALIDARG; + } + else + { + hr = ValidateServerHandle(args.GetServerHandle()); + + if (SUCCEEDED(hr)) + { + hr = ActivateLegacyConhost(args.GetServerHandle()); + } + } + } + else + { + if (args.ShouldCreateServerHandle()) + { + hr = Entrypoints::StartConsoleForCmdLine(args.GetClientCommandline().c_str(), &args); + } + else + { + hr = ValidateServerHandle(args.GetServerHandle()); + + if (SUCCEEDED(hr)) + { + hr = Entrypoints::StartConsoleForServerHandle(args.GetServerHandle(), &args); + } + } + } + } + } + + // Unregister Tracelogging + TraceLoggingUnregister(g_ConhostLauncherProvider); + + // Only do this if startup was successful. Otherwise, this will leave conhost.exe running with no hosted application. + if (SUCCEEDED(hr)) + { + // Since the lifetime of conhost.exe is inextricably tied to the lifetime of its client processes we set our process + // shutdown priority to zero in order to effectively opt out of shutdown process enumeration. Conhost will exit when + // all of its client processes do. + SetProcessShutdownParameters(0, 0); + + ExitThread(hr); + } + + return hr; +} diff --git a/src/host/exe/sources b/src/host/exe/sources index a827864473..1071fdb5c1 100644 --- a/src/host/exe/sources +++ b/src/host/exe/sources @@ -32,7 +32,8 @@ CETCOMPAT=1 SOURCES = \ $(SOURCES) \ - ..\exemain.cpp \ + .\CConsoleHandoff.cpp \ + .\exemain.cpp \ ..\res.rc \ # ------------------------------------- diff --git a/src/host/exemain.cpp b/src/host/exemain.cpp deleted file mode 100644 index 8d338ff48e..0000000000 --- a/src/host/exemain.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "precomp.h" - -#include "ConsoleArguments.hpp" -#include "srvinit.h" -#include "../server/Entrypoints.h" -#include "../interactivity/inc/ServiceLocator.hpp" - -// Define TraceLogging provider -TRACELOGGING_DEFINE_PROVIDER( - g_ConhostLauncherProvider, - "Microsoft.Windows.Console.Launcher", - // {770aa552-671a-5e97-579b-151709ec0dbd} - (0x770aa552, 0x671a, 0x5e97, 0x57, 0x9b, 0x15, 0x17, 0x09, 0xec, 0x0d, 0xbd), - TraceLoggingOptionMicrosoftTelemetry()); - -static bool ConhostV2ForcedInRegistry() -{ - // If the registry value doesn't exist, or exists and is non-zero, we should default to using the v2 console. - // Otherwise, in the case of an explicit value of 0, we should use the legacy console. - bool fShouldUseConhostV2 = true; - PCSTR pszErrorDescription = nullptr; - bool fIgnoreError = false; - - // open HKCU\Console - wil::unique_hkey hConsoleSubKey; - LONG lStatus = NTSTATUS_FROM_WIN32(RegOpenKeyExW(HKEY_CURRENT_USER, L"Console", 0, KEY_READ, &hConsoleSubKey)); - if (ERROR_SUCCESS == lStatus) - { - // now get the value of the ForceV2 reg value, if it exists - DWORD dwValue; - DWORD dwType; - DWORD cbValue = sizeof(dwValue); - lStatus = RegQueryValueExW(hConsoleSubKey.get(), - L"ForceV2", - nullptr, - &dwType, - (PBYTE)&dwValue, - &cbValue); - - if (ERROR_SUCCESS == lStatus && - dwType == REG_DWORD && // response is a DWORD - cbValue == sizeof(dwValue)) // response data exists - { - // Value exists. If non-zero use v2 console. - fShouldUseConhostV2 = dwValue != 0; - } - else - { - pszErrorDescription = "RegQueryValueKey Failed"; - fIgnoreError = lStatus == ERROR_FILE_NOT_FOUND; - } - } - else - { - pszErrorDescription = "RegOpenKey Failed"; - // ignore error caused by RegOpenKey if it's a simple case of the key not being found - fIgnoreError = lStatus == ERROR_FILE_NOT_FOUND; - } - - return fShouldUseConhostV2; -} - -[[nodiscard]] static HRESULT ValidateServerHandle(const HANDLE handle) -{ - // Make sure this is a console file. - FILE_FS_DEVICE_INFORMATION DeviceInformation; - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS const Status = NtQueryVolumeInformationFile(handle, &IoStatusBlock, &DeviceInformation, sizeof(DeviceInformation), FileFsDeviceInformation); - if (!NT_SUCCESS(Status)) - { - RETURN_NTSTATUS(Status); - } - else if (DeviceInformation.DeviceType != FILE_DEVICE_CONSOLE) - { - return E_INVALIDARG; - } - else - { - return S_OK; - } -} - -static bool ShouldUseLegacyConhost(const ConsoleArguments& args) -{ - if (args.InConptyMode()) - { - return false; - } - - if (args.GetForceV1()) - { - return true; - } - - // Per the documentation in ConhostV2ForcedInRegistry, it checks the value - // of HKCU\Console:ForceV2. If it's *not found* or nonzero, "v2" is forced. - return !ConhostV2ForcedInRegistry(); -} - -[[nodiscard]] static HRESULT ActivateLegacyConhost(const HANDLE handle) -{ - HRESULT hr = S_OK; - - // TraceLog that we're using the legacy console. We won't log new console - // because there's already a count of how many total processes were launched. - // Total - legacy = new console. - // We expect legacy launches to be infrequent enough to not cause an issue. - TraceLoggingWrite(g_ConhostLauncherProvider, "IsLegacyLoaded", TraceLoggingBool(true, "ConsoleLegacy"), TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY)); - - const PCWSTR pszConhostDllName = L"ConhostV1.dll"; - - // Load our implementation, and then Load/Launch the IO thread. - wil::unique_hmodule hConhostBin(LoadLibraryExW(pszConhostDllName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); - if (hConhostBin.get() != nullptr) - { - typedef NTSTATUS (*PFNCONSOLECREATEIOTHREAD)(__in HANDLE Server); - - PFNCONSOLECREATEIOTHREAD pfnConsoleCreateIoThread = (PFNCONSOLECREATEIOTHREAD)GetProcAddress(hConhostBin.get(), "ConsoleCreateIoThread"); - if (pfnConsoleCreateIoThread != nullptr) - { - hr = HRESULT_FROM_NT(pfnConsoleCreateIoThread(handle)); - } - else - { - hr = HRESULT_FROM_WIN32(GetLastError()); - } - } - else - { - // setup status error - hr = HRESULT_FROM_WIN32(GetLastError()); - } - - if (SUCCEEDED(hr)) - { - hConhostBin.release(); - } - - return hr; -} - -// Routine Description: -// - Main entry point for EXE version of console launching. -// This can be used as a debugging/diagnostics tool as well as a method of testing the console without -// replacing the system binary. -// Arguments: -// - hInstance - This module instance pointer is saved for resource lookups. -// - hPrevInstance - Unused pointer to the module instances. See wWinMain definitions @ MSDN for more details. -// - pwszCmdLine - Unused variable. We will look up the command line using GetCommandLineW(). -// - nCmdShow - Unused variable specifying window show/hide state for Win32 mode applications. -// Return value: -// - [[noreturn]] - This function will not return. It will kill the thread we were called from and the console server threads will take over. -int CALLBACK wWinMain( - _In_ HINSTANCE hInstance, - _In_ HINSTANCE /*hPrevInstance*/, - _In_ PWSTR /*pwszCmdLine*/, - _In_ int /*nCmdShow*/) -{ - Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInstance = hInstance; - - ConsoleCheckDebug(); - - // Register Trace provider by GUID - TraceLoggingRegister(g_ConhostLauncherProvider); - - // Pass command line and standard handles at this point in time as - // potential preferences for execution that were passed on process creation. - ConsoleArguments args(GetCommandLineW(), - GetStdHandle(STD_INPUT_HANDLE), - GetStdHandle(STD_OUTPUT_HANDLE)); - - HRESULT hr = args.ParseCommandline(); - if (SUCCEEDED(hr)) - { - if (ShouldUseLegacyConhost(args)) - { - if (args.ShouldCreateServerHandle()) - { - hr = E_INVALIDARG; - } - else - { - hr = ValidateServerHandle(args.GetServerHandle()); - - if (SUCCEEDED(hr)) - { - hr = ActivateLegacyConhost(args.GetServerHandle()); - } - } - } - else - { - if (args.ShouldCreateServerHandle()) - { - hr = Entrypoints::StartConsoleForCmdLine(args.GetClientCommandline().c_str(), &args); - } - else - { - hr = ValidateServerHandle(args.GetServerHandle()); - - if (SUCCEEDED(hr)) - { - hr = Entrypoints::StartConsoleForServerHandle(args.GetServerHandle(), &args); - } - } - } - } - - // Unregister Tracelogging - TraceLoggingUnregister(g_ConhostLauncherProvider); - - // Only do this if startup was successful. Otherwise, this will leave conhost.exe running with no hosted application. - if (SUCCEEDED(hr)) - { - // Since the lifetime of conhost.exe is inextricably tied to the lifetime of its client processes we set our process - // shutdown priority to zero in order to effectively opt out of shutdown process enumeration. Conhost will exit when - // all of its client processes do. - SetProcessShutdownParameters(0, 0); - - ExitThread(hr); - } - - return hr; -} diff --git a/src/host/globals.h b/src/host/globals.h index 2bcfd2859e..4edf2bbc45 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -73,6 +73,7 @@ public: bool handoffTarget = false; std::optional handoffConsoleClsid; + std::optional handoffTerminalClsid; #ifdef UNIT_TESTING void EnableConptyModeForTests(std::unique_ptr vtRenderEngine); diff --git a/src/host/host-common.vcxitems b/src/host/host-common.vcxitems index 0361b6f82b..190eef7920 100644 --- a/src/host/host-common.vcxitems +++ b/src/host/host-common.vcxitems @@ -121,7 +121,7 @@ - %(AdditionalIncludeDirectories) + $(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) diff --git a/src/host/lib/hostlib.vcxproj b/src/host/lib/hostlib.vcxproj index adc1124195..fb83977af9 100644 --- a/src/host/lib/hostlib.vcxproj +++ b/src/host/lib/hostlib.vcxproj @@ -6,7 +6,7 @@ hostlib Host ConhostV2Lib - StaticLibrary + StaticLibrary diff --git a/src/host/lib/hostlib.vcxproj.filters b/src/host/lib/hostlib.vcxproj.filters index bd95d73516..e8877f96c7 100644 --- a/src/host/lib/hostlib.vcxproj.filters +++ b/src/host/lib/hostlib.vcxproj.filters @@ -30,9 +30,6 @@ Source Files - - Source Files - Source Files @@ -162,9 +159,6 @@ Source Files - - Source Files - Source Files @@ -183,6 +177,12 @@ Source Files + + Source Files + + + Source Files + @@ -254,9 +254,6 @@ Header Files - - Header Files - Header Files @@ -332,9 +329,6 @@ Header Files - - Header Files - Header Files @@ -353,5 +347,17 @@ Header Files + + Header Files + + + Header Files + + + Header Files + - + + + + \ No newline at end of file diff --git a/src/host/proxy/Host.Proxy.vcxproj b/src/host/proxy/Host.Proxy.vcxproj index 4124661157..9d479599e4 100644 --- a/src/host/proxy/Host.Proxy.vcxproj +++ b/src/host/proxy/Host.Proxy.vcxproj @@ -1,17 +1,14 @@ - {E437B604-3E98-4F40-A927-E173E818EA4B} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} Win32Proj openconsoleproxy OpenConsoleProxy OpenConsoleProxy - Utility + DynamicLibrary - - - + REGISTER_PROXY_DLL;%(PreprocessorDefinitions) NotUsing + + OpenConsoleProxy.def + diff --git a/src/host/proxy/Host.Proxy.vcxproj.filters b/src/host/proxy/Host.Proxy.vcxproj.filters index 103c008ebe..df6bcbd10c 100644 --- a/src/host/proxy/Host.Proxy.vcxproj.filters +++ b/src/host/proxy/Host.Proxy.vcxproj.filters @@ -14,11 +14,31 @@ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + - + + Header Files + + Header Files @@ -26,5 +46,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/host/proxy/IConsoleHandoff.idl b/src/host/proxy/IConsoleHandoff.idl index f964698527..067eb0efa8 100644 --- a/src/host/proxy/IConsoleHandoff.idl +++ b/src/host/proxy/IConsoleHandoff.idl @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import "oaidl.idl"; import "ocidl.idl"; @@ -24,3 +27,4 @@ typedef const CONSOLE_PORTABLE_ATTACH_MSG* PCCONSOLE_PORTABLE_ATTACH_MSG; [in, system_handle(sh_event)] HANDLE inputEvent, [in, ref] PCCONSOLE_PORTABLE_ATTACH_MSG msg); }; + diff --git a/src/host/proxy/ITerminalHandoff.idl b/src/host/proxy/ITerminalHandoff.idl new file mode 100644 index 0000000000..79c356908b --- /dev/null +++ b/src/host/proxy/ITerminalHandoff.idl @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import "oaidl.idl"; +import "ocidl.idl"; + +[ + object, + uuid(FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74) +] interface ITerminalHandoff : IUnknown +{ + HRESULT EstablishPtyHandoff([in, system_handle(sh_pipe)] HANDLE in, + [in, system_handle(sh_pipe)] HANDLE out, + [in, system_handle(sh_pipe)] HANDLE signal, + [in, system_handle(sh_process)] HANDLE client); +}; diff --git a/src/host/proxy/OpenConsoleProxy.def b/src/host/proxy/OpenConsoleProxy.def new file mode 100644 index 0000000000..e41123ab14 --- /dev/null +++ b/src/host/proxy/OpenConsoleProxy.def @@ -0,0 +1,8 @@ +LIBRARY OpenConsoleProxy + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + GetProxyDllInfo diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 88a7d85c96..ad43d06ed5 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -23,6 +23,7 @@ #include "renderData.hpp" #include "../renderer/base/renderer.hpp" +#include "ITerminalHandoff.h" #include "../inc/conint.h" #include "../propslib/DelegationConfig.hpp" @@ -60,6 +61,10 @@ try { Globals.handoffConsoleClsid = delegationClsid; } + if (SUCCEEDED(DelegationConfig::s_GetDefaultTerminalId(delegationClsid))) + { + Globals.handoffTerminalClsid = delegationClsid; + } } // Removed allocation of scroll buffer here. @@ -265,20 +270,53 @@ void ConsoleCheckDebug() #endif } -[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) +// Routine Description: +// - Sets up the main driver message packet (I/O) processing +// thread that will handle all client requests from all +// attached command-line applications for the duration +// of this console server session. +// - The optional arguments are only used when receiving a handoff +// from another console server (typically in-box to the Windows OS image) +// that has already started processing the console session. +// They will be blank and generated internally by this method if this is the first +// console server starting in response to a client startup or ConPTY setup +// request. +// Arguments: +// - Server - Handle to the console driver that represents +// our server side of the connection. +// - args - Command-line arguments from starting this console host +// that may affect the way we host the session. +// - driverInputEvent - (Optional) Event registered with the console driver +// that we will use to wake up input read requests that +// are blocked because they came in when we had no input ready. +// - connectMessage - (Optional) A message received from a connecting client +// by another console server that is being passed off to us as a part of +// the handoff strategy. +HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, + const ConsoleArguments* const args, + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage) { auto& g = ServiceLocator::LocateGlobals(); RETURN_IF_FAILED(ConsoleServerInitialization(Server, args)); RETURN_IF_FAILED(g.hConsoleInputInitEvent.create(wil::EventOptions::None)); - // Set up and tell the driver about the input available event. - RETURN_IF_FAILED(g.hInputEvent.create(wil::EventOptions::ManualReset)); + if (driverInputEvent != INVALID_HANDLE_VALUE) + { + // Store the driver input event. It's already been told that it exists by whomever started us. + g.hInputEvent.reset(driverInputEvent); + } + else + { + // Set up and tell the driver about the input available event. + RETURN_IF_FAILED(g.hInputEvent.create(wil::EventOptions::ManualReset)); - CD_IO_SERVER_INFORMATION ServerInformation; - ServerInformation.InputAvailableEvent = ServiceLocator::LocateGlobals().hInputEvent.get(); - RETURN_IF_FAILED(g.pDeviceComm->SetServerInformation(&ServerInformation)); + CD_IO_SERVER_INFORMATION ServerInformation; + ServerInformation.InputAvailableEvent = ServiceLocator::LocateGlobals().hInputEvent.get(); + RETURN_IF_FAILED(g.pDeviceComm->SetServerInformation(&ServerInformation)); + } - HANDLE const hThread = CreateThread(nullptr, 0, ConsoleIoThread, nullptr, 0, nullptr); + HANDLE const hThread = CreateThread(nullptr, 0, ConsoleIoThread, connectMessage, 0, nullptr); RETURN_HR_IF(E_HANDLE, hThread == nullptr); LOG_IF_WIN32_BOOL_FALSE(CloseHandle(hThread)); // The thread will run on its own and close itself. Free the associated handle. @@ -295,6 +333,117 @@ void ConsoleCheckDebug() return S_OK; } +// Routine Description: +// - Accepts a console server session from another console server +// most commonly from the operating system in-box console to +// a more-up-to-date and out-of-band delivered one. +// Arguments: +// - Server - Handle to the console driver that represents our server +// side of hosting the console session +// - driverInputEvent - Handle to an event already registered with the +// driver that clients will implicitly wait on when we don't have +// any input to return in the queue when a request is made and is +// signaled to unblock them when input finally arrives. +// - connectMessage - A console driver/server message as received +// by the previous console server for us to finish processing in +// order to complete the client's initial connection and store +// all necessary callback information for all subsequent API calls. +// Return Value: +// - COM errors, registry errors, pipe errors, handle manipulation errors, +// errors from the creating the thread for the +// standard IO thread loop for the server to process messages +// from the driver... or an S_OK success. +[[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage) +try +{ + auto& g = ServiceLocator::LocateGlobals(); + g.handoffTarget = true; + + IID delegationClsid; + if (SUCCEEDED(DelegationConfig::s_GetDefaultConsoleId(delegationClsid))) + { + g.handoffConsoleClsid = delegationClsid; + } + if (SUCCEEDED(DelegationConfig::s_GetDefaultTerminalId(delegationClsid))) + { + g.handoffTerminalClsid = delegationClsid; + } + + if (!g.handoffTerminalClsid) + { + return E_NOT_SET; + } + + wil::unique_handle signalPipeTheirSide; + wil::unique_handle signalPipeOurSide; + + wil::unique_handle inPipeTheirSide; + wil::unique_handle inPipeOurSide; + + wil::unique_handle outPipeTheirSide; + wil::unique_handle outPipeOurSide; + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + // Mark inheritable for signal handle when creating. It'll have the same value on the other side. + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = nullptr; + + RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(signalPipeOurSide.addressof(), signalPipeTheirSide.addressof(), nullptr, 0)); + RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(signalPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); + + RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(inPipeOurSide.addressof(), inPipeTheirSide.addressof(), nullptr, 0)); + RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(inPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); + + RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(outPipeTheirSide.addressof(), outPipeOurSide.addressof(), nullptr, 0)); + RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(outPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); + + wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, TRUE, static_cast(connectMessage->Descriptor.Process)) }; + RETURN_LAST_ERROR_IF_NULL(clientProcess.get()); + + ::Microsoft::WRL::ComPtr handoff; + + RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); + + RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(), + outPipeTheirSide.get(), + signalPipeTheirSide.get(), + clientProcess.get())); + + inPipeTheirSide.release(); + outPipeTheirSide.release(); + signalPipeTheirSide.release(); + + const auto commandLine = fmt::format(FMT_COMPILE(L" --headless --signal {:#x}"), (int64_t)signalPipeOurSide.release()); + + ConsoleArguments consoleArgs(commandLine, inPipeOurSide.release(), outPipeOurSide.release()); + RETURN_IF_FAILED(consoleArgs.ParseCommandline()); + + return ConsoleCreateIoThread(Server, &consoleArgs, driverInputEvent, connectMessage); +} +CATCH_RETURN() + +// Routine Description: +// - Creates the I/O thread for handling and processing messages from the console driver +// as the server side of a console session. +// - This entrypoint is for all start scenarios that are not receiving a hand-off +// from another console server. For example, getting started by kernelbase.dll from +// the operating system as a client application realizes it needs a console server, +// getting started to be a ConPTY host inside the OS, or being double clicked either +// inside the OS as `conhost.exe` or outside as `OpenConsole.exe`. +// Arguments: +// - Server - The server side handle to the console driver to let us pick up messages to process for the clients. +// - args - A structure of arguments that may have been passed in on the command-line, typically only used to control the ConPTY configuration. +// Return Value: +// - S_OK if the thread starts up correctly or any number of thread, registry, windowing, or just about any other +// failure that could possibly occur during console server initialization. +[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) +{ + return ConsoleCreateIoThread(Server, args, INVALID_HANDLE_VALUE, nullptr); +} + #define SYSTEM_ROOT (L"%SystemRoot%") #define SYSTEM_ROOT_LENGTH (sizeof(SYSTEM_ROOT) - sizeof(WCHAR)) @@ -662,10 +811,10 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, // - This routine is the main one in the console server IO thread. // - It reads IO requests submitted by clients through the driver, services and completes them in a loop. // Arguments: -// - +// - lpParameter - PCONSOLE_API_MSG being handed off to us from the previous I/O. // Return Value: // - This routine never returns. The process exits when no more references or clients exist. -DWORD WINAPI ConsoleIoThread(LPVOID /*lpParameter*/) +DWORD WINAPI ConsoleIoThread(LPVOID lpParameter) { auto& globals = ServiceLocator::LocateGlobals(); @@ -674,6 +823,15 @@ DWORD WINAPI ConsoleIoThread(LPVOID /*lpParameter*/) ReceiveMsg._pDeviceComm = globals.pDeviceComm; PCONSOLE_API_MSG ReplyMsg = nullptr; + // If we were given a message on startup, process that in our context and then continue with the IO loop normally. + if (lpParameter) + { + ReceiveMsg = *(PCONSOLE_API_MSG)lpParameter; + ReceiveMsg._pApiRoutines = &globals.api; + ReceiveMsg._pDeviceComm = globals.pDeviceComm; + IoSorter::ServiceIoOperation(&ReceiveMsg, &ReplyMsg); + } + bool fShouldExit = false; while (!fShouldExit) { diff --git a/src/host/srvinit.h b/src/host/srvinit.h index 58fbb3035c..3b2725a390 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -28,4 +28,8 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, [[nodiscard]] bool ConsoleConnectionDeservesVisibleWindow(PCONSOLE_API_CONNECTINFO p); +[[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage); + void ConsoleCheckDebug(); diff --git a/src/host/ut_host/ConsoleArgumentsTests.cpp b/src/host/ut_host/ConsoleArgumentsTests.cpp index 7a23a5995e..b210899b76 100644 --- a/src/host/ut_host/ConsoleArgumentsTests.cpp +++ b/src/host/ut_host/ConsoleArgumentsTests.cpp @@ -81,7 +81,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe \"this is the commandline\""; @@ -101,7 +102,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless \"--vtmode bar this is the commandline\""; @@ -121,7 +123,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless --server 0x4 this is the commandline"; @@ -141,7 +144,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() false, // createServerHandle 0x4, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\t--vtmode\txterm\tthis\tis\tthe\tcommandline"; @@ -161,7 +165,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\\ foo\\ --outpipe\\ bar\\ this\\ is\\ the\\ commandline"; @@ -181,7 +186,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless\\\tfoo\\\t--outpipe\\\tbar\\\tthis\\\tis\\\tthe\\\tcommandline"; @@ -201,7 +207,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode a\\\\\\\\\"b c\" d e"; @@ -221,7 +228,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe this is the commandline"; @@ -241,7 +249,8 @@ void ConsoleArgumentsTests::ArgSplittingTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? } @@ -266,7 +275,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe foo"; @@ -286,7 +296,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe foo -- bar"; @@ -306,7 +317,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode foo foo -- bar"; @@ -326,7 +338,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe console --vtmode foo foo -- bar"; @@ -346,7 +359,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe console --vtmode foo --outpipe foo -- bar"; @@ -366,7 +380,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode foo -- --outpipe foo bar"; @@ -386,7 +401,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode -- --headless bar"; @@ -406,7 +422,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --"; @@ -426,7 +443,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe"; @@ -446,7 +464,8 @@ void ConsoleArgumentsTests::ClientCommandlineTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? } @@ -471,7 +490,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --server 0x4"; @@ -491,7 +511,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe 0x4 0x8"; @@ -511,7 +532,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --server 0x4 0x8"; @@ -531,7 +553,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe 0x4 --server 0x8"; @@ -551,7 +574,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --server 0x4 --server 0x8"; @@ -571,7 +595,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe 0x4 -ForceV1"; @@ -591,7 +616,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe -ForceV1"; @@ -611,7 +637,8 @@ void ConsoleArgumentsTests::LegacyFormatsTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? } @@ -660,7 +687,8 @@ void ConsoleArgumentsTests::CombineVtPipeHandleTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --vtmode xterm-256color"; @@ -680,7 +708,8 @@ void ConsoleArgumentsTests::CombineVtPipeHandleTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? } @@ -715,7 +744,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width 120"; @@ -735,7 +765,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --height 30"; @@ -755,7 +786,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width 0"; @@ -775,7 +807,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width -1"; @@ -795,7 +828,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --width foo"; @@ -815,7 +849,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --width 2foo"; @@ -835,7 +870,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --width 65535"; @@ -855,7 +891,8 @@ void ConsoleArgumentsTests::InitialSizeTests() true, // createServerHandle 0ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? } @@ -880,7 +917,8 @@ void ConsoleArgumentsTests::HeadlessArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless 0x4"; @@ -900,7 +938,8 @@ void ConsoleArgumentsTests::HeadlessArgTests() false, // createServerHandle 4ul, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --headless --headless"; @@ -920,7 +959,8 @@ void ConsoleArgumentsTests::HeadlessArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe -- foo.exe --headless"; @@ -940,7 +980,8 @@ void ConsoleArgumentsTests::HeadlessArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? } @@ -969,7 +1010,8 @@ void ConsoleArgumentsTests::SignalHandleTests() false, // createServerHandle 4ul, // serverHandle 8ul, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --server 0x4 --signal ASDF"; @@ -989,7 +1031,8 @@ void ConsoleArgumentsTests::SignalHandleTests() false, // createServerHandle 4ul, // serverHandle 0ul, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --signal --server 0x4"; @@ -1009,7 +1052,8 @@ void ConsoleArgumentsTests::SignalHandleTests() true, // createServerHandle 0ul, // serverHandle 0ul, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? } @@ -1038,7 +1082,8 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --feature tty"; ArgTestsRunner(L"#2 Error case, pass an unsupported feature", @@ -1057,7 +1102,8 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature pty"; @@ -1077,7 +1123,8 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer true); // successful parse? commandline = L"conhost.exe --feature pty --feature tty"; @@ -1097,7 +1144,8 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature"; @@ -1117,7 +1165,8 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? commandline = L"conhost.exe --feature pty --feature --signal foo"; @@ -1137,6 +1186,7 @@ void ConsoleArgumentsTests::FeatureArgTests() true, // createServerHandle 0, // serverHandle 0, // signalHandle - false), // inheritCursor + false, // inheritCursor + false), // runAsComServer false); // successful parse? } diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index ac312a23e7..f9570d6dde 100644 --- a/src/internal/stubs.cpp +++ b/src/internal/stubs.cpp @@ -32,6 +32,8 @@ void EdpPolicy::AuditClipboard(const std::wstring_view /*destinationName*/) noex [[nodiscard]] HRESULT DefaultApp::CheckDefaultAppPolicy(bool& isEnabled) noexcept { - isEnabled = false; + // True so propsheet will show configuration options but be sure that + // the open one won't attempt handoff from double click of OpenConsole.exe + isEnabled = true; return S_OK; -} \ No newline at end of file +} diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 03ca357982..58909c7d95 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -146,6 +146,19 @@ static bool _shouldAttemptHandoff(const Globals& globals, const CONSOLE_INFORMATION& gci, CONSOLE_API_CONNECTINFO& cac) { +#ifndef __INSIDE_WINDOWS + + UNREFERENCED_PARAMETER(globals); + UNREFERENCED_PARAMETER(gci); + UNREFERENCED_PARAMETER(cac); + + // If we are outside of Windows, do not attempt a handoff + // to another target as handoff is an inbox escape mechanism + // to get to this copy! + return false; + +#else + // This console is already initialized. Do not // attempt handoff to another one. // Note you can have a non-attach secondary connect for a child process @@ -209,6 +222,7 @@ static bool _shouldAttemptHandoff(const Globals& globals, } return true; +#endif } // Routine Description: From ea3e56db8134bad477ce15fc82a385820ee8723b Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Fri, 26 Mar 2021 15:11:08 -0700 Subject: [PATCH 04/56] Add some read and write locks around pattern tree manipulation (#9618) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have been seeing some crashes (#9410) originating from a use-after-free or a double-free in the renderer. The renderer is iterating over the dirty rects from the render engine¹ and the rect list is being freed out from under it. Things like this are usually the result of somebody manipulating the renderer's state outside of lock. Therefore, this pull request introduces some targeted locking fixes around manipulation of the pattern buffer (which, in turn, changes the renderer state.) ¹ This was not a problem until #8621, which made the renderer return a span instead of a copy for the list of dirty rects. ## Validation I ran Terminal under App Verifier, and introduced a manul delay (under lock) in the renderer such that the invalid map would definitely have been invalidated between the renderer taking the lock and the renderer handling the frame. AppVerif failed us without these locking changes, and did not do so once they were introduced. Closes #9410. --- src/cascadia/TerminalControl/TermControl.cpp | 24 ++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 08b78ec84d..2f7fa3ad1f 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -1815,7 +1815,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Clear the regex pattern tree so the renderer does not try to render them while scrolling - _terminal->ClearPatternTree(); + { + // We're taking the lock here instead of in ClearPatternTree because ClearPatternTree is + // sometimes called from an already-locked context. Here, we are sure we are not + // already under lock (since it is not an internal scroll bar update) + // TODO GH#9617: refine locking around pattern tree + auto lock = _terminal->LockForWriting(); + _terminal->ClearPatternTree(); + } const auto newValue = static_cast(args.NewValue()); @@ -2434,6 +2441,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Clear the regex pattern tree so the renderer does not try to render them while scrolling + // We're **NOT** taking the lock here unlike _ScrollbarChangeHandler because + // we are already under lock (since this usually happens as a result of writing). + // TODO GH#9617: refine locking around pattern tree _terminal->ClearPatternTree(); _scrollPositionChangedHandlers(viewTop, viewHeight, bufferSize); @@ -3334,8 +3344,13 @@ namespace winrt::Microsoft::Terminal::Control::implementation _lastHoveredCell = terminalPosition; + uint16_t newId{ 0u }; + // we can't use auto here because we're pre-declaring newInterval. + decltype(_terminal->GetHyperlinkIntervalFromPosition(COORD{})) newInterval{ std::nullopt }; if (terminalPosition.has_value()) { + auto lock = _terminal->LockForReading(); // Lock for the duration of our reads. + const auto uri = _terminal->GetHyperlinkAtPosition(*terminalPosition); if (!uri.empty()) { @@ -3361,15 +3376,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation OverlayCanvas().SetLeft(HyperlinkTooltipBorder(), (locationInDIPs.x() - SwapChainPanel().ActualOffset().x)); OverlayCanvas().SetTop(HyperlinkTooltipBorder(), (locationInDIPs.y() - SwapChainPanel().ActualOffset().y)); } - } - const uint16_t newId = terminalPosition.has_value() ? _terminal->GetHyperlinkIdAtPosition(*terminalPosition) : 0u; - const auto newInterval = terminalPosition.has_value() ? _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition) : std::nullopt; + newId = _terminal->GetHyperlinkIdAtPosition(*terminalPosition); + newInterval = _terminal->GetHyperlinkIntervalFromPosition(*terminalPosition); + } // If the hyperlink ID changed or the interval changed, trigger a redraw all // (so this will happen both when we move onto a link and when we move off a link) if (newId != _lastHoveredId || (newInterval != _lastHoveredInterval)) { + auto lock = _terminal->LockForWriting(); _lastHoveredId = newId; _lastHoveredInterval = newInterval; _renderEngine->UpdateHyperlinkHoveredId(newId); From 12275c85995d36afab94022a838452631979e084 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Mon, 29 Mar 2021 07:23:30 -0700 Subject: [PATCH 05/56] Add a Fuzzing configuration and a version of conhost that can be fuzzed (#9604) This commit introduces a new build configuration, "Fuzzing", which enables the new address sanitizer (shipped in VS 16.9) and code coverage over the entire solution. Only a small subset of projects (those comprising original conhost, right now) are selected to build in this configuration, and even then only in Fuzzing|x64. It also adds a fuzzing-adapted build of conhost, which makes no server connections and handles no client applications. To do this, I've replicated a bit of the console startup routine into fuzzmain.cpp and made up some fake data. This is the bare minimum required to boot up Win32 interactivity (or VT interactivity!) and pretend that a process has connected. If we don't pretend that a process has connected, "conhost" will exit immediately. If we don't forge the process list, conhost will exit. If we can't provide a server handle, we can't provide a "device comm". Minor changes were necessary to server/host such that they would accept a preexisting "device comm". We use this new behavior to provide a "null" one that only hangs up threads and otherwise responds to requests successfully. This fuzzing-adapted build links LLVM's libFuzzer, which is an excellent coverage-based fuzzer that will produce a corpus of inputs that exercise unique codepaths. Eventually, we can use this to generate known-"good" inputs for anything. I've gone ahead and added a fuzz function that yeets bytes directly into WriteCharsLegacy, which was the original reason I went down this path. The implementation of LLVMFuzzerTestOneInput should be replaced with whatever you want to fuzz. --- .github/actions/spelling/expect/expect.txt | 4 + OpenConsole.sln | 630 ++++++++++++++++++++ src/common.build.pre.props | 34 +- src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj | 86 +++ src/host/ft_fuzzer/fuzzmain.cpp | 149 +++++ src/host/globals.h | 2 +- src/host/srvinit.cpp | 6 +- 7 files changed, 907 insertions(+), 4 deletions(-) create mode 100644 src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj create mode 100644 src/host/ft_fuzzer/fuzzmain.cpp diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 148e470807..639ca0ed00 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -88,6 +88,7 @@ args argv ARRAYSIZE ARROWKEYS +asan ASBRST ASBSET ASDF @@ -832,6 +833,7 @@ FRAMECHANGED fre freopen frontend +fsanitize Fscreen FSCTL FSINFOCLASS @@ -844,6 +846,7 @@ fullwidth func FUNCTIONCALL fuzzer +fuzzmain fuzzmap fuzzwrapper fwdecl @@ -1256,6 +1259,7 @@ LEFTSHIFT len lhs libpopcnt +libsancov libtickit LIMITTEXT LINEDOWN diff --git a/OpenConsole.sln b/OpenConsole.sln index 0cdb34c7ef..459f5a76b6 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -383,6 +383,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Settings", "Settings", "{77 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Control", "Control", "{9921CA0A-320C-4460-8623-3A3196E7F4CB}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.FuzzWrapper", "src\host\ft_fuzzer\Host.FuzzWrapper.vcxproj", "{05D9052F-D78F-478F-968A-2DE38A6DB996}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -399,6 +401,13 @@ Global Debug|DotNet_x86Test = Debug|DotNet_x86Test Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Fuzzing|Any CPU = Fuzzing|Any CPU + Fuzzing|ARM = Fuzzing|ARM + Fuzzing|ARM64 = Fuzzing|ARM64 + Fuzzing|DotNet_x64Test = Fuzzing|DotNet_x64Test + Fuzzing|DotNet_x86Test = Fuzzing|DotNet_x86Test + Fuzzing|x64 = Fuzzing|x64 + Fuzzing|x86 = Fuzzing|x86 Release|Any CPU = Release|Any CPU Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 @@ -430,6 +439,13 @@ Global {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.ActiveCfg = Debug|x86 {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Build.0 = Debug|x86 {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Debug|x86.Deploy.0 = Debug|x86 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|Any CPU.ActiveCfg = Debug|x86 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|ARM.ActiveCfg = Debug|x86 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|ARM64.ActiveCfg = Debug|ARM64 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|x86 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|x86 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|x64.ActiveCfg = Debug|x64 + {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Fuzzing|x86.ActiveCfg = Debug|x86 {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|Any CPU.ActiveCfg = Release|x86 {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|ARM.ActiveCfg = Release|x86 {CA5CAD1A-224A-4171-B13A-F16E576FDD12}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -460,6 +476,13 @@ Global {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Build.0 = Debug|x64 {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.ActiveCfg = Debug|Win32 {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.Build.0 = Debug|Win32 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|Any CPU.ActiveCfg = Release|Win32 {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM.ActiveCfg = Release|Win32 {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -487,6 +510,14 @@ Global {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x64.Build.0 = Debug|x64 {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x86.ActiveCfg = Debug|Win32 {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Debug|x86.Build.0 = Debug|Win32 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|Any CPU.ActiveCfg = Release|Win32 {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|ARM.ActiveCfg = Release|Win32 {345FD5A4-B32B-4F29-BD1C-B033BD2C35CC}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -514,6 +545,14 @@ Global {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x64.Build.0 = Debug|x64 {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x86.ActiveCfg = Debug|Win32 {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Debug|x86.Build.0 = Debug|Win32 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|Any CPU.ActiveCfg = Release|Win32 {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|ARM.ActiveCfg = Release|Win32 {2FD12FBB-1DDB-46D8-B818-1023C624CACA}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -544,6 +583,14 @@ Global {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x64.Build.0 = Debug|x64 {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x86.ActiveCfg = Debug|Win32 {3AE13314-1939-4DFA-9C14-38CA0834050C}.Debug|x86.Build.0 = Debug|Win32 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {3AE13314-1939-4DFA-9C14-38CA0834050C}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|Any CPU.ActiveCfg = Release|Win32 {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|ARM.ActiveCfg = Release|Win32 {3AE13314-1939-4DFA-9C14-38CA0834050C}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -574,6 +621,14 @@ Global {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64 {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.ActiveCfg = Debug|Win32 {DCF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.Build.0 = Debug|Win32 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {DCF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|Any CPU.ActiveCfg = Release|Win32 {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM.ActiveCfg = Release|Win32 {DCF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -604,6 +659,14 @@ Global {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x64.Build.0 = Debug|x64 {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.ActiveCfg = Debug|Win32 {1CF55140-EF6A-4736-A403-957E4F7430BB}.Debug|x86.Build.0 = Debug|Win32 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {1CF55140-EF6A-4736-A403-957E4F7430BB}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|Any CPU.ActiveCfg = Release|Win32 {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM.ActiveCfg = Release|Win32 {1CF55140-EF6A-4736-A403-957E4F7430BB}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -636,6 +699,14 @@ Global {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x64.Build.0 = Debug|x64 {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x86.ActiveCfg = Debug|Win32 {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Debug|x86.Build.0 = Debug|Win32 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|Any CPU.ActiveCfg = Release|Win32 {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|ARM.ActiveCfg = Release|Win32 {AF0A096A-8B3A-4949-81EF-7DF8F0FEE91F}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -665,6 +736,14 @@ Global {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x64.Build.0 = Debug|x64 {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x86.ActiveCfg = Debug|Win32 {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Debug|x86.Build.0 = Debug|Win32 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|Any CPU.ActiveCfg = Release|Win32 {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|ARM.ActiveCfg = Release|Win32 {1C959542-BAC2-4E55-9A6D-13251914CBB9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -692,6 +771,14 @@ Global {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x64.Build.0 = Debug|x64 {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x86.ActiveCfg = Debug|Win32 {06EC74CB-9A12-429C-B551-8562EC954746}.Debug|x86.Build.0 = Debug|Win32 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8562EC954746}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {06EC74CB-9A12-429C-B551-8562EC954746}.Release|Any CPU.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC954746}.Release|ARM.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC954746}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -719,6 +806,13 @@ Global {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x64.Build.0 = Debug|x64 {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x86.ActiveCfg = Debug|Win32 {06EC74CB-9A12-429C-B551-8562EC954747}.Debug|x86.Build.0 = Debug|Win32 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8562EC954747}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {06EC74CB-9A12-429C-B551-8562EC954747}.Release|Any CPU.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC954747}.Release|ARM.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC954747}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -746,6 +840,13 @@ Global {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x64.Build.0 = Debug|x64 {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x86.ActiveCfg = Debug|Win32 {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Debug|x86.Build.0 = Debug|Win32 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|Any CPU.ActiveCfg = Release|Win32 {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|ARM.ActiveCfg = Release|Win32 {531C23E7-4B76-4C08-8AAD-04164CB628C9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -773,6 +874,13 @@ Global {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x64.Build.0 = Debug|x64 {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x86.ActiveCfg = Debug|Win32 {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Debug|x86.Build.0 = Debug|Win32 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|Any CPU.ActiveCfg = Release|Win32 {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|ARM.ActiveCfg = Release|Win32 {531C23E7-4B76-4C08-8BBD-04164CB628C9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -799,6 +907,13 @@ Global {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x64.ActiveCfg = Debug|x64 {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x64.Build.0 = Debug|x64 {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Debug|x86.ActiveCfg = Debug|Win32 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|Any CPU.ActiveCfg = Release|Win32 {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|ARM.ActiveCfg = Release|Win32 {8CDB8850-7484-4EC7-B45B-181F85B2EE54}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -825,6 +940,13 @@ Global {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x64.Build.0 = Debug|x64 {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x86.ActiveCfg = Debug|Win32 {12144E07-FE63-4D33-9231-748B8D8C3792}.Debug|x86.Build.0 = Debug|Win32 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {12144E07-FE63-4D33-9231-748B8D8C3792}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|Any CPU.ActiveCfg = Release|Win32 {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|ARM.ActiveCfg = Release|Win32 {12144E07-FE63-4D33-9231-748B8D8C3792}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -852,6 +974,13 @@ Global {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x64.Build.0 = Debug|x64 {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x86.ActiveCfg = Debug|Win32 {6AF01638-84CF-4B65-9870-484DFFCAC772}.Debug|x86.Build.0 = Debug|Win32 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {6AF01638-84CF-4B65-9870-484DFFCAC772}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|Any CPU.ActiveCfg = Release|Win32 {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|ARM.ActiveCfg = Release|Win32 {6AF01638-84CF-4B65-9870-484DFFCAC772}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -879,6 +1008,13 @@ Global {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x64.Build.0 = Debug|x64 {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x86.ActiveCfg = Debug|Win32 {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Debug|x86.Build.0 = Debug|Win32 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|Any CPU.ActiveCfg = Release|Win32 {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|ARM.ActiveCfg = Release|Win32 {96927B31-D6E8-4ABD-B03E-A5088A30BEBE}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -906,6 +1042,13 @@ Global {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x64.Build.0 = Debug|x64 {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x86.ActiveCfg = Debug|Win32 {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Debug|x86.Build.0 = Debug|Win32 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|Any CPU.ActiveCfg = Release|Win32 {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|ARM.ActiveCfg = Release|Win32 {F210A4AE-E02A-4BFC-80BB-F50A672FE763}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -933,6 +1076,14 @@ Global {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x64.Build.0 = Debug|x64 {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x86.ActiveCfg = Debug|Win32 {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Debug|x86.Build.0 = Debug|Win32 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|Any CPU.ActiveCfg = Release|Win32 {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|ARM.ActiveCfg = Release|Win32 {5D23E8E1-3C64-4CC1-A8F7-6861677F7239}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -960,6 +1111,14 @@ Global {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x64.Build.0 = Debug|x64 {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x86.ActiveCfg = Debug|Win32 {18D09A24-8240-42D6-8CB6-236EEE820262}.Debug|x86.Build.0 = Debug|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {18D09A24-8240-42D6-8CB6-236EEE820262}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|Any CPU.ActiveCfg = Release|Win32 {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|ARM.ActiveCfg = Release|Win32 {18D09A24-8240-42D6-8CB6-236EEE820262}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -987,6 +1146,13 @@ Global {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x64.Build.0 = Debug|x64 {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x86.ActiveCfg = Debug|Win32 {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Debug|x86.Build.0 = Debug|Win32 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|Any CPU.ActiveCfg = Debug|x64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|ARM.ActiveCfg = Debug|x64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|ARM64.ActiveCfg = Release|ARM64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|DotNet_x64Test.ActiveCfg = Debug|x64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|x64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|x64.ActiveCfg = Debug|x64 + {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Fuzzing|x86.ActiveCfg = Release|Win32 {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|Any CPU.ActiveCfg = Release|Win32 {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|ARM.ActiveCfg = Release|Win32 {C17E1BF3-9D34-4779-9458-A8EF98CC5662}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1013,6 +1179,13 @@ Global {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x64.Build.0 = Debug|x64 {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x86.ActiveCfg = Debug|Win32 {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Debug|x86.Build.0 = Debug|Win32 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM.ActiveCfg = Debug|Win32 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x64.ActiveCfg = Debug|x64 + {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|Any CPU.ActiveCfg = Release|Win32 {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|ARM.ActiveCfg = Release|Win32 {099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1039,6 +1212,13 @@ Global {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x64.Build.0 = Debug|x64 {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x86.ActiveCfg = Debug|Win32 {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Debug|x86.Build.0 = Debug|Win32 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|Any CPU.ActiveCfg = Release|Win32 {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|ARM.ActiveCfg = Release|Win32 {FC802440-AD6A-4919-8F2C-7701F2B38D79}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1066,6 +1246,14 @@ Global {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x64.Build.0 = Debug|x64 {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x86.ActiveCfg = Debug|Win32 {919544AC-D39B-463F-8414-3C3C67CF727C}.Debug|x86.Build.0 = Debug|Win32 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {919544AC-D39B-463F-8414-3C3C67CF727C}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|Any CPU.ActiveCfg = Release|Win32 {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|ARM.ActiveCfg = Release|Win32 {919544AC-D39B-463F-8414-3C3C67CF727C}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1093,6 +1281,13 @@ Global {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x64.Build.0 = Debug|x64 {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x86.ActiveCfg = Debug|Win32 {ED82003F-FC5D-4E94-8B36-F480018ED064}.Debug|x86.Build.0 = Debug|Win32 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {ED82003F-FC5D-4E94-8B36-F480018ED064}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|Any CPU.ActiveCfg = Release|Win32 {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|ARM.ActiveCfg = Release|Win32 {ED82003F-FC5D-4E94-8B36-F480018ED064}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1120,6 +1315,14 @@ Global {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x64.Build.0 = Debug|x64 {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x86.ActiveCfg = Debug|Win32 {06EC74CB-9A12-429C-B551-8532EC964726}.Debug|x86.Build.0 = Debug|Win32 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8532EC964726}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {06EC74CB-9A12-429C-B551-8532EC964726}.Release|Any CPU.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8532EC964726}.Release|ARM.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8532EC964726}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1147,6 +1350,14 @@ Global {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x64.Build.0 = Debug|x64 {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x86.ActiveCfg = Debug|Win32 {ED82003F-FC5D-4E94-8B47-F480018ED064}.Debug|x86.Build.0 = Debug|Win32 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {ED82003F-FC5D-4E94-8B47-F480018ED064}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|Any CPU.ActiveCfg = Release|Win32 {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|ARM.ActiveCfg = Release|Win32 {ED82003F-FC5D-4E94-8B47-F480018ED064}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1174,6 +1385,14 @@ Global {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x64.Build.0 = Debug|x64 {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x86.ActiveCfg = Debug|Win32 {06EC74CB-9A12-429C-B551-8562EC964846}.Debug|x86.Build.0 = Debug|Win32 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {06EC74CB-9A12-429C-B551-8562EC964846}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {06EC74CB-9A12-429C-B551-8562EC964846}.Release|Any CPU.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC964846}.Release|ARM.ActiveCfg = Release|Win32 {06EC74CB-9A12-429C-B551-8562EC964846}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1201,6 +1420,13 @@ Global {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x64.Build.0 = Debug|x64 {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x86.ActiveCfg = Debug|Win32 {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Debug|x86.Build.0 = Debug|Win32 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|Any CPU.ActiveCfg = Release|Win32 {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|ARM.ActiveCfg = Release|Win32 {D3B92829-26CB-411A-BDA2-7F5DA3D25DD4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1228,6 +1454,13 @@ Global {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x64.Build.0 = Debug|x64 {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x86.ActiveCfg = Debug|Win32 {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Debug|x86.Build.0 = Debug|Win32 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|Any CPU.ActiveCfg = Release|Win32 {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|ARM.ActiveCfg = Release|Win32 {C7A6A5D9-60BE-4AEB-A5F6-AFE352F86CBB}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1255,6 +1488,14 @@ Global {990F2657-8580-4828-943F-5DD657D11842}.Debug|x64.Build.0 = Debug|x64 {990F2657-8580-4828-943F-5DD657D11842}.Debug|x86.ActiveCfg = Debug|Win32 {990F2657-8580-4828-943F-5DD657D11842}.Debug|x86.Build.0 = Debug|Win32 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {990F2657-8580-4828-943F-5DD657D11842}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {990F2657-8580-4828-943F-5DD657D11842}.Release|Any CPU.ActiveCfg = Release|Win32 {990F2657-8580-4828-943F-5DD657D11842}.Release|ARM.ActiveCfg = Release|Win32 {990F2657-8580-4828-943F-5DD657D11842}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1282,6 +1523,13 @@ Global {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x64.Build.0 = Debug|x64 {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x86.ActiveCfg = Debug|Win32 {814DBDDE-894E-4327-A6E1-740504850098}.Debug|x86.Build.0 = Debug|Win32 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {814DBDDE-894E-4327-A6E1-740504850098}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {814DBDDE-894E-4327-A6E1-740504850098}.Release|Any CPU.ActiveCfg = Release|Win32 {814DBDDE-894E-4327-A6E1-740504850098}.Release|ARM.ActiveCfg = Release|Win32 {814DBDDE-894E-4327-A6E1-740504850098}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1309,6 +1557,13 @@ Global {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x64.Build.0 = Debug|x64 {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x86.ActiveCfg = Debug|Win32 {814CBEEE-894E-4327-A6E1-740504850098}.Debug|x86.Build.0 = Debug|Win32 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {814CBEEE-894E-4327-A6E1-740504850098}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {814CBEEE-894E-4327-A6E1-740504850098}.Release|Any CPU.ActiveCfg = Release|Win32 {814CBEEE-894E-4327-A6E1-740504850098}.Release|ARM.ActiveCfg = Release|Win32 {814CBEEE-894E-4327-A6E1-740504850098}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1341,6 +1596,14 @@ Global {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x64.Build.0 = Debug|x64 {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.ActiveCfg = Debug|Win32 {18D09A24-8240-42D6-8CB6-236EEE820263}.Debug|x86.Build.0 = Debug|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {18D09A24-8240-42D6-8CB6-236EEE820263}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|Any CPU.ActiveCfg = Release|Win32 {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM.ActiveCfg = Release|Win32 {18D09A24-8240-42D6-8CB6-236EEE820263}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1370,6 +1633,13 @@ Global {990F2657-8580-4828-943F-5DD657D11843}.Debug|x64.Build.0 = Debug|x64 {990F2657-8580-4828-943F-5DD657D11843}.Debug|x86.ActiveCfg = Debug|Win32 {990F2657-8580-4828-943F-5DD657D11843}.Debug|x86.Build.0 = Debug|Win32 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {990F2657-8580-4828-943F-5DD657D11843}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {990F2657-8580-4828-943F-5DD657D11843}.Release|Any CPU.ActiveCfg = Release|Win32 {990F2657-8580-4828-943F-5DD657D11843}.Release|ARM.ActiveCfg = Release|Win32 {990F2657-8580-4828-943F-5DD657D11843}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1402,6 +1672,14 @@ Global {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x64.Build.0 = Debug|x64 {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x86.ActiveCfg = Debug|Win32 {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Debug|x86.Build.0 = Debug|Win32 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|Any CPU.ActiveCfg = Release|Win32 {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|ARM.ActiveCfg = Release|Win32 {0CF235BD-2DA0-407E-90EE-C467E8BBC714}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1436,6 +1714,14 @@ Global {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x64.Build.0 = Debug|x64 {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x86.ActiveCfg = Debug|Win32 {48D21369-3D7B-4431-9967-24E81292CF62}.Debug|x86.Build.0 = Debug|Win32 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {48D21369-3D7B-4431-9967-24E81292CF62}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {48D21369-3D7B-4431-9967-24E81292CF62}.Release|Any CPU.ActiveCfg = Release|Win32 {48D21369-3D7B-4431-9967-24E81292CF62}.Release|ARM.ActiveCfg = Release|Win32 {48D21369-3D7B-4431-9967-24E81292CF62}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1466,6 +1752,13 @@ Global {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1496,6 +1789,13 @@ Global {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-ABCD-429C-B551-8562EC954746}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1525,6 +1825,13 @@ Global {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1552,6 +1859,13 @@ Global {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-F542-4635-A069-7CAEFB930070}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1579,6 +1893,13 @@ Global {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1606,6 +1927,13 @@ Global {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1634,6 +1962,13 @@ Global {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x64.Build.0 = Debug|x64 {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x86.ActiveCfg = Debug|Win32 {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x86.Build.0 = Debug|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|Any CPU.ActiveCfg = Release|Win32 {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|ARM.ActiveCfg = Release|Win32 {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1661,6 +1996,13 @@ Global {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x64.Build.0 = Debug|x64 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x86.ActiveCfg = Debug|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Debug|x86.Build.0 = Debug|Win32 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|Any CPU.ActiveCfg = Release|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|ARM.ActiveCfg = Release|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1691,6 +2033,14 @@ Global {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x64.Build.0 = Debug|x64 {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x86.ActiveCfg = Debug|Win32 {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Debug|x86.Build.0 = Debug|Win32 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|Any CPU.ActiveCfg = Release|Win32 {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|ARM.ActiveCfg = Release|Win32 {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1718,6 +2068,13 @@ Global {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Debug|x64.Build.0 = Debug|x64 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Debug|x86.ActiveCfg = Debug|Win32 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Debug|x86.Build.0 = Debug|Win32 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|Any CPU.ActiveCfg = Release|Win32 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|ARM.ActiveCfg = Release|Win32 {34DE34D3-1CD6-4EE3-8BD9-A26B5B27EC73}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1748,6 +2105,13 @@ Global {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x64.Build.0 = Debug|x64 {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.ActiveCfg = Debug|Win32 {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Debug|x86.Build.0 = Debug|Win32 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|Any CPU.ActiveCfg = Release|Win32 {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM.ActiveCfg = Release|Win32 {84848BFA-931D-42CE-9ADF-01EE54DE7890}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1781,6 +2145,13 @@ Global {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Debug|DotNet_x86Test.Build.0 = Debug|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Debug|x64.ActiveCfg = Debug|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Debug|x86.ActiveCfg = Debug|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|Any CPU.ActiveCfg = Debug|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|ARM.ActiveCfg = Debug|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|x64.ActiveCfg = Debug|Any CPU + {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|x86.ActiveCfg = Fuzzing|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Release|Any CPU.ActiveCfg = Release|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Release|Any CPU.Build.0 = Release|Any CPU {376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Release|ARM.ActiveCfg = Release|Any CPU @@ -1809,6 +2180,13 @@ Global {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-9333-4D05-B12A-1905CBF112F9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1836,6 +2214,13 @@ Global {CA5CAD1A-9A12-429C-B551-8562EC954746}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-9A12-429C-B551-8562EC954746}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-9A12-429C-B551-8562EC954746}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-9A12-429C-B551-8562EC954746}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-9A12-429C-B551-8562EC954746}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-9A12-429C-B551-8562EC954746}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-9A12-429C-B551-8562EC954746}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1863,6 +2248,13 @@ Global {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1893,6 +2285,13 @@ Global {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x64.Build.0 = Debug|x64 {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x86.ActiveCfg = Debug|Win32 {48D21369-3D7B-4431-9967-24E81292CF63}.Debug|x86.Build.0 = Debug|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {48D21369-3D7B-4431-9967-24E81292CF63}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {48D21369-3D7B-4431-9967-24E81292CF63}.Release|Any CPU.ActiveCfg = Release|Win32 {48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM.ActiveCfg = Release|Win32 {48D21369-3D7B-4431-9967-24E81292CF63}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1921,6 +2320,13 @@ Global {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1955,6 +2361,13 @@ Global {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.ActiveCfg = Debug|Win32 {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.Build.0 = Debug|Win32 {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Debug|x86.Deploy.0 = Debug|Win32 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|Any CPU.ActiveCfg = Release|Win32 {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM.ActiveCfg = Release|Win32 {B0AC39D6-7B40-49A9-8202-58549BAE1FB1}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -1988,6 +2401,13 @@ Global {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Debug|x64.Build.0 = Debug|x64 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Debug|x86.ActiveCfg = Debug|Win32 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Debug|x86.Build.0 = Debug|Win32 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|Any CPU.ActiveCfg = Release|Win32 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|ARM.ActiveCfg = Release|Win32 {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2017,6 +2437,13 @@ Global {A22EC5F6-7851-4B88-AC52-47249D437A52}.Debug|x64.Build.0 = Debug|x64 {A22EC5F6-7851-4B88-AC52-47249D437A52}.Debug|x86.ActiveCfg = Debug|Win32 {A22EC5F6-7851-4B88-AC52-47249D437A52}.Debug|x86.Build.0 = Debug|Win32 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {A22EC5F6-7851-4B88-AC52-47249D437A52}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {A22EC5F6-7851-4B88-AC52-47249D437A52}.Release|Any CPU.ActiveCfg = Release|Win32 {A22EC5F6-7851-4B88-AC52-47249D437A52}.Release|ARM.ActiveCfg = Release|Win32 {A22EC5F6-7851-4B88-AC52-47249D437A52}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2047,6 +2474,13 @@ Global {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Debug|x86.ActiveCfg = Debug|Win32 {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Debug|x86.Build.0 = Debug|Win32 {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Debug|x86.Deploy.0 = Debug|Win32 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Release|Any CPU.ActiveCfg = Release|Win32 {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Release|ARM.ActiveCfg = Release|Win32 {A021EDFF-45C8-4DC2-BEF7-36E1B3B8CFE8}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2079,6 +2513,13 @@ Global {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Debug|x64.Build.0 = Debug|x64 {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Debug|x86.ActiveCfg = Debug|Win32 {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Debug|x86.Build.0 = Debug|Win32 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Release|Any CPU.ActiveCfg = Release|Win32 {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Release|ARM.ActiveCfg = Release|Win32 {767268EE-174A-46FE-96F0-EEE698A1BBC9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2109,6 +2550,13 @@ Global {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Debug|x64.Build.0 = Debug|x64 {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Debug|x86.ActiveCfg = Debug|Win32 {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Debug|x86.Build.0 = Debug|Win32 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Release|Any CPU.ActiveCfg = Release|Win32 {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Release|ARM.ActiveCfg = Release|Win32 {A602A555-BAAC-46E1-A91D-3DAB0475C5A1}.Release|ARM64.ActiveCfg = Release|Win32 @@ -2137,6 +2585,13 @@ Global {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Debug|x64.Build.0 = Debug|x64 {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Debug|x86.ActiveCfg = Debug|Win32 {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Debug|x86.Build.0 = Debug|Win32 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Release|Any CPU.ActiveCfg = Release|Win32 {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Release|ARM.ActiveCfg = Release|Win32 {95B136F9-B238-490C-A7C5-5843C1FECAC4}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2166,6 +2621,13 @@ Global {024052DE-83FB-4653-AEA4-90790D29D5BD}.Debug|x64.Build.0 = Debug|x64 {024052DE-83FB-4653-AEA4-90790D29D5BD}.Debug|x86.ActiveCfg = Debug|Win32 {024052DE-83FB-4653-AEA4-90790D29D5BD}.Debug|x86.Build.0 = Debug|Win32 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {024052DE-83FB-4653-AEA4-90790D29D5BD}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|Any CPU.ActiveCfg = Release|Win32 {024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|ARM.ActiveCfg = Release|Win32 {024052DE-83FB-4653-AEA4-90790D29D5BD}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2195,6 +2657,13 @@ Global {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x64.Build.0 = Debug|x64 {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x86.ActiveCfg = Debug|Win32 {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Debug|x86.Build.0 = Debug|Win32 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|Any CPU.ActiveCfg = Release|Win32 {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|ARM.ActiveCfg = Release|Win32 {067F0A06-FCB7-472C-96E9-B03B54E8E18D}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2227,6 +2696,14 @@ Global {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x64.Build.0 = Debug|x64 {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.ActiveCfg = Debug|Win32 {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Debug|x86.Build.0 = Debug|Win32 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|Any CPU.ActiveCfg = Release|Win32 {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM.ActiveCfg = Release|Win32 {6BAE5851-50D5-4934-8D5E-30361A8A40F3}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2257,6 +2734,13 @@ Global {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Debug|DotNet_x86Test.Build.0 = Debug|x86 {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Debug|x64.ActiveCfg = Debug|Any CPU {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Debug|x86.ActiveCfg = Debug|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|Any CPU.ActiveCfg = Debug|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|ARM.ActiveCfg = Debug|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|ARM64.ActiveCfg = Fuzzing|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Any CPU + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|x64.ActiveCfg = Debug|x64 + {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|x86.ActiveCfg = Fuzzing|x86 {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|Any CPU.ActiveCfg = Release|Any CPU {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|ARM.ActiveCfg = Release|Any CPU {1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Release|ARM.Build.0 = Release|Any CPU @@ -2287,6 +2771,13 @@ Global {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Debug|x64.Build.0 = Debug|x64 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Debug|x86.ActiveCfg = Debug|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Debug|x86.Build.0 = Debug|Win32 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|Any CPU.ActiveCfg = Release|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|ARM.ActiveCfg = Release|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2327,6 +2818,13 @@ Global {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.Build.0 = Debug|Win32 {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Debug|x86.Deploy.0 = Debug|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2358,6 +2856,13 @@ Global {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2387,6 +2892,13 @@ Global {CA5CAD1A-082C-4476-9F33-94B339494076}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-082C-4476-9F33-94B339494076}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-082C-4476-9F33-94B339494076}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-082C-4476-9F33-94B339494076}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-082C-4476-9F33-94B339494076}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-082C-4476-9F33-94B339494076}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-082C-4476-9F33-94B339494076}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2416,6 +2928,13 @@ Global {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Debug|x64.Build.0 = Debug|x64 {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Debug|x86.ActiveCfg = Debug|Win32 {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Debug|x86.Build.0 = Debug|Win32 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|Any CPU.ActiveCfg = Release|Win32 {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|ARM.ActiveCfg = Release|Win32 {CA5CAD1A-9B68-456A-B13E-C8218070DC42}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2443,6 +2962,13 @@ Global {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x64.Build.0 = Debug|x64 {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x86.ActiveCfg = Debug|Win32 {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Debug|x86.Build.0 = Debug|Win32 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|Any CPU.ActiveCfg = Release|Win32 {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|ARM.ActiveCfg = Release|Win32 {21B7EA5E-1EF8-49B6-AC07-11714AF0E37D}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2483,6 +3009,13 @@ Global {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.ActiveCfg = Debug|x86 {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Build.0 = Debug|x86 {F75E29D0-D288-478B-8D83-2C190F321A3F}.Debug|x86.Deploy.0 = Debug|x86 + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|Any CPU.ActiveCfg = Release|Any CPU + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|ARM.ActiveCfg = Fuzzing|ARM + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|DotNet_x86Test.ActiveCfg = Release|Any CPU + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x64.ActiveCfg = Release|x64 + {F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x86.ActiveCfg = Release|x86 {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|Any CPU.ActiveCfg = Release|Any CPU {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM.ActiveCfg = Release|ARM {F75E29D0-D288-478B-8D83-2C190F321A3F}.Release|ARM.Build.0 = Release|ARM @@ -2518,6 +3051,13 @@ Global {43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x64.Build.0 = Debug|x64 {43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x86.ActiveCfg = Debug|Win32 {43CE4CE5-0010-4B99-9569-672670D26E26}.Debug|x86.Build.0 = Debug|Win32 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {43CE4CE5-0010-4B99-9569-672670D26E26}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {43CE4CE5-0010-4B99-9569-672670D26E26}.Release|Any CPU.ActiveCfg = Release|Win32 {43CE4CE5-0010-4B99-9569-672670D26E26}.Release|ARM.ActiveCfg = Release|Win32 {43CE4CE5-0010-4B99-9569-672670D26E26}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2547,6 +3087,13 @@ Global {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x64.Build.0 = Debug|x64 {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x86.ActiveCfg = Debug|Win32 {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Debug|x86.Build.0 = Debug|Win32 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|Any CPU.ActiveCfg = Release|Win32 {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|ARM.ActiveCfg = Release|Win32 {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2576,6 +3123,13 @@ Global {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x64.Build.0 = Debug|x64 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x86.ActiveCfg = Debug|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Debug|x86.Build.0 = Debug|Win32 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|Any CPU.ActiveCfg = Release|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|ARM.ActiveCfg = Release|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2586,6 +3140,73 @@ Global {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x64.Build.0 = Release|x64 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.ActiveCfg = Release|Win32 {68A10CD3-AA64-465B-AF5F-ED4E9700543C}.Release|x86.Build.0 = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x64.Build.0 = AuditMode|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|x86.Build.0 = AuditMode|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM.ActiveCfg = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|ARM64.Build.0 = Debug|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.ActiveCfg = Debug|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x64.Build.0 = Debug|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.ActiveCfg = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Debug|x86.Build.0 = Debug|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|Any CPU.ActiveCfg = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM.ActiveCfg = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.ActiveCfg = Release|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|ARM64.Build.0 = Release|ARM64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.ActiveCfg = Release|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x64.Build.0 = Release|x64 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.ActiveCfg = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.Release|x86.Build.0 = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x64.ActiveCfg = Debug|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Debug|x86.ActiveCfg = Debug|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|Any CPU.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|ARM64.ActiveCfg = Release|ARM64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x64.ActiveCfg = Release|x64 + {05D9052F-D78F-478F-968A-2DE38A6DB996}.Release|x86.ActiveCfg = Release|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 @@ -2606,6 +3227,14 @@ Global {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x64.Build.0 = Debug|x64 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x86.ActiveCfg = Debug|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Debug|x86.Build.0 = Debug|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|Any CPU.ActiveCfg = Release|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|ARM.ActiveCfg = Release|Win32 {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -2711,6 +3340,7 @@ Global {2D17E75D-2DDC-42C4-AD70-704D95A937AE} = {59840756-302F-44DF-AA47-441A9D673202} {77875138-BB08-49F9-8BB1-409C2150E0E1} = {59840756-302F-44DF-AA47-441A9D673202} {9921CA0A-320C-4460-8623-3A3196E7F4CB} = {59840756-302F-44DF-AA47-441A9D673202} + {05D9052F-D78F-478F-968A-2DE38A6DB996} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/common.build.pre.props b/src/common.build.pre.props index 2beeec1f54..3df286774e 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -42,6 +42,10 @@ AuditMode x64 + + Fuzzing + Win32 + Debug x64 @@ -50,6 +54,10 @@ Release x64 + + Fuzzing + x64 + AuditMode ARM64 @@ -62,6 +70,10 @@ Release ARM64 + + Fuzzing + ARM64 + @@ -125,12 +137,12 @@ - + false true - + MaxSpeed true @@ -166,6 +178,24 @@ + + x86_64 + i386 + i386 + + + + + /fsanitize=address /fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div %(AdditionalOptions) + + MultiThreaded + FUZZING_BUILD;%(PreprocessorDefinitions) + + + libsancov.lib;clang_rt.asan-$(OCClangArchitectureName).lib;%(AdditionalDependencies) + + + diff --git a/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj b/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj new file mode 100644 index 0000000000..e351317812 --- /dev/null +++ b/src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj @@ -0,0 +1,86 @@ + + + + {05d9052f-d78f-478f-968a-2de38a6db996} + Win32Proj + Host.FuzzWrapper + Host.FuzzWrapper + OpenConsoleFuzzer + Application + + + + + + + + Create + ProgramDatabase + + + + + + {0cf235bd-2da0-407e-90ee-c467e8bbc714} + + + {06ec74cb-9a12-429c-b551-8562ec964846} + + + {06ec74cb-9a12-429c-b551-8532ec964726} + + + {ef3e32a7-5ff6-42b4-b6e2-96cd7d033f00} + + + {345fd5a4-b32b-4f29-bd1c-b033bd2c35cc} + + + {af0a096a-8b3a-4949-81ef-7df8f0fee91f} + + + {48d21369-3d7b-4431-9967-24e81292cf62} + + + {1c959542-bac2-4e55-9a6d-13251914cbb9} + + + {990f2657-8580-4828-943f-5dd657d11842} + + + {18d09a24-8240-42d6-8cb6-236eee820262} + + + {dcf55140-ef6a-4736-a403-957e4f7430bb} + + + {3ae13314-1939-4dfa-9c14-38ca0834050c} + + + {2fd12fbb-1ddb-46d8-b818-1023c624caca} + + + {18d09a24-8240-42d6-8cb6-236eee820263} + + + {06ec74cb-9a12-429c-b551-8562ec954746} + + + + + ..;%(AdditionalIncludeDirectories) + + + Console + + + + + + + clang_rt.fuzzer-$(OCClangArchitectureName).lib;%(AdditionalDependencies) + + + + + diff --git a/src/host/ft_fuzzer/fuzzmain.cpp b/src/host/ft_fuzzer/fuzzmain.cpp new file mode 100644 index 0000000000..674e898d37 --- /dev/null +++ b/src/host/ft_fuzzer/fuzzmain.cpp @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "precomp.h" + +#include "../ConsoleArguments.hpp" +#include "../srvinit.h" +#include "../../server/Entrypoints.h" +#include "../../interactivity/inc/ServiceLocator.hpp" +#include "../../server/DeviceHandle.h" +#include "../../server/IoThread.h" +#include "../_stream.h" +#include "../getset.h" +#include + +struct NullDeviceComm : public IDeviceComm +{ + HRESULT SetServerInformation(CD_IO_SERVER_INFORMATION* const) const override + { + return S_FALSE; + } + HRESULT ReadIo(PCONSOLE_API_MSG const, CONSOLE_API_MSG* const) const override + { + // The easiest way to get the IO thread to stop reading from us us to simply + // suspend it. The fuzzer doesn't need a device IO thread. + SuspendThread(GetCurrentThread()); + return S_FALSE; + } + HRESULT CompleteIo(CD_IO_COMPLETE* const) const override + { + return S_FALSE; + } + HRESULT ReadInput(CD_IO_OPERATION* const) const override + { + SuspendThread(GetCurrentThread()); + return S_FALSE; + } + HRESULT WriteOutput(CD_IO_OPERATION* const) const override + { + return S_FALSE; + } + HRESULT AllowUIAccess() const override + { + return S_FALSE; + } + ULONG_PTR PutHandle(const void*) override + { + return 0; + } + void* GetHandle(ULONG_PTR) const override + { + return nullptr; + } + HRESULT GetServerHandle(HANDLE*) const override + { + return S_FALSE; + } +}; + +[[nodiscard]] HRESULT StartNullConsole(const ConsoleArguments* const args) +{ + auto& globals = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals(); + globals.pDeviceComm = new NullDeviceComm{}; // quickly, before we "connect". Leak this. + + // it is safe to pass INVALID_HANDLE_VALUE here because the null handle would have been detected + // in ConDrvDeviceComm (which has been avoided by setting a global device comm beforehand) + RETURN_IF_NTSTATUS_FAILED(ConsoleCreateIoThreadLegacy(INVALID_HANDLE_VALUE, args)); + + auto& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation(); + + // Process handle list manipulation must be done under lock + gci.LockConsole(); + ConsoleProcessHandle* pProcessHandle{ nullptr }; + RETURN_IF_FAILED(gci.ProcessHandleList.AllocProcessData(GetCurrentProcessId(), + GetCurrentThreadId(), + 0, + nullptr, + &pProcessHandle)); + pProcessHandle->fRootProcess = true; + + constexpr static std::wstring_view fakeTitle{ L"Fuzzing Harness" }; + + CONSOLE_API_CONNECTINFO fakeConnectInfo{}; + fakeConnectInfo.ConsoleInfo.SetShowWindow(SW_NORMAL); + fakeConnectInfo.ConsoleInfo.SetScreenBufferSize(til::size{ 80, 25 }); + fakeConnectInfo.ConsoleInfo.SetWindowSize(til::size{ 80, 25 }); + fakeConnectInfo.ConsoleInfo.SetStartupFlags(STARTF_USECOUNTCHARS); + wcscpy_s(fakeConnectInfo.Title, fakeTitle.data()); + fakeConnectInfo.TitleLength = gsl::narrow_cast(fakeTitle.size() * sizeof(wchar_t)); // bytes, not wchars + wcscpy_s(fakeConnectInfo.AppName, fakeTitle.data()); + fakeConnectInfo.AppNameLength = gsl::narrow_cast(fakeTitle.size() * sizeof(wchar_t)); // bytes, not wchars + fakeConnectInfo.ConsoleApp = TRUE; + fakeConnectInfo.WindowVisible = TRUE; + RETURN_IF_NTSTATUS_FAILED(ConsoleAllocateConsole(&fakeConnectInfo)); + + CommandHistory::s_Allocate(fakeTitle, (HANDLE)pProcessHandle); + + gci.UnlockConsole(); + + return S_OK; +} + +extern "C" __declspec(dllexport) HRESULT RunConhost() +{ + Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().hInstance = wil::GetModuleInstanceHandle(); + + // passing stdin/stdout lets us drive this like conpty (!!) and test the VT renderer (!!) + // but for now we want to drive it like conhost + ConsoleArguments args({}, nullptr, nullptr); + + HRESULT hr = args.ParseCommandline(); + if (SUCCEEDED(hr)) + { + hr = StartNullConsole(&args); + } + + return hr; +} + +#ifdef FUZZING_BUILD +extern "C" __declspec(dllexport) int LLVMFuzzerInitialize(int* /*argc*/, char*** /*argv*/) +#else +int main(int /*argc*/, char** /*argv*/) +#endif +{ + RETURN_IF_FAILED(RunConhost()); + return 0; +} + +extern "C" __declspec(dllexport) int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + auto& gci = Microsoft::Console::Interactivity::ServiceLocator::LocateGlobals().getConsoleInformation(); + + const auto u16String{ til::u8u16(std::string_view{ reinterpret_cast(data), size }) }; + SHORT scrollY{}; + size_t sizeInBytes{ u16String.size() * 2 }; + gci.LockConsole(); + auto u = wil::scope_exit([&]() { gci.UnlockConsole(); }); + (void)WriteCharsLegacy(gci.GetActiveOutputBuffer(), + u16String.data(), + u16String.data(), + u16String.data(), + &sizeInBytes, + nullptr, + 0, + WC_PRINTABLE_CONTROL_CHARS | WC_DESTRUCTIVE_BACKSPACE | WC_KEEP_CURSOR_VISIBLE, + &scrollY); + return 0; +} diff --git a/src/host/globals.h b/src/host/globals.h index 4edf2bbc45..c99794845f 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -46,7 +46,7 @@ public: CONSOLE_INFORMATION& getConsoleInformation(); - IDeviceComm* pDeviceComm; + IDeviceComm* pDeviceComm{ nullptr }; wil::unique_event_nothrow hInputEvent; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index ad43d06ed5..b3f21f0cda 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -40,7 +40,11 @@ try { Globals& Globals = ServiceLocator::LocateGlobals(); - Globals.pDeviceComm = new ConDrvDeviceComm(Server); + if (!Globals.pDeviceComm) + { + // in rare circumstances (such as in the fuzzing harness), there will already be a device comm + Globals.pDeviceComm = new ConDrvDeviceComm(Server); + } Globals.launchArgs = *args; From 806d992a06d197c0684663243e6873a154fc9386 Mon Sep 17 00:00:00 2001 From: Chester Liu Date: Tue, 30 Mar 2021 00:03:16 +0800 Subject: [PATCH 06/56] Prefer constexpr over const across the codebase (#9587) Supports #2941 Previous PRs: #3362 #3416 --- src/inc/conattrs.hpp | 16 +++--- src/inc/unicode.hpp | 53 +++++++++---------- .../adapter/adaptDispatchGraphics.cpp | 40 +++++++------- src/terminal/input/mouseInput.cpp | 2 +- src/terminal/input/terminalInput.cpp | 2 - .../parser/InputStateMachineEngine.hpp | 14 ++--- 6 files changed, 62 insertions(+), 65 deletions(-) diff --git a/src/inc/conattrs.hpp b/src/inc/conattrs.hpp index 482e427a78..cb91100643 100644 --- a/src/inc/conattrs.hpp +++ b/src/inc/conattrs.hpp @@ -26,15 +26,15 @@ WORD XtermToWindowsIndex(const size_t index) noexcept; WORD Xterm256ToWindowsIndex(const size_t index) noexcept; WORD XtermToLegacy(const size_t xtermForeground, const size_t xtermBackground); -const WORD WINDOWS_RED_ATTR = FOREGROUND_RED; -const WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN; -const WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE; -const WORD WINDOWS_BRIGHT_ATTR = FOREGROUND_INTENSITY; +constexpr WORD WINDOWS_RED_ATTR = FOREGROUND_RED; +constexpr WORD WINDOWS_GREEN_ATTR = FOREGROUND_GREEN; +constexpr WORD WINDOWS_BLUE_ATTR = FOREGROUND_BLUE; +constexpr WORD WINDOWS_BRIGHT_ATTR = FOREGROUND_INTENSITY; -const WORD XTERM_RED_ATTR = 0x01; -const WORD XTERM_GREEN_ATTR = 0x02; -const WORD XTERM_BLUE_ATTR = 0x04; -const WORD XTERM_BRIGHT_ATTR = 0x08; +constexpr WORD XTERM_RED_ATTR = 0x01; +constexpr WORD XTERM_GREEN_ATTR = 0x02; +constexpr WORD XTERM_BLUE_ATTR = 0x04; +constexpr WORD XTERM_BRIGHT_ATTR = 0x08; enum class CursorType : unsigned int { diff --git a/src/inc/unicode.hpp b/src/inc/unicode.hpp index 6e0e4a202d..e41c32821f 100644 --- a/src/inc/unicode.hpp +++ b/src/inc/unicode.hpp @@ -26,37 +26,36 @@ Author(s): #define IsEastAsianCP(cp) ((cp) == CP_JAPANESE || (cp) == CP_KOREAN || (cp) == CP_CHINESE_TRADITIONAL || (cp) == CP_CHINESE_SIMPLIFIED) // UNICODE_NULL is a Windows macro definition -const wchar_t UNICODE_BACKSPACE = 0x8; -const wchar_t UNICODE_ESC = 0x1b; -const wchar_t UNICODE_DEL = 0x7f; +constexpr wchar_t UNICODE_BACKSPACE = 0x8; +constexpr wchar_t UNICODE_ESC = 0x1b; +constexpr wchar_t UNICODE_DEL = 0x7f; // NOTE: This isn't actually a backspace. It's a graphical block. But // I believe it's emitted by one of our ANSI/OEM --> Unicode conversions. // We should dig further into this in the future. -const wchar_t UNICODE_BEL = 0x7; -const wchar_t UNICODE_BACKSPACE2 = 0x25d8; -const wchar_t UNICODE_CARRIAGERETURN = 0x0d; -const wchar_t UNICODE_LINEFEED = 0x0a; -const wchar_t UNICODE_BELL = 0x07; -const wchar_t UNICODE_TAB = 0x09; -const wchar_t UNICODE_SPACE = 0x20; -const wchar_t UNICODE_LEFT_SMARTQUOTE = 0x201c; -const wchar_t UNICODE_RIGHT_SMARTQUOTE = 0x201d; -const wchar_t UNICODE_EM_DASH = 0x2014; -const wchar_t UNICODE_EN_DASH = 0x2013; -const wchar_t UNICODE_NBSP = 0xa0; -const wchar_t UNICODE_NARROW_NBSP = 0x202f; -const wchar_t UNICODE_QUOTE = L'\"'; -const wchar_t UNICODE_HYPHEN = L'-'; -const wchar_t UNICODE_BOX_DRAW_LIGHT_DOWN_AND_RIGHT = 0x250c; -const wchar_t UNICODE_BOX_DRAW_LIGHT_DOWN_AND_LEFT = 0x2510; -const wchar_t UNICODE_BOX_DRAW_LIGHT_HORIZONTAL = 0x2500; -const wchar_t UNICODE_BOX_DRAW_LIGHT_VERTICAL = 0x2502; -const wchar_t UNICODE_BOX_DRAW_LIGHT_UP_AND_RIGHT = 0x2514; -const wchar_t UNICODE_BOX_DRAW_LIGHT_UP_AND_LEFT = 0x2518; -const wchar_t UNICODE_INVALID = 0xFFFF; +constexpr wchar_t UNICODE_BACKSPACE2 = 0x25d8; +constexpr wchar_t UNICODE_CARRIAGERETURN = 0x0d; +constexpr wchar_t UNICODE_LINEFEED = 0x0a; +constexpr wchar_t UNICODE_BELL = 0x07; +constexpr wchar_t UNICODE_TAB = 0x09; +constexpr wchar_t UNICODE_SPACE = 0x20; +constexpr wchar_t UNICODE_LEFT_SMARTQUOTE = 0x201c; +constexpr wchar_t UNICODE_RIGHT_SMARTQUOTE = 0x201d; +constexpr wchar_t UNICODE_EM_DASH = 0x2014; +constexpr wchar_t UNICODE_EN_DASH = 0x2013; +constexpr wchar_t UNICODE_NBSP = 0xa0; +constexpr wchar_t UNICODE_NARROW_NBSP = 0x202f; +constexpr wchar_t UNICODE_QUOTE = L'\"'; +constexpr wchar_t UNICODE_HYPHEN = L'-'; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_DOWN_AND_RIGHT = 0x250c; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_DOWN_AND_LEFT = 0x2510; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_HORIZONTAL = 0x2500; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_VERTICAL = 0x2502; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_UP_AND_RIGHT = 0x2514; +constexpr wchar_t UNICODE_BOX_DRAW_LIGHT_UP_AND_LEFT = 0x2518; +constexpr wchar_t UNICODE_INVALID = 0xFFFF; // This is the "Ctrl+C" character. // With VKey='C', it generates a CTRL_C_EVENT // With VKey=VK_CANCEL (0x3), it generates a CTRL_BREAK_EVENT -const wchar_t UNICODE_ETX = L'\x3'; -const wchar_t UNICODE_REPLACEMENT = 0xFFFD; +constexpr wchar_t UNICODE_ETX = L'\x3'; +constexpr wchar_t UNICODE_REPLACEMENT = 0xFFFD; diff --git a/src/terminal/adapter/adaptDispatchGraphics.cpp b/src/terminal/adapter/adaptDispatchGraphics.cpp index 66e419b1c2..c258c2c446 100644 --- a/src/terminal/adapter/adaptDispatchGraphics.cpp +++ b/src/terminal/adapter/adaptDispatchGraphics.cpp @@ -14,26 +14,26 @@ using namespace Microsoft::Console::VirtualTerminal; using namespace Microsoft::Console::VirtualTerminal::DispatchTypes; // clang-format off -const BYTE BLUE_ATTR = 0x01; -const BYTE GREEN_ATTR = 0x02; -const BYTE RED_ATTR = 0x04; -const BYTE BRIGHT_ATTR = 0x08; -const BYTE DARK_BLACK = 0; -const BYTE DARK_RED = RED_ATTR; -const BYTE DARK_GREEN = GREEN_ATTR; -const BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR; -const BYTE DARK_BLUE = BLUE_ATTR; -const BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR; -const BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR; -const BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR; -const BYTE BRIGHT_BLACK = BRIGHT_ATTR; -const BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR; -const BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR; -const BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR; -const BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR; -const BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR; -const BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR; -const BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR; +constexpr BYTE BLUE_ATTR = 0x01; +constexpr BYTE GREEN_ATTR = 0x02; +constexpr BYTE RED_ATTR = 0x04; +constexpr BYTE BRIGHT_ATTR = 0x08; +constexpr BYTE DARK_BLACK = 0; +constexpr BYTE DARK_RED = RED_ATTR; +constexpr BYTE DARK_GREEN = GREEN_ATTR; +constexpr BYTE DARK_YELLOW = RED_ATTR | GREEN_ATTR; +constexpr BYTE DARK_BLUE = BLUE_ATTR; +constexpr BYTE DARK_MAGENTA = RED_ATTR | BLUE_ATTR; +constexpr BYTE DARK_CYAN = GREEN_ATTR | BLUE_ATTR; +constexpr BYTE DARK_WHITE = RED_ATTR | GREEN_ATTR | BLUE_ATTR; +constexpr BYTE BRIGHT_BLACK = BRIGHT_ATTR; +constexpr BYTE BRIGHT_RED = BRIGHT_ATTR | RED_ATTR; +constexpr BYTE BRIGHT_GREEN = BRIGHT_ATTR | GREEN_ATTR; +constexpr BYTE BRIGHT_YELLOW = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR; +constexpr BYTE BRIGHT_BLUE = BRIGHT_ATTR | BLUE_ATTR; +constexpr BYTE BRIGHT_MAGENTA = BRIGHT_ATTR | RED_ATTR | BLUE_ATTR; +constexpr BYTE BRIGHT_CYAN = BRIGHT_ATTR | GREEN_ATTR | BLUE_ATTR; +constexpr BYTE BRIGHT_WHITE = BRIGHT_ATTR | RED_ATTR | GREEN_ATTR | BLUE_ATTR; // clang-format on // Routine Description: diff --git a/src/terminal/input/mouseInput.cpp b/src/terminal/input/mouseInput.cpp index 5d9f7a7d6a..ec02b2513a 100644 --- a/src/terminal/input/mouseInput.cpp +++ b/src/terminal/input/mouseInput.cpp @@ -11,7 +11,7 @@ using namespace Microsoft::Console::VirtualTerminal; #ifdef BUILD_ONECORE_INTERACTIVITY #include "../../interactivity/inc/VtApiRedirection.hpp" #endif -static const int s_MaxDefaultCoordinate = 94; +static constexpr int s_MaxDefaultCoordinate = 94; // Alternate scroll sequences static constexpr std::wstring_view CursorUpSequence{ L"\x1b[A" }; diff --git a/src/terminal/input/terminalInput.cpp b/src/terminal/input/terminalInput.cpp index 1e63a7c8ef..7430345b4a 100644 --- a/src/terminal/input/terminalInput.cpp +++ b/src/terminal/input/terminalInput.cpp @@ -19,8 +19,6 @@ using namespace Microsoft::Console::VirtualTerminal; -DWORD const dwAltGrFlags = LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED; - TerminalInput::TerminalInput(_In_ std::function>&)> pfn) : _leadingSurrogate{} { diff --git a/src/terminal/parser/InputStateMachineEngine.hpp b/src/terminal/parser/InputStateMachineEngine.hpp index 390e7c4609..9d36ee8673 100644 --- a/src/terminal/parser/InputStateMachineEngine.hpp +++ b/src/terminal/parser/InputStateMachineEngine.hpp @@ -24,20 +24,20 @@ Author(s): namespace Microsoft::Console::VirtualTerminal { // The values used by VkKeyScan to encode modifiers in the high order byte - const short KEYSCAN_SHIFT = 1; - const short KEYSCAN_CTRL = 2; - const short KEYSCAN_ALT = 4; + constexpr short KEYSCAN_SHIFT = 1; + constexpr short KEYSCAN_CTRL = 2; + constexpr short KEYSCAN_ALT = 4; // The values with which VT encodes modifier values. - const short VT_SHIFT = 1; - const short VT_ALT = 2; - const short VT_CTRL = 4; + constexpr short VT_SHIFT = 1; + constexpr short VT_ALT = 2; + constexpr short VT_CTRL = 4; // The assumed values for SGR Mouse Scroll Wheel deltas constexpr DWORD SCROLL_DELTA_BACKWARD = 0xFF800000; constexpr DWORD SCROLL_DELTA_FORWARD = 0x00800000; - const size_t WRAPPED_SEQUENCE_MAX_LENGTH = 8; + constexpr size_t WRAPPED_SEQUENCE_MAX_LENGTH = 8; // For reference, the equivalent INPUT_RECORD values are: // RIGHT_ALT_PRESSED 0x0001 From 5a785666281df52a3e7ee23db40fddf49d8f3218 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 11:57:18 -0500 Subject: [PATCH 07/56] Make TerminalConnection depend on OpenConsoleProxy (#9649) Building code merged with `main` this morning, and I hit a error where the `TerminalConnection` project needed `ITerminalHandoff` something or other, but that hadn't been built yet. I suspect that's because the `OpenConsoleProxy` project needs to be built first, but it isn't set as a dependency. I suspect once that project is built once, this isn't ever an issue, but I hadn't done that yet. This fixed the build for me locally. * [x] fixes local dev builds * [x] also updates the name of the TerminalControl project in the .sln, because apparently VS didn't like that. --- OpenConsole.sln | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 459f5a76b6..bc9b5383e7 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -164,10 +164,13 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererDx", "src\renderer\dx\lib\dx.vcxproj", "{48D21369-3D7B-4431-9967-24E81292CF62}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalConnection", "src\cascadia\TerminalConnection\TerminalConnection.vcxproj", "{CA5CAD1A-C46D-4588-B1C0-40F31AE9100B}" + ProjectSection(ProjectDependencies) = postProject + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalCore", "src\cascadia\TerminalCore\lib\TerminalCore-lib.vcxproj", "{CA5CAD1A-ABCD-429C-B551-8562EC954746}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control.Lib", "src\cascadia\TerminalControl\TerminalControlLib.vcxproj", "{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} @@ -175,15 +178,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControlLib", "src\c {48D21369-3D7B-4431-9967-24E81292CF63} = {48D21369-3D7B-4431-9967-24E81292CF63} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalControl", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Control", "src\cascadia\TerminalControl\dll\TerminalControl.vcxproj", "{CA5CAD1A-F542-4635-A069-7CAEFB930070}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} = {CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminal", "src\cascadia\WindowsTerminal\WindowsTerminal.vcxproj", "{CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject - {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} {CA5CAD1A-ABCD-429C-B551-8562EC954746} = {CA5CAD1A-ABCD-429C-B551-8562EC954746} {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} @@ -194,9 +197,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-9A12-429C-B551-8562EC954746} = {CA5CAD1A-9A12-429C-B551-8562EC954746} {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} + {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} - {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}" @@ -246,8 +249,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalAppLib", "src\cascadia\TerminalApp\TerminalAppLib.vcxproj", "{CA5CAD1A-9A12-429C-B551-8562EC954746}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} - {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} = {CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_TerminalApp", "src\cascadia\LocalTests_TerminalApp\TerminalApp.LocalTests.vcxproj", "{CA5CAD1A-B11C-4DDB-A4FE-C3AFAE9B5506}" @@ -348,8 +351,8 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LocalTests_SettingsModel", "src\cascadia\LocalTests_SettingsModel\SettingsModel.LocalTests.vcxproj", "{CA5CAD1A-9B68-456A-B13E-C8218070DC42}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} - {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-F542-4635-A069-7CAEFB930070} = {CA5CAD1A-F542-4635-A069-7CAEFB930070} + {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} = {CA5CAD1A-C46D-4588-B1C0-40F31AE9100B} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} EndProjectSection EndProject From 704836e45d91acfc4a9f883fd15c3aea6f46a3db Mon Sep 17 00:00:00 2001 From: Don-Vito Date: Mon, 29 Mar 2021 20:23:09 +0300 Subject: [PATCH 08/56] Prevent arrow keys from dismissing tab renamer (#9633) ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/issues/9632 * [x] CLA signed. * [ ] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [ ] I've discussed this with core contributors already. --- src/cascadia/TerminalApp/TabHeaderControl.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TabHeaderControl.cpp b/src/cascadia/TerminalApp/TabHeaderControl.cpp index 37045dcb0d..47cb16ba29 100644 --- a/src/cascadia/TerminalApp/TabHeaderControl.cpp +++ b/src/cascadia/TerminalApp/TabHeaderControl.cpp @@ -18,8 +18,18 @@ namespace winrt::TerminalApp::implementation // We'll only process the KeyUp event if we received an initial KeyDown event first. // Avoids issue immediately closing the tab rename when we see the enter KeyUp event that was // sent to the command palette to trigger the openTabRenamer action in the first place. - HeaderRenamerTextBox().KeyDown([&](auto&&, auto&&) { + HeaderRenamerTextBox().KeyDown([&](auto&&, auto&& e) { _receivedKeyDown = true; + + // GH#9632 - mark navigation buttons as handled. + // This should prevent the tab view to use this key for navigation between tabs + if (e.OriginalKey() == Windows::System::VirtualKey::Down || + e.OriginalKey() == Windows::System::VirtualKey::Up || + e.OriginalKey() == Windows::System::VirtualKey::Left || + e.OriginalKey() == Windows::System::VirtualKey::Right) + { + e.Handled(true); + } }); // NOTE: (Preview)KeyDown does not work here. If you use that, we'll From 8470857016e910ca275cd9f25daa20e57754ca8f Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Mon, 29 Mar 2021 12:23:20 -0500 Subject: [PATCH 09/56] Fix the preview package manifest We missed this one. --- src/cascadia/CascadiaPackage/Package-Pre.appxmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index aac5b64f31..fd4ed234ce 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -109,7 +109,7 @@ - From ba543c06963c5f449d08636ee959aebc5073b3b1 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 14:53:39 -0500 Subject: [PATCH 10/56] minor refactor: Move Tab management into its own file (#9629) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I think we can all agree that `TerminalPage.cpp` is an unruly beast of a file. It's got everything. It does everything. It can sometimes be a bit hard to work with, because of simply how big it is. This PR tries to alleviate this by making `TerminalPage.cpp` just a little smaller. It does so by moving pretty much everything related to tab management into its own file, `TabManagement.cpp`. These methods that have moved are all the same as they were before, and they're still members of `TerminalPage`. But now they're all in one place. I tried to move all the references to `_tabs` in `TerminalPage.cpp`, but there's still a few that I left behind. Mostly because I felt that moving those would be too gnarly a code change for an otherwise simple cut&paste PR. There are a few new methods I introduced: * `_TabDragStarted` and `_TabDragCompleted`: These were lambdas before, promoted to full methods. * `_DismissTabContextMenus`: Remove all the right-click context menus from the tabs * `_FocusCurrentTab`: This one's a bit trickier, we were actually doing this in a few different places, so I tried consolidating. * `_HasMultipleTabs`: This doesn't need explaining. * `_RemoveAllTabs`: Really, just encapsulation for the sake of removing a `_tabs` from `TerminalPage.cpp` * `_ResizeTabContent`: Really, just encapsulation for the sake of removing a `_tabs` from `TerminalPage.cpp` In the future, some enterprising young soul could try promoting that file to its own class, and hiding `_tabs` (and `_mruTabs`) inside it. Probably would need to take a reference to TerminalPage's `_tabView` and `_newTabButton`. I'm not doing that right now, because I already hate the idea of the ... > 920 additions and 847 deletions. ... I'm making you look at already. ## Other thoughts Some of the calls might be a little arbitrary - `_OpenNewTab` and `_CreateNewTabFromSettings` probably should stay in `TerminalPage`? Or at least elements of those might need to get split up better. Similarly `TerminalPage::_OpenSettingsUI` stayed in `TerminalPage.cpp`, but it does a lot of the same work as `_CreateNewTabFromSettings`. I'm not saying this is the definitive places for these methods - it's code we're working with, not stone ☺️ --- src/cascadia/TerminalApp/TabManagement.cpp | 901 ++++++++++++++++++ .../TerminalApp/TerminalAppLib.vcxproj | 4 + src/cascadia/TerminalApp/TerminalPage.cpp | 859 +---------------- src/cascadia/TerminalApp/TerminalPage.h | 11 +- 4 files changed, 924 insertions(+), 851 deletions(-) create mode 100644 src/cascadia/TerminalApp/TabManagement.cpp diff --git a/src/cascadia/TerminalApp/TabManagement.cpp b/src/cascadia/TerminalApp/TabManagement.cpp new file mode 100644 index 0000000000..3199fdd67e --- /dev/null +++ b/src/cascadia/TerminalApp/TabManagement.cpp @@ -0,0 +1,901 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// This file contains much of the code related to tab management for the +// TerminalPage. Things like opening new tabs, selecting different tabs, +// switching tabs, should all be handled in this file. Hypothetically, in the +// future, the contents of this file could be moved to a separate class +// entirely. +// + +#include "pch.h" +#include "TerminalPage.h" +#include "Utils.h" +#include "../../types/inc/utils.hpp" + +#include + +#include "TabRowControl.h" +#include "ColorHelper.h" +#include "DebugTapConnection.h" +#include "SettingsTab.h" + +using namespace winrt; +using namespace winrt::Windows::Foundation::Collections; +using namespace winrt::Windows::UI::Xaml; +using namespace winrt::Windows::UI::Xaml::Controls; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::System; +using namespace winrt::Windows::ApplicationModel::DataTransfer; +using namespace winrt::Windows::UI::Text; +using namespace winrt::Microsoft::Terminal; +using namespace winrt::Microsoft::Terminal::Control; +using namespace winrt::Microsoft::Terminal::TerminalConnection; +using namespace winrt::Microsoft::Terminal::Settings::Model; +using namespace ::TerminalApp; +using namespace ::Microsoft::Console; + +namespace winrt +{ + namespace MUX = Microsoft::UI::Xaml; + namespace WUX = Windows::UI::Xaml; + using IInspectable = Windows::Foundation::IInspectable; +} + +namespace winrt::TerminalApp::implementation +{ + // Method Description: + // - Open a new tab. This will create the TerminalControl hosting the + // terminal, and add a new Tab to our list of tabs. The method can + // optionally be provided a NewTerminalArgs, which will be used to create + // a tab using the values in that object. + // Arguments: + // - newTerminalArgs: An object that may contain a blob of parameters to + // control which profile is created and with possible other + // configurations. See TerminalSettings::CreateWithNewTerminalArgs for more details. + // - existingConnection: An optional connection that is already established to a PTY + // for this tab to host instead of creating one. + // If not defined, the tab will create the connection. + void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) + try + { + const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) }; + const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) }; + + _CreateNewTabFromSettings(profileGuid, settings, existingConnection); + + const uint32_t tabCount = _tabs.Size(); + const bool usedManualProfile = (newTerminalArgs != nullptr) && + (newTerminalArgs.ProfileIndex() != nullptr || + newTerminalArgs.Profile().empty()); + + // Lookup the name of the color scheme used by this profile. + const auto scheme = _settings.GetColorSchemeForProfile(profileGuid); + // If they explicitly specified `null` as the scheme (indicating _no_ scheme), log + // that as the empty string. + const auto schemeName = scheme ? scheme.Name() : L"\0"; + + TraceLoggingWrite( + g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider + "TabInformation", + TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"), + TraceLoggingUInt32(1u, "EventVer", "Version of this event"), + TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"), + TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"), + TraceLoggingGuid(profileGuid, "ProfileGuid", "The GUID of the profile spawned in the new tab"), + TraceLoggingBool(settings.UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"), + TraceLoggingFloat64(settings.TintOpacity(), "TintOpacity", "Opacity preference from the settings"), + TraceLoggingWideString(settings.FontFace().c_str(), "FontFace", "Font face chosen in the settings"), + TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), + TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); + } + CATCH_LOG(); + + // Method Description: + // - Creates a new tab with the given settings. If the tab bar is not being + // currently displayed, it will be shown. + // Arguments: + // - profileGuid: ID to use to lookup profile settings for this connection + // - settings: the TerminalSettings object to use to create the TerminalControl with. + // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one + void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, TerminalConnection::ITerminalConnection existingConnection) + { + // Initialize the new tab + // Create a connection based on the values in our settings object if we weren't given one. + auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); + + TerminalConnection::ITerminalConnection debugConnection{ nullptr }; + if (_settings.GlobalSettings().DebugFeaturesEnabled()) + { + const CoreWindow window = CoreWindow::GetForCurrentThread(); + const auto rAltState = window.GetKeyState(VirtualKey::RightMenu); + const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu); + const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) && + WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); + if (bothAltsPressed) + { + std::tie(connection, debugConnection) = OpenDebugTapConnection(connection); + } + } + + // Give term control a child of the settings so that any overrides go in the child + // This way, when we do a settings reload we just update the parent and the overrides remain + auto term = _InitControl(settings, connection); + + auto newTabImpl = winrt::make_self(profileGuid, term); + + // Add the new tab to the list of our tabs. + _tabs.Append(*newTabImpl); + _mruTabs.Append(*newTabImpl); + + newTabImpl->SetDispatch(*_actionDispatch); + newTabImpl->SetKeyMap(_settings.KeyMap()); + + // Give the tab its index in the _tabs vector so it can manage its own SwitchToTab command. + _UpdateTabIndices(); + + // Hookup our event handlers to the new terminal + _RegisterTerminalEvents(term, *newTabImpl); + + // Don't capture a strong ref to the tab. If the tab is removed as this + // is called, we don't really care anymore about handling the event. + auto weakTab = make_weak(newTabImpl); + + // When the tab's active pane changes, we'll want to lookup a new icon + // for it. The Title change will be propagated upwards through the tab's + // PropertyChanged event handler. + newTabImpl->ActivePaneChanged([weakTab, weakThis{ get_weak() }]() { + auto page{ weakThis.get() }; + auto tab{ weakTab.get() }; + + if (page && tab) + { + // Possibly update the icon of the tab. + page->_UpdateTabIcon(*tab); + } + }); + + // The RaiseVisualBell event has been bubbled up to here from the pane, + // the next part of the chain is bubbling up to app logic, which will + // forward it to app host. + newTabImpl->TabRaiseVisualBell([weakTab, weakThis{ get_weak() }]() { + auto page{ weakThis.get() }; + auto tab{ weakTab.get() }; + + if (page && tab) + { + page->_RaiseVisualBellHandlers(nullptr, nullptr); + } + }); + + newTabImpl->DuplicateRequested([weakTab, weakThis{ get_weak() }]() { + auto page{ weakThis.get() }; + auto tab{ weakTab.get() }; + + if (page && tab) + { + page->_DuplicateTab(*tab); + } + }); + + auto tabViewItem = newTabImpl->TabViewItem(); + _tabView.TabItems().Append(tabViewItem); + + // Set this tab's icon to the icon from the user's profile + const auto profile = _settings.FindProfile(profileGuid); + if (profile != nullptr && !profile.Icon().empty()) + { + newTabImpl->UpdateIcon(profile.Icon()); + } + + tabViewItem.PointerPressed({ this, &TerminalPage::_OnTabClick }); + + // When the tab is closed, remove it from our list of tabs. + newTabImpl->Closed([tabViewItem, weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) { + if (auto page{ weakThis.get() }) + { + page->_RemoveOnCloseRoutine(tabViewItem, page); + } + }); + + newTabImpl->TabRenamerDeactivated([weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) { + if (const auto page{ weakThis.get() }) + { + page->_FocusCurrentTab(false); + } + }); + + if (debugConnection) // this will only be set if global debugging is on and tap is active + { + auto newControl = _InitControl(settings, debugConnection); + _RegisterTerminalEvents(newControl, *newTabImpl); + // Split (auto) with the debug tap. + newTabImpl->SplitPane(SplitState::Automatic, 0.5f, profileGuid, newControl); + } + + // This kicks off TabView::SelectionChanged, in response to which + // we'll attach the terminal's Xaml control to the Xaml root. + _tabView.SelectedItem(tabViewItem); + } + + // Method Description: + // - Get the icon of the currently focused terminal control, and set its + // tab's icon to that icon. + // Arguments: + // - tab: the Tab to update the title for. + void TerminalPage::_UpdateTabIcon(TerminalTab& tab) + { + const auto lastFocusedProfileOpt = tab.GetFocusedProfile(); + if (lastFocusedProfileOpt.has_value()) + { + const auto lastFocusedProfile = lastFocusedProfileOpt.value(); + const auto matchingProfile = _settings.FindProfile(lastFocusedProfile); + if (matchingProfile) + { + tab.UpdateIcon(matchingProfile.Icon()); + } + else + { + tab.UpdateIcon({}); + } + } + } + + // Method Description: + // - Handle changes to the tab width set by the user + void TerminalPage::_UpdateTabWidthMode() + { + _tabView.TabWidthMode(_settings.GlobalSettings().TabWidthMode()); + } + + // Method Description: + // - Handle changes in tab layout. + void TerminalPage::_UpdateTabView() + { + // Never show the tab row when we're fullscreen. Otherwise: + // Show tabs when there's more than 1, or the user has chosen to always + // show the tab bar. + const bool isVisible = (!_isFullscreen && !_isInFocusMode) && + (_settings.GlobalSettings().ShowTabsInTitlebar() || + (_tabs.Size() > 1) || + _settings.GlobalSettings().AlwaysShowTabs()); + + // collapse/show the tabs themselves + _tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed); + + // collapse/show the row that the tabs are in. + // NaN is the special value XAML uses for "Auto" sizing. + _tabRow.Height(isVisible ? NAN : 0); + } + + // Method Description: + // - Duplicates the current focused tab + void TerminalPage::_DuplicateFocusedTab() + { + if (const auto terminalTab{ _GetFocusedTabImpl() }) + { + _DuplicateTab(*terminalTab); + } + } + + // Method Description: + // - Duplicates specified tab + // Arguments: + // - tab: tab to duplicate + void TerminalPage::_DuplicateTab(const TerminalTab& tab) + { + try + { + // TODO: GH#5047 - In the future, we should get the Profile of + // the focused pane, and use that to build a new instance of the + // settings so we can duplicate this tab/pane. + // + // Currently, if the profile doesn't exist anymore in our + // settings, we'll silently do nothing. + // + // In the future, it will be preferable to just duplicate the + // current control's settings, but we can't do that currently, + // because we won't be able to create a new instance of the + // connection without keeping an instance of the original Profile + // object around. + + const auto& profileGuid = tab.GetFocusedProfile(); + if (profileGuid.has_value()) + { + const auto settings{ TerminalSettings::CreateWithProfileByID(_settings, profileGuid.value(), *_bindings) }; + const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); + const auto validWorkingDirectory = !workingDirectory.empty(); + if (validWorkingDirectory) + { + settings.StartingDirectory(workingDirectory); + } + + _CreateNewTabFromSettings(profileGuid.value(), settings); + } + } + CATCH_LOG(); + } + + // Method Description: + // - Look for the index of the input tabView in the tabs vector, + // and call _RemoveTab + // Arguments: + // - tabViewItem: the TabViewItem in the TabView that is being removed. + void TerminalPage::_RemoveTabViewItem(const MUX::Controls::TabViewItem& tabViewItem) + { + uint32_t tabIndexFromControl = 0; + if (_tabView.TabItems().IndexOf(tabViewItem, tabIndexFromControl)) + { + // If IndexOf returns true, we've actually got an index + auto tab{ _tabs.GetAt(tabIndexFromControl) }; + _RemoveTab(tab); + } + } + + // Method Description: + // - Removes the tab (both TerminalControl and XAML) + // Arguments: + // - tab: the tab to remove + winrt::Windows::Foundation::IAsyncAction TerminalPage::_RemoveTab(winrt::TerminalApp::TabBase tab) + { + if (tab.ReadOnly()) + { + ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog(); + + // If the user didn't explicitly click on close tab - leave + if (warningResult != ContentDialogResult::Primary) + { + co_return; + } + } + + uint32_t tabIndex{}; + if (!_tabs.IndexOf(tab, tabIndex)) + { + // The tab is already removed + co_return; + } + + // We use _removing flag to suppress _OnTabSelectionChanged events + // that might get triggered while removing + _removing = true; + auto unsetRemoving = wil::scope_exit([&]() noexcept { _removing = false; }); + + const auto focusedTabIndex{ _GetFocusedTabIndex() }; + + // Removing the tab from the collection should destroy its control and disconnect its connection, + // but it doesn't always do so. The UI tree may still be holding the control and preventing its destruction. + tab.Shutdown(); + + uint32_t mruIndex{}; + if (_mruTabs.IndexOf(tab, mruIndex)) + { + _mruTabs.RemoveAt(mruIndex); + } + + _tabs.RemoveAt(tabIndex); + _tabView.TabItems().RemoveAt(tabIndex); + _UpdateTabIndices(); + + // To close the window here, we need to close the hosting window. + if (_tabs.Size() == 0) + { + _LastTabClosedHandlers(*this, nullptr); + } + else if (focusedTabIndex.has_value() && focusedTabIndex.value() == gsl::narrow_cast(tabIndex)) + { + // Manually select the new tab to get focus, rather than relying on TabView since: + // 1. We want to customize this behavior (e.g., use MRU logic) + // 2. In fullscreen (GH#5799) and focus (GH#7916) modes the _OnTabItemsChanged is not fired + // 3. When rearranging tabs (GH#7916) _OnTabItemsChanged is suppressed + const auto tabSwitchMode = _settings.GlobalSettings().TabSwitcherMode(); + + if (tabSwitchMode == TabSwitcherMode::MostRecentlyUsed) + { + const auto newSelectedTab = _mruTabs.GetAt(0); + + uint32_t newSelectedIndex; + if (_tabs.IndexOf(newSelectedTab, newSelectedIndex)) + { + _UpdatedSelectedTab(newSelectedIndex); + _tabView.SelectedItem(newSelectedTab.TabViewItem()); + } + } + else + { + // We can't use + // auto selectedIndex = _tabView.SelectedIndex(); + // Because this will always return -1 in this scenario unfortunately. + // + // So, what we're going to try to do is move the focus to the tab + // to the left, within the bounds of how many tabs we have. + // + // EX: we have 4 tabs: [A, B, C, D]. If we close: + // * A (tabIndex=0): We'll want to focus tab B (now in index 0) + // * B (tabIndex=1): We'll want to focus tab A (now in index 0) + // * C (tabIndex=2): We'll want to focus tab B (now in index 1) + // * D (tabIndex=3): We'll want to focus tab C (now in index 2) + const auto newSelectedIndex = std::clamp(tabIndex - 1, 0, _tabs.Size()); + // _UpdatedSelectedTab will do the work of setting up the new tab as + // the focused one, and unfocusing all the others. + _UpdatedSelectedTab(newSelectedIndex); + + // Also, we need to _manually_ set the SelectedItem of the tabView + // here. If we don't, then the TabView will technically not have a + // selected item at all, which can make things like ClosePane not + // work correctly. + auto newSelectedTab{ _tabs.GetAt(newSelectedIndex) }; + _tabView.SelectedItem(newSelectedTab.TabViewItem()); + } + } + + // GH#5559 - If we were in the middle of a drag/drop, end it by clearing + // out our state. + if (_rearranging) + { + _rearranging = false; + _rearrangeFrom = std::nullopt; + _rearrangeTo = std::nullopt; + } + + co_return; + } + + // Method Description: + // - Sets focus to the tab to the right or left the currently selected tab. + void TerminalPage::_SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference& customTabSwitcherMode) + { + const auto index{ _GetFocusedTabIndex().value_or(0) }; + const auto tabSwitchMode = customTabSwitcherMode ? customTabSwitcherMode.Value() : _settings.GlobalSettings().TabSwitcherMode(); + if (tabSwitchMode == TabSwitcherMode::Disabled) + { + uint32_t tabCount = _tabs.Size(); + // Wraparound math. By adding tabCount and then calculating + // modulo tabCount, we clamp the values to the range [0, + // tabCount) while still supporting moving leftward from 0 to + // tabCount - 1. + const auto newTabIndex = ((tabCount + index + (bMoveRight ? 1 : -1)) % tabCount); + _SelectTab(newTabIndex); + } + else + { + CommandPalette().SetTabs(_tabs, _mruTabs); + + // Otherwise, set up the tab switcher in the selected mode, with + // the given ordering, and make it visible. + CommandPalette().EnableTabSwitcherMode(index, tabSwitchMode); + CommandPalette().Visibility(Visibility::Visible); + CommandPalette().SelectNextItem(bMoveRight); + } + } + + // Method Description: + // - Sets focus to the desired tab. Returns false if the provided tabIndex + // is greater than the number of tabs we have. + // - During startup, we'll immediately set the selected tab as focused. + // - After startup, we'll dispatch an async method to set the the selected + // item of the TabView, which will then also trigger a + // TabView::SelectionChanged, handled in + // TerminalPage::_OnTabSelectionChanged + // Return Value: + // true iff we were able to select that tab index, false otherwise + bool TerminalPage::_SelectTab(const uint32_t tabIndex) + { + if (tabIndex >= 0 && tabIndex < _tabs.Size()) + { + if (_startupState == StartupState::InStartup) + { + auto tab{ _tabs.GetAt(tabIndex) }; + _tabView.SelectedItem(tab.TabViewItem()); + _UpdatedSelectedTab(tabIndex); + } + else + { + _SetFocusedTabIndex(tabIndex); + } + + return true; + } + return false; + } + + // Method Description: + // - This method is called once a tab was selected in tab switcher + // We'll use this event to select the relevant tab + // Arguments: + // - tab - tab to select + // Return Value: + // - + void TerminalPage::_OnSwitchToTabRequested(const IInspectable& /*sender*/, const winrt::TerminalApp::TabBase& tab) + { + uint32_t index{}; + if (_tabs.IndexOf(tab, index)) + { + _SelectTab(index); + } + } + + // Method Description: + // - Returns the index in our list of tabs of the currently focused tab. If + // no tab is currently selected, returns nullopt. + // Return Value: + // - the index of the currently focused tab if there is one, else nullopt + std::optional TerminalPage::_GetFocusedTabIndex() const noexcept + { + // GH#1117: This is a workaround because _tabView.SelectedIndex() + // sometimes return incorrect result after removing some tabs + uint32_t focusedIndex; + if (_tabView.TabItems().IndexOf(_tabView.SelectedItem(), focusedIndex)) + { + return focusedIndex; + } + return std::nullopt; + } + + // Method Description: + // - returns a com_ptr to the currently focused tab. This might return null, + // so make sure to check the result! + winrt::TerminalApp::TabBase TerminalPage::_GetFocusedTab() const noexcept + { + if (auto index{ _GetFocusedTabIndex() }) + { + return _tabs.GetAt(*index); + } + return nullptr; + } + + // Method Description: + // - returns a com_ptr to the currently focused tab implementation. This might return null, + // so make sure to check the result! + winrt::com_ptr TerminalPage::_GetFocusedTabImpl() const noexcept + { + if (auto tab{ _GetFocusedTab() }) + { + return _GetTerminalTabImpl(tab); + } + return nullptr; + } + + // Method Description: + // - An async method for changing the focused tab on the UI thread. This + // method will _only_ set the selected item of the TabView, which will + // then also trigger a TabView::SelectionChanged event, which we'll handle + // in TerminalPage::_OnTabSelectionChanged, where we'll mark the new tab + // as focused. + // Arguments: + // - tabIndex: the index in the list of tabs to focus. + // Return Value: + // - + winrt::fire_and_forget TerminalPage::_SetFocusedTabIndex(const uint32_t tabIndex) + { + // GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex) + // sometimes set focus to an incorrect tab after removing some tabs + auto weakThis{ get_weak() }; + + co_await winrt::resume_foreground(_tabView.Dispatcher()); + + if (auto page{ weakThis.get() }) + { + auto tabToFocus = page->_tabs.GetAt(tabIndex); + _tabView.SelectedItem(tabToFocus.TabViewItem()); + } + } + + // Method Description: + // - Close the currently focused tab. Focus will move to the left, if possible. + void TerminalPage::_CloseFocusedTab() + { + if (auto index{ _GetFocusedTabIndex() }) + { + auto tab{ _tabs.GetAt(*index) }; + _RemoveTab(tab); + } + } + + // Method Description: + // - Close the currently focused pane. If the pane is the last pane in the + // tab, the tab will also be closed. This will happen when we handle the + // tab's Closed event. + winrt::fire_and_forget TerminalPage::_CloseFocusedPane() + { + if (const auto terminalTab{ _GetFocusedTabImpl() }) + { + _UnZoomIfNeeded(); + + auto pane = terminalTab->GetActivePane(); + + if (const auto pane{ terminalTab->GetActivePane() }) + { + if (const auto control{ pane->GetTerminalControl() }) + { + if (control.ReadOnly()) + { + ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog(); + + // If the user didn't explicitly click on close tab - leave + if (warningResult != ContentDialogResult::Primary) + { + co_return; + } + + // Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab + if (control.ReadOnly()) + { + control.ToggleReadOnly(); + } + } + + pane->Close(); + } + } + } + else if (auto index{ _GetFocusedTabIndex() }) + { + const auto tab{ _tabs.GetAt(*index) }; + if (tab.try_as()) + { + _RemoveTab(tab); + } + } + } + + // Method Description: + // - Closes provided tabs one by one + // Arguments: + // - tabs - tabs to remove + winrt::fire_and_forget TerminalPage::_RemoveTabs(const std::vector tabs) + { + for (auto& tab : tabs) + { + co_await _RemoveTab(tab); + } + } + // Method Description: + // - Responds to changes in the TabView's item list by changing the + // tabview's visibility. + // - This method is also invoked when tabs are dragged / dropped as part of + // tab reordering and this method hands that case as well in concert with + // TabDragStarting and TabDragCompleted handlers that are set up in + // TerminalPage::Create() + // Arguments: + // - sender: the control that originated this event + // - eventArgs: the event's constituent arguments + void TerminalPage::_OnTabItemsChanged(const IInspectable& /*sender*/, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs) + { + if (_rearranging) + { + if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemRemoved) + { + _rearrangeFrom = eventArgs.Index(); + } + + if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemInserted) + { + _rearrangeTo = eventArgs.Index(); + } + } + + CommandPalette().Visibility(Visibility::Collapsed); + _UpdateTabView(); + } + + // Method Description: + // - Additional responses to clicking on a TabView's item. Currently, just remove tab with middle click + // Arguments: + // - sender: the control that originated this event (TabViewItem) + // - eventArgs: the event's constituent arguments + void TerminalPage::_OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs) + { + if (eventArgs.GetCurrentPoint(*this).Properties().IsMiddleButtonPressed()) + { + _RemoveTabViewItem(sender.as()); + eventArgs.Handled(true); + } + else if (eventArgs.GetCurrentPoint(*this).Properties().IsRightButtonPressed()) + { + eventArgs.Handled(true); + } + } + + void TerminalPage::_UpdatedSelectedTab(const int32_t index) + { + // Unfocus all the tabs. + for (auto tab : _tabs) + { + tab.Focus(FocusState::Unfocused); + } + + if (index >= 0) + { + try + { + auto tab{ _tabs.GetAt(index) }; + + _tabContent.Children().Clear(); + _tabContent.Children().Append(tab.Content()); + + // GH#7409: If the tab switcher is open, then we _don't_ want to + // automatically focus the new tab here. The tab switcher wants + // to be able to "preview" the selected tab as the user tabs + // through the menu, but if we toss the focus to the control + // here, then the user won't be able to navigate the ATS any + // longer. + // + // When the tab switcher is eventually dismissed, the focus will + // get tossed back to the focused terminal control, so we don't + // need to worry about focus getting lost. + if (CommandPalette().Visibility() != Visibility::Visible) + { + tab.Focus(FocusState::Programmatic); + _UpdateMRUTab(index); + } + + tab.TabViewItem().StartBringIntoView(); + + // Raise an event that our title changed + if (_settings.GlobalSettings().ShowTitleInTitlebar()) + { + _TitleChangedHandlers(*this, tab.Title()); + } + } + CATCH_LOG(); + } + } + + // Method Description: + // - Responds to the TabView control's Selection Changed event (to move a + // new terminal control into focus) when not in in the middle of a tab rearrangement. + // Arguments: + // - sender: the control that originated this event + // - eventArgs: the event's constituent arguments + void TerminalPage::_OnTabSelectionChanged(const IInspectable& sender, const WUX::Controls::SelectionChangedEventArgs& /*eventArgs*/) + { + if (!_rearranging && !_removing) + { + auto tabView = sender.as(); + auto selectedIndex = tabView.SelectedIndex(); + _UpdatedSelectedTab(selectedIndex); + } + } + + // Method Description: + // - Updates all tabs with their current index in _tabs. + // Arguments: + // - + // Return Value: + // - + void TerminalPage::_UpdateTabIndices() + { + const uint32_t size = _tabs.Size(); + for (uint32_t i = 0; i < size; ++i) + { + auto tab{ _tabs.GetAt(i) }; + auto tabImpl{ winrt::get_self(tab) }; + tabImpl->UpdateTabViewIndex(i, size); + } + } + + // Method Description: + // - Bumps the tab in its in-order index up to the top of the mru list. + // Arguments: + // - index: the in-order index of the tab to bump. + // Return Value: + // - + void TerminalPage::_UpdateMRUTab(const uint32_t index) + { + uint32_t mruIndex; + const auto tab = _tabs.GetAt(index); + if (_mruTabs.IndexOf(tab, mruIndex)) + { + if (mruIndex > 0) + { + _mruTabs.RemoveAt(mruIndex); + _mruTabs.InsertAt(0, tab); + } + } + } + + // Method Description: + // - Moves the tab to another index in the tabs row (if required). + // Arguments: + // - currentTabIndex: the current index of the tab to move + // - suggestedNewTabIndex: the new index of the tab, might get clamped to fit int the tabs row boundaries + // Return Value: + // - + void TerminalPage::_TryMoveTab(const uint32_t currentTabIndex, const int32_t suggestedNewTabIndex) + { + auto newTabIndex = gsl::narrow_cast(std::clamp(suggestedNewTabIndex, 0, _tabs.Size() - 1)); + if (currentTabIndex != newTabIndex) + { + auto tab = _tabs.GetAt(currentTabIndex); + auto tabViewItem = tab.TabViewItem(); + _tabs.RemoveAt(currentTabIndex); + _tabs.InsertAt(newTabIndex, tab); + _UpdateTabIndices(); + + _tabView.TabItems().RemoveAt(currentTabIndex); + _tabView.TabItems().InsertAt(newTabIndex, tabViewItem); + _tabView.SelectedItem(tabViewItem); + } + } + + void TerminalPage::_TabDragStarted(const IInspectable& /*sender*/, + const IInspectable& /*eventArgs*/) + { + _rearranging = true; + _rearrangeFrom = std::nullopt; + _rearrangeTo = std::nullopt; + } + + void TerminalPage::_TabDragCompleted(const IInspectable& /*sender*/, + const IInspectable& /*eventArgs*/) + { + auto& from{ _rearrangeFrom }; + auto& to{ _rearrangeTo }; + + if (from.has_value() && to.has_value() && to != from) + { + auto& tabs{ _tabs }; + auto tab = tabs.GetAt(from.value()); + tabs.RemoveAt(from.value()); + tabs.InsertAt(to.value(), tab); + _UpdateTabIndices(); + } + + _rearranging = false; + from = std::nullopt; + to = std::nullopt; + } + + void TerminalPage::_DismissTabContextMenus() + { + for (const auto& tab : _tabs) + { + if (tab.TabViewItem().ContextFlyout()) + { + tab.TabViewItem().ContextFlyout().Hide(); + } + } + } + + void TerminalPage::_FocusCurrentTab(const bool focusAlways) + { + // We don't want to set focus on the tab if fly-out is open as it will + // be closed TODO GH#5400: consider checking we are not in the opening + // state, by hooking both Opening and Open events + if (focusAlways || !_newTabButton.Flyout().IsOpen()) + { + // Return focus to the active control + if (auto index{ _GetFocusedTabIndex() }) + { + _tabs.GetAt(*index).Focus(FocusState::Programmatic); + _UpdateMRUTab(index.value()); + } + } + } + + bool TerminalPage::_HasMultipleTabs() const + { + return _tabs.Size() > 1; + } + + void TerminalPage::_RemoveAllTabs() + { + // Since _RemoveTab is asynchronous, create a snapshot of the tabs we want to remove + std::vector tabsToRemove; + std::copy(begin(_tabs), end(_tabs), std::back_inserter(tabsToRemove)); + _RemoveTabs(tabsToRemove); + } + + void TerminalPage::_ResizeTabContent(const winrt::Windows::Foundation::Size& newSize) + { + for (auto tab : _tabs) + { + if (auto terminalTab = _GetTerminalTabImpl(tab)) + { + terminalTab->ResizeContent(newSize); + } + } + } +} diff --git a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj index a37fe1de6f..3afff5cd2d 100644 --- a/src/cascadia/TerminalApp/TerminalAppLib.vcxproj +++ b/src/cascadia/TerminalApp/TerminalAppLib.vcxproj @@ -171,6 +171,10 @@ TerminalPage.xaml Code + + TerminalPage.xaml + Code + TerminalTabStatus.idl Code diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 0475725751..c2fc032b29 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -143,36 +143,8 @@ namespace winrt::TerminalApp::implementation _tabRow.PointerMoved({ get_weak(), &TerminalPage::_RestorePointerCursorHandler }); _tabView.CanReorderTabs(!isElevated); _tabView.CanDragTabs(!isElevated); - - _tabView.TabDragStarting([weakThis{ get_weak() }](auto&& /*o*/, auto&& /*a*/) { - if (auto page{ weakThis.get() }) - { - page->_rearranging = true; - page->_rearrangeFrom = std::nullopt; - page->_rearrangeTo = std::nullopt; - } - }); - - _tabView.TabDragCompleted([weakThis{ get_weak() }](auto&& /*o*/, auto&& /*a*/) { - if (auto page{ weakThis.get() }) - { - auto& from{ page->_rearrangeFrom }; - auto& to{ page->_rearrangeTo }; - - if (from.has_value() && to.has_value() && to != from) - { - auto& tabs{ page->_tabs }; - auto tab = tabs.GetAt(from.value()); - tabs.RemoveAt(from.value()); - tabs.InsertAt(to.value(), tab); - page->_UpdateTabIndices(); - } - - page->_rearranging = false; - from = std::nullopt; - to = std::nullopt; - } - }); + _tabView.TabDragStarting({ get_weak(), &TerminalPage::_TabDragStarted }); + _tabView.TabDragCompleted({ get_weak(), &TerminalPage::_TabDragCompleted }); auto tabRowImpl = winrt::get_self(_tabRow); _newTabButton = tabRowImpl->NewTabButton(); @@ -313,22 +285,6 @@ namespace winrt::TerminalApp::implementation _actionDispatch->DoAction(actionAndArgs); } - // Method Description: - // - This method is called once a tab was selected in tab switcher - // We'll use this event to select the relevant tab - // Arguments: - // - tab - tab to select - // Return Value: - // - - void TerminalPage::_OnSwitchToTabRequested(const IInspectable& /*sender*/, const winrt::TerminalApp::TabBase& tab) - { - uint32_t index{}; - if (_tabs.IndexOf(tab, index)) - { - _SelectTab(index); - } - } - // Method Description: // - This method is called once on startup, on the first LayoutUpdated event. // We'll use this event to know that we have an ActualWidth and @@ -740,11 +696,7 @@ namespace winrt::TerminalApp::implementation // e.g., the command palette will be dismissed by the menu, // and then closing the fly-out will move the focus to wrong location. newTabFlyout.Opening([this](auto&&, auto&&) { - if (auto index{ _GetFocusedTabIndex() }) - { - _tabs.GetAt(*index).Focus(FocusState::Programmatic); - _UpdateMRUTab(index.value()); - } + _FocusCurrentTab(true); }); _newTabButton.Flyout(newTabFlyout); } @@ -760,54 +712,6 @@ namespace winrt::TerminalApp::implementation _newTabButton.Flyout().ShowAt(_newTabButton, options); } - // Method Description: - // - Open a new tab. This will create the TerminalControl hosting the - // terminal, and add a new Tab to our list of tabs. The method can - // optionally be provided a NewTerminalArgs, which will be used to create - // a tab using the values in that object. - // Arguments: - // - newTerminalArgs: An object that may contain a blob of parameters to - // control which profile is created and with possible other - // configurations. See TerminalSettings::CreateWithNewTerminalArgs for more details. - // - existingConnection: An optional connection that is already established to a PTY - // for this tab to host instead of creating one. - // If not defined, the tab will create the connection. - void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) - try - { - const auto profileGuid{ _settings.GetProfileForArgs(newTerminalArgs) }; - const auto settings{ TerminalSettings::CreateWithNewTerminalArgs(_settings, newTerminalArgs, *_bindings) }; - - _CreateNewTabFromSettings(profileGuid, settings, existingConnection); - - const uint32_t tabCount = _tabs.Size(); - const bool usedManualProfile = (newTerminalArgs != nullptr) && - (newTerminalArgs.ProfileIndex() != nullptr || - newTerminalArgs.Profile().empty()); - - // Lookup the name of the color scheme used by this profile. - const auto scheme = _settings.GetColorSchemeForProfile(profileGuid); - // If they explicitly specified `null` as the scheme (indicating _no_ scheme), log - // that as the empty string. - const auto schemeName = scheme ? scheme.Name() : L"\0"; - - TraceLoggingWrite( - g_hTerminalAppProvider, // handle to TerminalApp tracelogging provider - "TabInformation", - TraceLoggingDescription("Event emitted upon new tab creation in TerminalApp"), - TraceLoggingUInt32(1u, "EventVer", "Version of this event"), - TraceLoggingUInt32(tabCount, "TabCount", "Count of tabs currently opened in TerminalApp"), - TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"), - TraceLoggingGuid(profileGuid, "ProfileGuid", "The GUID of the profile spawned in the new tab"), - TraceLoggingBool(settings.UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"), - TraceLoggingFloat64(settings.TintOpacity(), "TintOpacity", "Opacity preference from the settings"), - TraceLoggingWideString(settings.FontFace().c_str(), "FontFace", "Font face chosen in the settings"), - TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"), - TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), - TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance)); - } - CATCH_LOG(); - winrt::fire_and_forget TerminalPage::_RemoveOnCloseRoutine(Microsoft::UI::Xaml::Controls::TabViewItem tabViewItem, winrt::com_ptr page) { co_await winrt::resume_foreground(page->_tabView.Dispatcher()); @@ -815,139 +719,6 @@ namespace winrt::TerminalApp::implementation page->_RemoveTabViewItem(tabViewItem); } - // Method Description: - // - Creates a new tab with the given settings. If the tab bar is not being - // currently displayed, it will be shown. - // Arguments: - // - profileGuid: ID to use to lookup profile settings for this connection - // - settings: the TerminalSettings object to use to create the TerminalControl with. - // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one - void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, TerminalConnection::ITerminalConnection existingConnection) - { - // Initialize the new tab - // Create a connection based on the values in our settings object if we weren't given one. - auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); - - TerminalConnection::ITerminalConnection debugConnection{ nullptr }; - if (_settings.GlobalSettings().DebugFeaturesEnabled()) - { - const CoreWindow window = CoreWindow::GetForCurrentThread(); - const auto rAltState = window.GetKeyState(VirtualKey::RightMenu); - const auto lAltState = window.GetKeyState(VirtualKey::LeftMenu); - const bool bothAltsPressed = WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) && - WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down); - if (bothAltsPressed) - { - std::tie(connection, debugConnection) = OpenDebugTapConnection(connection); - } - } - - // Give term control a child of the settings so that any overrides go in the child - // This way, when we do a settings reload we just update the parent and the overrides remain - auto term = _InitControl(settings, connection); - - auto newTabImpl = winrt::make_self(profileGuid, term); - - // Add the new tab to the list of our tabs. - _tabs.Append(*newTabImpl); - _mruTabs.Append(*newTabImpl); - - newTabImpl->SetDispatch(*_actionDispatch); - newTabImpl->SetKeyMap(_settings.KeyMap()); - - // Give the tab its index in the _tabs vector so it can manage its own SwitchToTab command. - _UpdateTabIndices(); - - // Hookup our event handlers to the new terminal - _RegisterTerminalEvents(term, *newTabImpl); - - // Don't capture a strong ref to the tab. If the tab is removed as this - // is called, we don't really care anymore about handling the event. - auto weakTab = make_weak(newTabImpl); - - // When the tab's active pane changes, we'll want to lookup a new icon - // for it. The Title change will be propagated upwards through the tab's - // PropertyChanged event handler. - newTabImpl->ActivePaneChanged([weakTab, weakThis{ get_weak() }]() { - auto page{ weakThis.get() }; - auto tab{ weakTab.get() }; - - if (page && tab) - { - // Possibly update the icon of the tab. - page->_UpdateTabIcon(*tab); - } - }); - - // The RaiseVisualBell event has been bubbled up to here from the pane, - // the next part of the chain is bubbling up to app logic, which will - // forward it to app host. - newTabImpl->TabRaiseVisualBell([weakTab, weakThis{ get_weak() }]() { - auto page{ weakThis.get() }; - auto tab{ weakTab.get() }; - - if (page && tab) - { - page->_RaiseVisualBellHandlers(nullptr, nullptr); - } - }); - - newTabImpl->DuplicateRequested([weakTab, weakThis{ get_weak() }]() { - auto page{ weakThis.get() }; - auto tab{ weakTab.get() }; - - if (page && tab) - { - page->_DuplicateTab(*tab); - } - }); - - auto tabViewItem = newTabImpl->TabViewItem(); - _tabView.TabItems().Append(tabViewItem); - - // Set this tab's icon to the icon from the user's profile - const auto profile = _settings.FindProfile(profileGuid); - if (profile != nullptr && !profile.Icon().empty()) - { - newTabImpl->UpdateIcon(profile.Icon()); - } - - tabViewItem.PointerPressed({ this, &TerminalPage::_OnTabClick }); - - // When the tab is closed, remove it from our list of tabs. - newTabImpl->Closed([tabViewItem, weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) { - if (auto page{ weakThis.get() }) - { - page->_RemoveOnCloseRoutine(tabViewItem, page); - } - }); - - newTabImpl->TabRenamerDeactivated([weakThis{ get_weak() }](auto&& /*s*/, auto&& /*e*/) { - if (const auto page{ weakThis.get() }) - { - if (!page->_newTabButton.Flyout().IsOpen()) - { - if (const auto tab{ page->_GetFocusedTab() }) - { - tab.Focus(FocusState::Programmatic); - } - } - } - }); - - if (debugConnection) // this will only be set if global debugging is on and tap is active - { - auto newControl = _InitControl(settings, debugConnection); - _RegisterTerminalEvents(newControl, *newTabImpl); - // Split (auto) with the debug tap. - newTabImpl->SplitPane(SplitState::Automatic, 0.5f, profileGuid, newControl); - } - - // This kicks off TabView::SelectionChanged, in response to which - // we'll attach the terminal's Xaml control to the Xaml root. - _tabView.SelectedItem(tabViewItem); - } - // Method Description: // - Creates a new connection based on the profile settings // Arguments: @@ -1231,229 +1002,6 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: - // - Get the icon of the currently focused terminal control, and set its - // tab's icon to that icon. - // Arguments: - // - tab: the Tab to update the title for. - void TerminalPage::_UpdateTabIcon(TerminalTab& tab) - { - const auto lastFocusedProfileOpt = tab.GetFocusedProfile(); - if (lastFocusedProfileOpt.has_value()) - { - const auto lastFocusedProfile = lastFocusedProfileOpt.value(); - const auto matchingProfile = _settings.FindProfile(lastFocusedProfile); - if (matchingProfile) - { - tab.UpdateIcon(matchingProfile.Icon()); - } - else - { - tab.UpdateIcon({}); - } - } - } - - // Method Description: - // - Handle changes to the tab width set by the user - void TerminalPage::_UpdateTabWidthMode() - { - _tabView.TabWidthMode(_settings.GlobalSettings().TabWidthMode()); - } - - // Method Description: - // - Handle changes in tab layout. - void TerminalPage::_UpdateTabView() - { - // Never show the tab row when we're fullscreen. Otherwise: - // Show tabs when there's more than 1, or the user has chosen to always - // show the tab bar. - const bool isVisible = (!_isFullscreen && !_isInFocusMode) && - (_settings.GlobalSettings().ShowTabsInTitlebar() || - (_tabs.Size() > 1) || - _settings.GlobalSettings().AlwaysShowTabs()); - - // collapse/show the tabs themselves - _tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed); - - // collapse/show the row that the tabs are in. - // NaN is the special value XAML uses for "Auto" sizing. - _tabRow.Height(isVisible ? NAN : 0); - } - - // Method Description: - // - Duplicates the current focused tab - void TerminalPage::_DuplicateFocusedTab() - { - if (const auto terminalTab{ _GetFocusedTabImpl() }) - { - _DuplicateTab(*terminalTab); - } - } - - // Method Description: - // - Duplicates specified tab - // Arguments: - // - tab: tab to duplicate - void TerminalPage::_DuplicateTab(const TerminalTab& tab) - { - try - { - // TODO: GH#5047 - In the future, we should get the Profile of - // the focused pane, and use that to build a new instance of the - // settings so we can duplicate this tab/pane. - // - // Currently, if the profile doesn't exist anymore in our - // settings, we'll silently do nothing. - // - // In the future, it will be preferable to just duplicate the - // current control's settings, but we can't do that currently, - // because we won't be able to create a new instance of the - // connection without keeping an instance of the original Profile - // object around. - - const auto& profileGuid = tab.GetFocusedProfile(); - if (profileGuid.has_value()) - { - const auto settings{ TerminalSettings::CreateWithProfileByID(_settings, profileGuid.value(), *_bindings) }; - const auto workingDirectory = tab.GetActiveTerminalControl().WorkingDirectory(); - const auto validWorkingDirectory = !workingDirectory.empty(); - if (validWorkingDirectory) - { - settings.StartingDirectory(workingDirectory); - } - - _CreateNewTabFromSettings(profileGuid.value(), settings); - } - } - CATCH_LOG(); - } - - // Method Description: - // - Look for the index of the input tabView in the tabs vector, - // and call _RemoveTab - // Arguments: - // - tabViewItem: the TabViewItem in the TabView that is being removed. - void TerminalPage::_RemoveTabViewItem(const MUX::Controls::TabViewItem& tabViewItem) - { - uint32_t tabIndexFromControl = 0; - if (_tabView.TabItems().IndexOf(tabViewItem, tabIndexFromControl)) - { - // If IndexOf returns true, we've actually got an index - auto tab{ _tabs.GetAt(tabIndexFromControl) }; - _RemoveTab(tab); - } - } - - // Method Description: - // - Removes the tab (both TerminalControl and XAML) - // Arguments: - // - tab: the tab to remove - winrt::Windows::Foundation::IAsyncAction TerminalPage::_RemoveTab(winrt::TerminalApp::TabBase tab) - { - if (tab.ReadOnly()) - { - ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog(); - - // If the user didn't explicitly click on close tab - leave - if (warningResult != ContentDialogResult::Primary) - { - co_return; - } - } - - uint32_t tabIndex{}; - if (!_tabs.IndexOf(tab, tabIndex)) - { - // The tab is already removed - co_return; - } - - // We use _removing flag to suppress _OnTabSelectionChanged events - // that might get triggered while removing - _removing = true; - auto unsetRemoving = wil::scope_exit([&]() noexcept { _removing = false; }); - - const auto focusedTabIndex{ _GetFocusedTabIndex() }; - - // Removing the tab from the collection should destroy its control and disconnect its connection, - // but it doesn't always do so. The UI tree may still be holding the control and preventing its destruction. - tab.Shutdown(); - - uint32_t mruIndex{}; - if (_mruTabs.IndexOf(tab, mruIndex)) - { - _mruTabs.RemoveAt(mruIndex); - } - - _tabs.RemoveAt(tabIndex); - _tabView.TabItems().RemoveAt(tabIndex); - _UpdateTabIndices(); - - // To close the window here, we need to close the hosting window. - if (_tabs.Size() == 0) - { - _LastTabClosedHandlers(*this, nullptr); - } - else if (focusedTabIndex.has_value() && focusedTabIndex.value() == gsl::narrow_cast(tabIndex)) - { - // Manually select the new tab to get focus, rather than relying on TabView since: - // 1. We want to customize this behavior (e.g., use MRU logic) - // 2. In fullscreen (GH#5799) and focus (GH#7916) modes the _OnTabItemsChanged is not fired - // 3. When rearranging tabs (GH#7916) _OnTabItemsChanged is suppressed - const auto tabSwitchMode = _settings.GlobalSettings().TabSwitcherMode(); - - if (tabSwitchMode == TabSwitcherMode::MostRecentlyUsed) - { - const auto newSelectedTab = _mruTabs.GetAt(0); - - uint32_t newSelectedIndex; - if (_tabs.IndexOf(newSelectedTab, newSelectedIndex)) - { - _UpdatedSelectedTab(newSelectedIndex); - _tabView.SelectedItem(newSelectedTab.TabViewItem()); - } - } - else - { - // We can't use - // auto selectedIndex = _tabView.SelectedIndex(); - // Because this will always return -1 in this scenario unfortunately. - // - // So, what we're going to try to do is move the focus to the tab - // to the left, within the bounds of how many tabs we have. - // - // EX: we have 4 tabs: [A, B, C, D]. If we close: - // * A (tabIndex=0): We'll want to focus tab B (now in index 0) - // * B (tabIndex=1): We'll want to focus tab A (now in index 0) - // * C (tabIndex=2): We'll want to focus tab B (now in index 1) - // * D (tabIndex=3): We'll want to focus tab C (now in index 2) - const auto newSelectedIndex = std::clamp(tabIndex - 1, 0, _tabs.Size()); - // _UpdatedSelectedTab will do the work of setting up the new tab as - // the focused one, and unfocusing all the others. - _UpdatedSelectedTab(newSelectedIndex); - - // Also, we need to _manually_ set the SelectedItem of the tabView - // here. If we don't, then the TabView will technically not have a - // selected item at all, which can make things like ClosePane not - // work correctly. - auto newSelectedTab{ _tabs.GetAt(newSelectedIndex) }; - _tabView.SelectedItem(newSelectedTab.TabViewItem()); - } - } - - // GH#5559 - If we were in the middle of a drag/drop, end it by clearing - // out our state. - if (_rearranging) - { - _rearranging = false; - _rearrangeFrom = std::nullopt; - _rearrangeTo = std::nullopt; - } - - co_return; - } - // Method Description: // - Connects event handlers to the TermControl for events that we want to // handle. This includes: @@ -1541,64 +1089,6 @@ namespace winrt::TerminalApp::implementation // _ClearNewTabButtonColor(); } - // Method Description: - // - Sets focus to the tab to the right or left the currently selected tab. - void TerminalPage::_SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference& customTabSwitcherMode) - { - const auto index{ _GetFocusedTabIndex().value_or(0) }; - const auto tabSwitchMode = customTabSwitcherMode ? customTabSwitcherMode.Value() : _settings.GlobalSettings().TabSwitcherMode(); - if (tabSwitchMode == TabSwitcherMode::Disabled) - { - uint32_t tabCount = _tabs.Size(); - // Wraparound math. By adding tabCount and then calculating - // modulo tabCount, we clamp the values to the range [0, - // tabCount) while still supporting moving leftward from 0 to - // tabCount - 1. - const auto newTabIndex = ((tabCount + index + (bMoveRight ? 1 : -1)) % tabCount); - _SelectTab(newTabIndex); - } - else - { - CommandPalette().SetTabs(_tabs, _mruTabs); - - // Otherwise, set up the tab switcher in the selected mode, with - // the given ordering, and make it visible. - CommandPalette().EnableTabSwitcherMode(index, tabSwitchMode); - CommandPalette().Visibility(Visibility::Visible); - CommandPalette().SelectNextItem(bMoveRight); - } - } - - // Method Description: - // - Sets focus to the desired tab. Returns false if the provided tabIndex - // is greater than the number of tabs we have. - // - During startup, we'll immediately set the selected tab as focused. - // - After startup, we'll dispatch an async method to set the the selected - // item of the TabView, which will then also trigger a - // TabView::SelectionChanged, handled in - // TerminalPage::_OnTabSelectionChanged - // Return Value: - // true iff we were able to select that tab index, false otherwise - bool TerminalPage::_SelectTab(const uint32_t tabIndex) - { - if (tabIndex >= 0 && tabIndex < _tabs.Size()) - { - if (_startupState == StartupState::InStartup) - { - auto tab{ _tabs.GetAt(tabIndex) }; - _tabView.SelectedItem(tab.TabViewItem()); - _UpdatedSelectedTab(tabIndex); - } - else - { - _SetFocusedTabIndex(tabIndex); - } - - return true; - } - return false; - } - // Method Description: // - Helper to manually exit "zoom" when certain actions take place. // Anything that modifies the state of the pane tree should probably @@ -1655,136 +1145,14 @@ namespace winrt::TerminalApp::implementation return nullptr; } - // Method Description: - // - Returns the index in our list of tabs of the currently focused tab. If - // no tab is currently selected, returns nullopt. - // Return Value: - // - the index of the currently focused tab if there is one, else nullopt - std::optional TerminalPage::_GetFocusedTabIndex() const noexcept - { - // GH#1117: This is a workaround because _tabView.SelectedIndex() - // sometimes return incorrect result after removing some tabs - uint32_t focusedIndex; - if (_tabView.TabItems().IndexOf(_tabView.SelectedItem(), focusedIndex)) - { - return focusedIndex; - } - return std::nullopt; - } - - // Method Description: - // - returns a com_ptr to the currently focused tab. This might return null, - // so make sure to check the result! - winrt::TerminalApp::TabBase TerminalPage::_GetFocusedTab() const noexcept - { - if (auto index{ _GetFocusedTabIndex() }) - { - return _tabs.GetAt(*index); - } - return nullptr; - } - - // Method Description: - // - returns a com_ptr to the currently focused tab implementation. This might return null, - // so make sure to check the result! - winrt::com_ptr TerminalPage::_GetFocusedTabImpl() const noexcept - { - if (auto tab{ _GetFocusedTab() }) - { - return _GetTerminalTabImpl(tab); - } - return nullptr; - } - - // Method Description: - // - An async method for changing the focused tab on the UI thread. This - // method will _only_ set the selected item of the TabView, which will - // then also trigger a TabView::SelectionChanged event, which we'll handle - // in TerminalPage::_OnTabSelectionChanged, where we'll mark the new tab - // as focused. - // Arguments: - // - tabIndex: the index in the list of tabs to focus. - // Return Value: - // - - winrt::fire_and_forget TerminalPage::_SetFocusedTabIndex(const uint32_t tabIndex) - { - // GH#1117: This is a workaround because _tabView.SelectedIndex(tabIndex) - // sometimes set focus to an incorrect tab after removing some tabs - auto weakThis{ get_weak() }; - - co_await winrt::resume_foreground(_tabView.Dispatcher()); - - if (auto page{ weakThis.get() }) - { - auto tabToFocus = page->_tabs.GetAt(tabIndex); - _tabView.SelectedItem(tabToFocus.TabViewItem()); - } - } - - // Method Description: - // - Close the currently focused tab. Focus will move to the left, if possible. - void TerminalPage::_CloseFocusedTab() - { - if (auto index{ _GetFocusedTabIndex() }) - { - auto tab{ _tabs.GetAt(*index) }; - _RemoveTab(tab); - } - } - - // Method Description: - // - Close the currently focused pane. If the pane is the last pane in the - // tab, the tab will also be closed. This will happen when we handle the - // tab's Closed event. - winrt::fire_and_forget TerminalPage::_CloseFocusedPane() - { - if (const auto terminalTab{ _GetFocusedTabImpl() }) - { - _UnZoomIfNeeded(); - - auto pane = terminalTab->GetActivePane(); - - if (const auto pane{ terminalTab->GetActivePane() }) - { - if (const auto control{ pane->GetTerminalControl() }) - { - if (control.ReadOnly()) - { - ContentDialogResult warningResult = co_await _ShowCloseReadOnlyDialog(); - - // If the user didn't explicitly click on close tab - leave - if (warningResult != ContentDialogResult::Primary) - { - co_return; - } - - // Clean read-only mode to prevent additional prompt if closing the pane triggers closing of a hosting tab - if (control.ReadOnly()) - { - control.ToggleReadOnly(); - } - } - - pane->Close(); - } - } - } - else if (auto index{ _GetFocusedTabIndex() }) - { - const auto tab{ _tabs.GetAt(*index) }; - if (tab.try_as()) - { - _RemoveTab(tab); - } - } - } - // Method Description: // - Close the terminal app. If there is more // than one tab opened, show a warning dialog. fire_and_forget TerminalPage::CloseWindow() { - if (_tabs.Size() > 1 && _settings.GlobalSettings().ConfirmCloseAllTabs() && !_displayingCloseDialog) + if (_HasMultipleTabs() && + _settings.GlobalSettings().ConfirmCloseAllTabs() && + !_displayingCloseDialog) { _displayingCloseDialog = true; ContentDialogResult warningResult = co_await _ShowCloseWarningDialog(); @@ -1796,22 +1164,7 @@ namespace winrt::TerminalApp::implementation } } - // Since _RemoveTab is asynchronous, create a snapshot of the tabs we want to remove - std::vector tabsToRemove; - std::copy(begin(_tabs), end(_tabs), std::back_inserter(tabsToRemove)); - _RemoveTabs(tabsToRemove); - } - - // Method Description: - // - Closes provided tabs one by one - // Arguments: - // - tabs - tabs to remove - winrt::fire_and_forget TerminalPage::_RemoveTabs(const std::vector tabs) - { - for (auto& tab : tabs) - { - co_await _RemoveTab(tab); - } + _RemoveAllTabs(); } // Method Description: @@ -2421,114 +1774,6 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: - // - Responds to changes in the TabView's item list by changing the - // tabview's visibility. - // - This method is also invoked when tabs are dragged / dropped as part of - // tab reordering and this method hands that case as well in concert with - // TabDragStarting and TabDragCompleted handlers that are set up in - // TerminalPage::Create() - // Arguments: - // - sender: the control that originated this event - // - eventArgs: the event's constituent arguments - void TerminalPage::_OnTabItemsChanged(const IInspectable& /*sender*/, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs) - { - if (_rearranging) - { - if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemRemoved) - { - _rearrangeFrom = eventArgs.Index(); - } - - if (eventArgs.CollectionChange() == Windows::Foundation::Collections::CollectionChange::ItemInserted) - { - _rearrangeTo = eventArgs.Index(); - } - } - - CommandPalette().Visibility(Visibility::Collapsed); - _UpdateTabView(); - } - - // Method Description: - // - Additional responses to clicking on a TabView's item. Currently, just remove tab with middle click - // Arguments: - // - sender: the control that originated this event (TabViewItem) - // - eventArgs: the event's constituent arguments - void TerminalPage::_OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs) - { - if (eventArgs.GetCurrentPoint(*this).Properties().IsMiddleButtonPressed()) - { - _RemoveTabViewItem(sender.as()); - eventArgs.Handled(true); - } - else if (eventArgs.GetCurrentPoint(*this).Properties().IsRightButtonPressed()) - { - eventArgs.Handled(true); - } - } - - void TerminalPage::_UpdatedSelectedTab(const int32_t index) - { - // Unfocus all the tabs. - for (auto tab : _tabs) - { - tab.Focus(FocusState::Unfocused); - } - - if (index >= 0) - { - try - { - auto tab{ _tabs.GetAt(index) }; - - _tabContent.Children().Clear(); - _tabContent.Children().Append(tab.Content()); - - // GH#7409: If the tab switcher is open, then we _don't_ want to - // automatically focus the new tab here. The tab switcher wants - // to be able to "preview" the selected tab as the user tabs - // through the menu, but if we toss the focus to the control - // here, then the user won't be able to navigate the ATS any - // longer. - // - // When the tab switcher is eventually dismissed, the focus will - // get tossed back to the focused terminal control, so we don't - // need to worry about focus getting lost. - if (CommandPalette().Visibility() != Visibility::Visible) - { - tab.Focus(FocusState::Programmatic); - _UpdateMRUTab(index); - } - - tab.TabViewItem().StartBringIntoView(); - - // Raise an event that our title changed - if (_settings.GlobalSettings().ShowTitleInTitlebar()) - { - _TitleChangedHandlers(*this, tab.Title()); - } - } - CATCH_LOG(); - } - } - - // Method Description: - // - Responds to the TabView control's Selection Changed event (to move a - // new terminal control into focus) when not in in the middle of a tab rearrangement. - // Arguments: - // - sender: the control that originated this event - // - eventArgs: the event's constituent arguments - void TerminalPage::_OnTabSelectionChanged(const IInspectable& sender, const WUX::Controls::SelectionChangedEventArgs& /*eventArgs*/) - { - if (!_rearranging && !_removing) - { - auto tabView = sender.as(); - auto selectedIndex = tabView.SelectedIndex(); - _UpdatedSelectedTab(selectedIndex); - } - } - // Method Description: // - Called when our tab content size changes. This updates each tab with // the new size, so they have a chance to update each of their panes with @@ -2540,13 +1785,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_OnContentSizeChanged(const IInspectable& /*sender*/, Windows::UI::Xaml::SizeChangedEventArgs const& e) { const auto newSize = e.NewSize(); - for (auto tab : _tabs) - { - if (auto terminalTab = _GetTerminalTabImpl(tab)) - { - terminalTab->ResizeContent(newSize); - } - } + _ResizeTabContent(newSize); } // Method Description: @@ -2801,14 +2040,7 @@ namespace winrt::TerminalApp::implementation { _newTabButton.Flyout().Hide(); } - - for (const auto& tab : _tabs) - { - if (tab.TabViewItem().ContextFlyout()) - { - tab.TabViewItem().ContextFlyout().Hide(); - } - } + _DismissTabContextMenus(); } // Method Description: @@ -3040,17 +2272,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_CommandPaletteClosed(const IInspectable& /*sender*/, const RoutedEventArgs& /*eventArgs*/) { - // We don't want to set focus on the tab if fly-out is open as it will be closed - // TODO GH#5400: consider checking we are not in the opening state, by hooking both Opening and Open events - if (!_newTabButton.Flyout().IsOpen()) - { - // Return focus to the active control - if (auto index{ _GetFocusedTabIndex() }) - { - _tabs.GetAt(*index).Focus(FocusState::Programmatic); - _UpdateMRUTab(index.value()); - } - } + _FocusCurrentTab(false); } bool TerminalPage::FocusMode() const @@ -3083,23 +2305,6 @@ namespace winrt::TerminalApp::implementation _OpenNewTab(nullptr, connection); } - // Method Description: - // - Updates all tabs with their current index in _tabs. - // Arguments: - // - - // Return Value: - // - - void TerminalPage::_UpdateTabIndices() - { - const uint32_t size = _tabs.Size(); - for (uint32_t i = 0; i < size; ++i) - { - auto tab{ _tabs.GetAt(i) }; - auto tabImpl{ winrt::get_self(tab) }; - tabImpl->UpdateTabViewIndex(i, size); - } - } - // Method Description: // - Creates a settings UI tab and focuses it. If there's already a settings UI tab open, // just focus the existing one. @@ -3224,50 +2429,6 @@ namespace winrt::TerminalApp::implementation return systemRowsToScroll; } - // Method Description: - // - Bumps the tab in its in-order index up to the top of the mru list. - // Arguments: - // - index: the in-order index of the tab to bump. - // Return Value: - // - - void TerminalPage::_UpdateMRUTab(const uint32_t index) - { - uint32_t mruIndex; - const auto tab = _tabs.GetAt(index); - if (_mruTabs.IndexOf(tab, mruIndex)) - { - if (mruIndex > 0) - { - _mruTabs.RemoveAt(mruIndex); - _mruTabs.InsertAt(0, tab); - } - } - } - - // Method Description: - // - Moves the tab to another index in the tabs row (if required). - // Arguments: - // - currentTabIndex: the current index of the tab to move - // - suggestedNewTabIndex: the new index of the tab, might get clamped to fit int the tabs row boundaries - // Return Value: - // - - void TerminalPage::_TryMoveTab(const uint32_t currentTabIndex, const int32_t suggestedNewTabIndex) - { - auto newTabIndex = gsl::narrow_cast(std::clamp(suggestedNewTabIndex, 0, _tabs.Size() - 1)); - if (currentTabIndex != newTabIndex) - { - auto tab = _tabs.GetAt(currentTabIndex); - auto tabViewItem = tab.TabViewItem(); - _tabs.RemoveAt(currentTabIndex); - _tabs.InsertAt(newTabIndex, tab); - _UpdateTabIndices(); - - _tabView.TabItems().RemoveAt(currentTabIndex); - _tabView.TabItems().InsertAt(newTabIndex, tabViewItem); - _tabView.SelectedItem(tabViewItem); - } - } - // Method Description: // - Displays a dialog stating the "Touch Keyboard and Handwriting Panel // Service" is disabled. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index bb830b9770..b47b6a55de 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -184,6 +184,12 @@ namespace winrt::TerminalApp::implementation void _RegisterTerminalEvents(Microsoft::Terminal::Control::TermControl term, TerminalTab& hostingTab); + void _DismissTabContextMenus(); + void _FocusCurrentTab(const bool focusAlways); + bool _HasMultipleTabs() const; + void _RemoveAllTabs(); + void _ResizeTabContent(const winrt::Windows::Foundation::Size& newSize); + void _SelectNextTab(const bool bMoveRight, const Windows::Foundation::IReference& customTabSwitcherMode); bool _SelectTab(const uint32_t tabIndex); void _MoveFocus(const Microsoft::Terminal::Settings::Model::FocusDirection& direction); @@ -199,8 +205,6 @@ namespace winrt::TerminalApp::implementation winrt::fire_and_forget _RemoveOnCloseRoutine(Microsoft::UI::Xaml::Controls::TabViewItem tabViewItem, winrt::com_ptr page); - // Todo: add more event implementations here - // MSFT:20641986: Add keybindings for New Window void _Scroll(ScrollDirection scrollDirection, const Windows::Foundation::IReference& rowsToScroll); void _SplitPane(const Microsoft::Terminal::Settings::Model::SplitState splitType, @@ -232,6 +236,9 @@ namespace winrt::TerminalApp::implementation fire_and_forget _LaunchSettings(const Microsoft::Terminal::Settings::Model::SettingsTarget target); + void _TabDragStarted(const IInspectable& sender, const IInspectable& eventArgs); + void _TabDragCompleted(const IInspectable& sender, const IInspectable& eventArgs); + void _OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs); void _OnTabSelectionChanged(const IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& eventArgs); void _OnTabItemsChanged(const IInspectable& sender, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs); From eac3eea4848d33f611297e124f46967bfc32e378 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 15:04:39 -0500 Subject: [PATCH 11/56] Add a `--colorScheme` param to `new-tab`, `split-pane` (#9602) This is entirely self-serving. In my go-to config, I like having some of the panes for a given profile in a different color scheme. This will let a user pass `--colorScheme ` to manually override the scheme for that profile. Neat! --- doc/cascadia/profiles.schema.json | 4 ++ .../CommandlineTest.cpp | 37 +++++++++++++++++++ .../TerminalApp/AppCommandlineArgs.cpp | 8 ++++ src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 + .../Resources/en-US/Resources.resw | 4 ++ .../TerminalSettingsModel/ActionArgs.cpp | 9 +++++ .../TerminalSettingsModel/ActionArgs.h | 7 +++- .../TerminalSettingsModel/ActionArgs.idl | 2 + .../TerminalSettings.cpp | 8 ++++ 9 files changed, 80 insertions(+), 1 deletion(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 681a0b6beb..5d3410951f 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -227,6 +227,10 @@ "type": "boolean", "default": "false", "description": "When set to true, tabTitle overrides the default title of the tab and any title change messages from the application will be suppressed. When set to false, tabTitle behaves as normal" + }, + "colorScheme": { + "description": "The name of a color scheme to use, instead of the one specified by the profile", + "type": "string" } }, "type": "object" diff --git a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp index 0afeb245e8..e9d6e74a3c 100644 --- a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp +++ b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp @@ -458,6 +458,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor()); VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -479,6 +480,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"cmd", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -500,6 +502,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"c:\\Foo", myArgs.TerminalArgs().StartingDirectory()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -521,6 +524,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"powershell.exe", myArgs.TerminalArgs().Commandline()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -543,6 +547,7 @@ namespace TerminalAppLocalTests VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); auto myCommand = myArgs.TerminalArgs().Commandline(); VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\"", myCommand); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -565,6 +570,7 @@ namespace TerminalAppLocalTests VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); auto myCommand = myArgs.TerminalArgs().Commandline(); VERIFY_ARE_EQUAL(L"powershell.exe \"This is an arg with spaces\" another-arg \"more spaces in this one\"", myCommand); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -586,6 +592,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"Windows PowerShell", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -606,6 +613,7 @@ namespace TerminalAppLocalTests VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -628,6 +636,7 @@ namespace TerminalAppLocalTests VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -651,6 +660,31 @@ namespace TerminalAppLocalTests VERIFY_ARE_EQUAL(til::color(myArgs.TerminalArgs().TabColor().Value()), expectedColor); VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); + } + { + AppCommandlineArgs appArgs{}; + std::vector rawCommands{ L"wt.exe", subcommand, L"--colorScheme", L"Vintage" }; + const winrt::hstring expectedScheme{ L"Vintage" }; + + _buildCommandlinesHelper(appArgs, 1u, rawCommands); + + VERIFY_ARE_EQUAL(1u, appArgs._startupActions.size()); + + auto actionAndArgs = appArgs._startupActions.at(0); + VERIFY_ARE_EQUAL(ShortcutAction::NewTab, actionAndArgs.Action()); + VERIFY_IS_NOT_NULL(actionAndArgs.Args()); + auto myArgs = actionAndArgs.Args().try_as(); + VERIFY_IS_NOT_NULL(myArgs); + VERIFY_IS_NOT_NULL(myArgs.TerminalArgs()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().Commandline().empty()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().StartingDirectory().empty()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().TabTitle().empty()); + VERIFY_IS_NULL(myArgs.TerminalArgs().TabColor()); + VERIFY_IS_NULL(myArgs.TerminalArgs().ProfileIndex()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().Profile().empty()); + VERIFY_IS_FALSE(myArgs.TerminalArgs().ColorScheme().empty()); + VERIFY_ARE_EQUAL(expectedScheme, myArgs.TerminalArgs().ColorScheme()); } } @@ -749,6 +783,7 @@ namespace TerminalAppLocalTests VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -777,6 +812,7 @@ namespace TerminalAppLocalTests VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"wsl -d Alpine", myArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } { AppCommandlineArgs appArgs{}; @@ -805,6 +841,7 @@ namespace TerminalAppLocalTests VERIFY_IS_FALSE(myArgs.TerminalArgs().Profile().empty()); VERIFY_ARE_EQUAL(L"wsl -d Alpine -H", myArgs.TerminalArgs().Commandline()); VERIFY_ARE_EQUAL(L"1", myArgs.TerminalArgs().Profile()); + VERIFY_IS_TRUE(myArgs.TerminalArgs().ColorScheme().empty()); } } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 6e68084e87..978b33abe3 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -422,6 +422,9 @@ void AppCommandlineArgs::_addNewTerminalArgs(AppCommandlineArgs::NewTerminalSubc _suppressApplicationTitle, RS_A(L"CmdSuppressApplicationTitleDesc")); + subcommand.colorSchemeOption = subcommand.subcommand->add_option("--colorScheme", + _startingColorScheme, + RS_A(L"CmdColorSchemeArgDesc")); // Using positionals_at_end allows us to support "wt new-tab -d wsl -d Ubuntu" // without CLI11 thinking that we've specified -d twice. // There's an alternate construction where we make all subcommands "prefix commands", @@ -494,6 +497,11 @@ NewTerminalArgs AppCommandlineArgs::_getNewTerminalArgs(AppCommandlineArgs::NewT args.SuppressApplicationTitle(_suppressApplicationTitle); } + if (*subcommand.colorSchemeOption) + { + args.ColorScheme(winrt::to_hstring(_startingColorScheme)); + } + return args; } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index bc3d56f16d..a058551349 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -63,6 +63,7 @@ private: CLI::Option* titleOption; CLI::Option* tabColorOption; CLI::Option* suppressApplicationTitleOption; + CLI::Option* colorSchemeOption; }; struct NewPaneSubcommand : public NewTerminalSubcommand @@ -87,6 +88,7 @@ private: std::string _startingDirectory; std::string _startingTitle; std::string _startingTabColor; + std::string _startingColorScheme; bool _suppressApplicationTitle{ false }; winrt::Microsoft::Terminal::Settings::Model::FocusDirection _moveFocusDirection{ winrt::Microsoft::Terminal::Settings::Model::FocusDirection::None }; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 68dcb0da86..e969a7a682 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -323,6 +323,10 @@ Open the tab with tabTitle overriding default title and suppressing title change messages from the application {Locked="\"tabTitle\""} + + Open the tab with the specified color scheme, instead of the profile's set "colorScheme" + {Locked="\"colorScheme\""} + Display the application version diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp index 5401c050f6..cf4a4956fe 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.cpp @@ -68,6 +68,10 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation const til::color tabColor{ _TabColor.Value() }; ss << fmt::format(L"tabColor: {}, ", tabColor.ToHexString(true)); } + if (!_ColorScheme.empty()) + { + ss << fmt::format(L"colorScheme: {}, ", _ColorScheme); + } if (_SuppressApplicationTitle) { @@ -135,6 +139,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } } + if (!_ColorScheme.empty()) + { + ss << fmt::format(L"--colorScheme \"{}\" ", _ColorScheme); + } + if (!_Commandline.empty()) { ss << fmt::format(L"-- \"{}\" ", _Commandline); diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index c96d08a25e..a2a3867bf9 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -70,6 +70,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation WINRT_PROPERTY(Windows::Foundation::IReference, ProfileIndex, nullptr); WINRT_PROPERTY(winrt::hstring, Profile, L""); WINRT_PROPERTY(Windows::Foundation::IReference, SuppressApplicationTitle, nullptr); + WINRT_PROPERTY(winrt::hstring, ColorScheme); static constexpr std::string_view CommandlineKey{ "commandline" }; static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; @@ -78,6 +79,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static constexpr std::string_view ProfileIndexKey{ "index" }; static constexpr std::string_view ProfileKey{ "profile" }; static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; + static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; public: hstring GenerateName() const; @@ -91,7 +93,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation other.TabColor() == _TabColor && other.ProfileIndex() == _ProfileIndex && other.Profile() == _Profile && - other.SuppressApplicationTitle() == _SuppressApplicationTitle; + other.SuppressApplicationTitle() == _SuppressApplicationTitle && + other.ColorScheme() == _ColorScheme; }; static Model::NewTerminalArgs FromJson(const Json::Value& json) { @@ -104,6 +107,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::GetValueForKey(json, ProfileKey, args->_Profile); JsonUtils::GetValueForKey(json, TabColorKey, args->_TabColor); JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, args->_SuppressApplicationTitle); + JsonUtils::GetValueForKey(json, ColorSchemeKey, args->_ColorScheme); return *args; } Model::NewTerminalArgs Copy() const @@ -116,6 +120,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation copy->_ProfileIndex = _ProfileIndex; copy->_Profile = _Profile; copy->_SuppressApplicationTitle = _SuppressApplicationTitle; + copy->_ColorScheme = _ColorScheme; return *copy; } }; diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 67b76be7b6..7a939c1f14 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -100,6 +100,8 @@ namespace Microsoft.Terminal.Settings.Model Windows.Foundation.IReference SuppressApplicationTitle; + String ColorScheme; + Boolean Equals(NewTerminalArgs other); String GenerateName(); String ToCommandline(); diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp index f59d9cb835..77e52c2a20 100644 --- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp @@ -118,6 +118,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { settings.SuppressApplicationTitle(newTerminalArgs.SuppressApplicationTitle().Value()); } + if (!newTerminalArgs.ColorScheme().empty()) + { + const auto schemes = appSettings.GlobalSettings().ColorSchemes(); + if (const auto& scheme = schemes.TryLookup(newTerminalArgs.ColorScheme())) + { + settings.ApplyColorScheme(scheme); + } + } } return settings; From 25527789c0733d9ac5fdbc94c17d513438998dd2 Mon Sep 17 00:00:00 2001 From: Dustin Howett Date: Mon, 29 Mar 2021 15:24:43 -0500 Subject: [PATCH 12/56] Reflect testlist change from OS --- src/testlist/sources | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlist/sources b/src/testlist/sources index de0493fa9d..eaa0a1270a 100644 --- a/src/testlist/sources +++ b/src/testlist/sources @@ -19,4 +19,4 @@ TESTLIST_REFERENCE_DIRS=\ $(OBJ_PATH)\..\terminal\adapter\ut_adapter\$O \ $(OBJ_PATH)\..\terminal\parser\ut_parser\$O \ $(OBJ_PATH)\..\types\ut_types\$O \ - $(ONECORE_PRIVATE_PATH)\minkernel\lib\$(TARGET_DIRECTORY)\testmetadata\console \ + $(MINKERNEL_PRIVATE_TESTMETADATA_PATH_L)\console \ From b67f40f4c4a11b479547951f32d4695f8899cc6e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 29 Mar 2021 15:28:09 -0500 Subject: [PATCH 13/56] Switch to create function as it will open if exists and create if not. --- src/propslib/DelegationConfig.cpp | 3 ++- src/propslib/RegistrySerialization.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 6a6f8ae922..cbd0727bb7 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -302,8 +302,9 @@ try RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_OpenConsoleKey(¤tUserKey, &consoleKey)); + // Create method for registry is a "create if not exists, otherwise open" function. wil::unique_hkey startupKey; - RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_OpenKey(consoleKey.get(), L"%%Startup", &startupKey)); + RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_CreateKey(consoleKey.get(), L"%%Startup", &startupKey)); wil::unique_cotaskmem_string str; RETURN_IF_FAILED(StringFromCLSID(clsid, &str)); diff --git a/src/propslib/RegistrySerialization.cpp b/src/propslib/RegistrySerialization.cpp index 627fbcb5e2..09995d680a 100644 --- a/src/propslib/RegistrySerialization.cpp +++ b/src/propslib/RegistrySerialization.cpp @@ -227,7 +227,8 @@ NTSTATUS RegistrySerialization::s_OpenConsoleKey(_Out_ HKEY* phCurrentUserKey, _ } // Routine Description: -// - Opens a subkey of the given key +// - Opens a subkey of the given key. Fails if it doesn't exist. +// - NOTE: To create if it doesn't exist and open otherwise, try `s_CreateKey`. // Arguments: // - hKey - Handle to a registry key // - pwszSubKey - String name of sub key @@ -256,6 +257,7 @@ NTSTATUS RegistrySerialization::s_DeleteValue(const HKEY hKey, _In_ PCWSTR const // Routine Description: // - Creates a subkey of the given key // This function creates keys with read/write access. +// - If key already exists, opens existing. // Arguments: // - hKey - Handle to a registry key // - pwszSubKey - String name of sub key From 477c4d9986de0a9157a7a25c60374746ccb935ba Mon Sep 17 00:00:00 2001 From: Dragos Sambotin Date: Mon, 29 Mar 2021 20:39:47 +0000 Subject: [PATCH 14/56] Merged PR 5854784: [Git2Git] When V1 console fails to load, fail upwards to V2 This change introduces a fallback from v1 to v2 for SKUs of Windows that do not compose v1. Related work items: MSFT-29352720 --- src/host/exemain.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/host/exemain.cpp b/src/host/exemain.cpp index 8d338ff48e..33c5306e89 100644 --- a/src/host/exemain.cpp +++ b/src/host/exemain.cpp @@ -16,6 +16,7 @@ TRACELOGGING_DEFINE_PROVIDER( (0x770aa552, 0x671a, 0x5e97, 0x57, 0x9b, 0x15, 0x17, 0x09, 0xec, 0x0d, 0xbd), TraceLoggingOptionMicrosoftTelemetry()); +static bool useV2 = true; static bool ConhostV2ForcedInRegistry() { // If the registry value doesn't exist, or exists and is non-zero, we should default to using the v2 console. @@ -23,6 +24,9 @@ static bool ConhostV2ForcedInRegistry() bool fShouldUseConhostV2 = true; PCSTR pszErrorDescription = nullptr; bool fIgnoreError = false; + DWORD dwValue; + DWORD dwType; + DWORD cbValue = sizeof(dwValue); // open HKCU\Console wil::unique_hkey hConsoleSubKey; @@ -30,9 +34,7 @@ static bool ConhostV2ForcedInRegistry() if (ERROR_SUCCESS == lStatus) { // now get the value of the ForceV2 reg value, if it exists - DWORD dwValue; - DWORD dwType; - DWORD cbValue = sizeof(dwValue); + cbValue = sizeof(dwValue); lStatus = RegQueryValueExW(hConsoleSubKey.get(), L"ForceV2", nullptr, @@ -132,6 +134,8 @@ static bool ShouldUseLegacyConhost(const ConsoleArguments& args) { // setup status error hr = HRESULT_FROM_WIN32(GetLastError()); + // fallback to V2 if conhostv1.dll cannot be loaded. + useV2 = true; } if (SUCCEEDED(hr)) @@ -177,6 +181,7 @@ int CALLBACK wWinMain( { if (ShouldUseLegacyConhost(args)) { + useV2 = false; if (args.ShouldCreateServerHandle()) { hr = E_INVALIDARG; @@ -191,7 +196,7 @@ int CALLBACK wWinMain( } } } - else + if(useV2) { if (args.ShouldCreateServerHandle()) { From d6954244ad63cf20fe92a6b6691157c5fda9613c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 29 Mar 2021 14:43:58 -0700 Subject: [PATCH 15/56] Fix ARM64 build by defining WIN32 (#9654) By default from ARM64 architecture projects, `WIN32` is not defined. It is supposed to be for this proxy stub to work. So I've set it with the preprocessor for this project. ## PR Checklist * [x] Closes release build failure after #7489 * [x] I work here. * [x] Built on my machine. ## Detailed Description of the Pull Request / Additional comments `WIN32` appears to convey two meanings depending on who you are: - To most of Windows, `WIN32` appears to mean the Win32 API surface and sometimes the major OS version that goes with it. (Specifically in contrast to 16-bit Windows.) - To others, `WIN32` appears to mean a 32-bit processor or a synonym of `x86`. This is generally not a problem for a few reasons: - VS defines `WIN32` in the default targets/props only for the `x86` processor type. **BUT** - Windows defines `WIN32` if it's not already defined in both `minwinbase.h` and `ole2.h` which generally speaking manage to get compiled into practically everything especially since `minwinbase.h` tends to sneak itself in somehow through `windows.h` and that's **THE** include to use the Windows API surface. - Windows also defines `WIN32` for itself unconditionally and relatively globally when building itself. However, it's a problem here because: - `rpcproxy.h` is the only header included in `dlldata.c`, a file generated automatically by `midl.exe` in the SDK when making a proxy stub. - `rpcproxy.h` only defines its contents for a proxy when `WIN32` or `_M_AMD64` are found. - Therefore, it's defined pretty naturally for x86 and AMD64 targets from VS, but not for ARM64. - ARM64 support is pretty new and those who are attempting to build for ARM64 and against the public SDK with Visual Studio for a classic COM proxy... seems like a relatively unlikely combination. I will follow up with the Visual Studio, Windows SDK, and MIDL/COM teams to try to remove this pitfall from the public tooling. But for now, this is the fix. --- src/host/proxy/Host.Proxy.vcxproj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/host/proxy/Host.Proxy.vcxproj b/src/host/proxy/Host.Proxy.vcxproj index 9d479599e4..45fc697f25 100644 --- a/src/host/proxy/Host.Proxy.vcxproj +++ b/src/host/proxy/Host.Proxy.vcxproj @@ -57,8 +57,9 @@ ..;%(AdditionalIncludeDirectories) - StdCall - REGISTER_PROXY_DLL;%(PreprocessorDefinitions) + StdCall + + REGISTER_PROXY_DLL;WIN32;%(PreprocessorDefinitions) NotUsing @@ -67,4 +68,4 @@ - + \ No newline at end of file From c19aa891234943c54ffa4d752986f6b013bbc2b0 Mon Sep 17 00:00:00 2001 From: Don-Vito Date: Tue, 30 Mar 2021 01:06:05 +0300 Subject: [PATCH 16/56] Add splitMode to the args for split-pane (as -D for duplicate) (#9652) Closes #9579 --- .../CommandlineTest.cpp | 24 +++++++++++++++++++ .../TerminalApp/AppCommandlineArgs.cpp | 8 ++++++- src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 ++ .../Resources/en-US/Resources.resw | 3 +++ .../TerminalSettingsModel/ActionArgs.h | 5 ++++ .../TerminalSettingsModel/ActionArgs.idl | 1 + 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp index e9d6e74a3c..c8423b47af 100644 --- a/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp +++ b/src/cascadia/LocalTests_TerminalApp/CommandlineTest.cpp @@ -714,6 +714,7 @@ namespace TerminalAppLocalTests auto myArgs = actionAndArgs.Args().try_as(); VERIFY_IS_NOT_NULL(myArgs); VERIFY_ARE_EQUAL(SplitState::Automatic, myArgs.SplitStyle()); + VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode()); VERIFY_IS_NOT_NULL(myArgs.TerminalArgs()); } { @@ -733,6 +734,7 @@ namespace TerminalAppLocalTests auto myArgs = actionAndArgs.Args().try_as(); VERIFY_IS_NOT_NULL(myArgs); VERIFY_ARE_EQUAL(SplitState::Horizontal, myArgs.SplitStyle()); + VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode()); VERIFY_IS_NOT_NULL(myArgs.TerminalArgs()); } { @@ -754,6 +756,28 @@ namespace TerminalAppLocalTests auto myArgs = actionAndArgs.Args().try_as(); VERIFY_IS_NOT_NULL(myArgs); VERIFY_ARE_EQUAL(SplitState::Vertical, myArgs.SplitStyle()); + VERIFY_ARE_EQUAL(SplitType::Manual, myArgs.SplitMode()); + VERIFY_IS_NOT_NULL(myArgs.TerminalArgs()); + } + { + AppCommandlineArgs appArgs{}; + std::vector rawCommands{ L"wt.exe", subcommand, L"-D" }; + auto commandlines = AppCommandlineArgs::BuildCommands(rawCommands); + VERIFY_ARE_EQUAL(1u, commandlines.size()); + _buildCommandlinesHelper(appArgs, 1u, rawCommands); + + VERIFY_ARE_EQUAL(2u, appArgs._startupActions.size()); + + // The first action is going to always be a new-tab action + VERIFY_ARE_EQUAL(ShortcutAction::NewTab, appArgs._startupActions.at(0).Action()); + + // The one we actually want to test here is the SplitPane action we created + auto actionAndArgs = appArgs._startupActions.at(1); + VERIFY_ARE_EQUAL(ShortcutAction::SplitPane, actionAndArgs.Action()); + VERIFY_IS_NOT_NULL(actionAndArgs.Args()); + auto myArgs = actionAndArgs.Args().try_as(); + VERIFY_IS_NOT_NULL(myArgs); + VERIFY_ARE_EQUAL(SplitType::Duplicate, myArgs.SplitMode()); VERIFY_IS_NOT_NULL(myArgs.TerminalArgs()); } { diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 978b33abe3..129b5aaf70 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -255,6 +255,10 @@ void AppCommandlineArgs::_buildSplitPaneParser() auto* sizeOpt = subcommand.subcommand->add_option("-s,--size", _splitPaneSize, RS_A(L"CmdSplitPaneSizeArgDesc")); + + subcommand._duplicateOption = subcommand.subcommand->add_flag("-D,--duplicate", + _splitDuplicate, + RS_A(L"CmdSplitPaneDuplicateArgDesc")); sizeOpt->check(CLI::Range(0.01f, 0.99f)); // When ParseCommand is called, if this subcommand was provided, this @@ -283,7 +287,8 @@ void AppCommandlineArgs::_buildSplitPaneParser() style = SplitState::Vertical; } } - SplitPaneArgs args{ style, _splitPaneSize, terminalArgs }; + const auto splitMode{ subcommand._duplicateOption && _splitDuplicate ? SplitType::Duplicate : SplitType::Manual }; + SplitPaneArgs args{ splitMode, style, _splitPaneSize, terminalArgs }; splitPaneActionAndArgs.Args(args); _startupActions.push_back(splitPaneActionAndArgs); }); @@ -545,6 +550,7 @@ void AppCommandlineArgs::_resetStateToDefault() _splitVertical = false; _splitHorizontal = false; _splitPaneSize = 0.5f; + _splitDuplicate = false; _focusTabIndex = -1; _focusNextTab = false; diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index a058551349..4ec6a19414 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -70,6 +70,7 @@ private: { CLI::Option* _horizontalOption; CLI::Option* _verticalOption; + CLI::Option* _duplicateOption; }; // --- Subcommands --- @@ -98,6 +99,7 @@ private: bool _splitVertical{ false }; bool _splitHorizontal{ false }; + bool _splitDuplicate{ false }; float _splitPaneSize{ 0.5f }; int _focusTabIndex{ -1 }; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index e969a7a682..7942b2df67 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -308,6 +308,9 @@ Create the new pane as a vertical split (think [|]) + + Create the new pane by duplicating the profile of the focused pane + Open in the given directory instead of the profile's set "startingDirectory" {Locked="\"startingDirectory\""} diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index a2a3867bf9..ef53781901 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -394,6 +394,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation struct SplitPaneArgs : public SplitPaneArgsT { SplitPaneArgs() = default; + SplitPaneArgs(SplitType splitMode, SplitState style, double size, const Model::NewTerminalArgs& terminalArgs) : + _SplitMode{ splitMode }, + _SplitStyle{ style }, + _SplitSize{ size }, + _TerminalArgs{ terminalArgs } {}; SplitPaneArgs(SplitState style, double size, const Model::NewTerminalArgs& terminalArgs) : _SplitStyle{ style }, _SplitSize{ size }, diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 7a939c1f14..dcfb0219ea 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -154,6 +154,7 @@ namespace Microsoft.Terminal.Settings.Model [default_interface] runtimeclass SplitPaneArgs : IActionArgs { + SplitPaneArgs(SplitType splitMode, SplitState split, Double size, NewTerminalArgs terminalArgs); SplitPaneArgs(SplitState split, Double size, NewTerminalArgs terminalArgs); SplitPaneArgs(SplitState split, NewTerminalArgs terminalArgs); SplitPaneArgs(SplitType splitMode); From 3323dc572419c3ab64feba903d723dcb78225d06 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 29 Mar 2021 17:09:38 -0500 Subject: [PATCH 17/56] Auto-format our XAML files and enforce in CI (#9589) This adds [`XamlStyler.Console`] to our solution, and calls it when we format the code, to also format our .xaml files. * `XamlStyler.Console` is a dotnet tool so it needs to be restored with `dotnet tool restore` * I've added a set of rules to approximately follow [@cmaneu's XAML guidelines]. Those guidelines also recommend things based on the code-behind, which this tool can't figure out, but also _don't matter that much_. * There's an extra step to strip BOMs from the output, since Xaml Styler adds a BOM by default. Some had them before and others didn't. BOMs have been nothing but trouble though. [`XamlStyler.Console`]: https://github.com/Xavalon/XamlStyler [@cmaneu's XAML guidelines]: https://github.com/cmaneu/xaml-coding-guidelines --- .config/dotnet-tools.json | 12 + .github/actions/spelling/excludes.txt | 1 + .github/actions/spelling/expect/expect.txt | 2 + .nuget/packages.config | 2 +- XamlStyler.json | 41 + build/scripts/Invoke-FormattingCheck.ps1 | 14 +- consolegit2gitfilters.json | 1 + .../ConPTY/GUIConsole/GUIConsole.WPF/App.xaml | 14 +- .../GUIConsole/GUIConsole.WPF/MainWindow.xaml | 184 ++-- .../TestHostApp/UnitTestApp.xaml | 13 +- src/cascadia/TerminalApp/App.xaml | 75 +- .../TerminalApp/ColorPickupFlyout.xaml | 185 ++-- src/cascadia/TerminalApp/CommandPalette.xaml | 990 +++++++++--------- .../TerminalApp/HighlightedTextControl.xaml | 20 +- .../TerminalApp/MinMaxCloseControl.xaml | 284 +++-- .../TerminalApp/TabHeaderControl.xaml | 153 +-- src/cascadia/TerminalApp/TabRowControl.xaml | 174 +-- src/cascadia/TerminalApp/TerminalPage.xaml | 256 +++-- src/cascadia/TerminalApp/TitlebarControl.xaml | 74 +- .../TerminalControl/SearchBoxControl.xaml | 322 +++--- .../TerminalControl/TSFInputControl.xaml | 21 +- src/cascadia/TerminalControl/TermControl.xaml | 118 ++- .../TerminalSettingsEditor/Actions.xaml | 231 ++-- .../TerminalSettingsEditor/ColorSchemes.xaml | 390 +++---- .../CommonResources.xaml | 169 +-- .../GlobalAppearance.xaml | 68 +- .../TerminalSettingsEditor/Interaction.xaml | 66 +- .../TerminalSettingsEditor/Launch.xaml | 109 +- .../TerminalSettingsEditor/MainPage.xaml | 109 +- .../TerminalSettingsEditor/Profiles.xaml | 712 +++++++------ .../TerminalSettingsEditor/Rendering.xaml | 35 +- .../SettingContainerStyle.xaml | 62 +- .../WpfTerminalControl/TerminalControl.xaml | 22 +- src/cascadia/WpfTerminalTestNetCore/App.xaml | 6 +- .../WpfTerminalTestNetCore/MainWindow.xaml | 13 +- tools/OpenConsole.psm1 | 61 +- tools/README.md | 63 +- tools/runxamlformat.cmd | 5 + 38 files changed, 2839 insertions(+), 2238 deletions(-) create mode 100644 .config/dotnet-tools.json create mode 100644 XamlStyler.json create mode 100644 tools/runxamlformat.cmd diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000000..2c4e940b50 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "XamlStyler.Console": { + "version": "3.2008.4", + "commands": [ + "xstyler" + ] + } + } +} diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 0b9616e306..8931e1ac61 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -64,3 +64,4 @@ SUMS$ ^\.github/actions/spelling/ ^\.gitignore$ ^doc/reference/master-sequence-list.csv$ +^\XamlStyler.json$ diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 639ca0ed00..77b95664de 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -2061,6 +2061,7 @@ runtests runtimeclass runuia runut +runxamlformat rvalue RVERTICAL rxvt @@ -2852,6 +2853,7 @@ XResource xsd xsi xsize +xstyler XSubstantial xtended xterm diff --git a/.nuget/packages.config b/.nuget/packages.config index 6b13d84793..fd940a873d 100644 --- a/.nuget/packages.config +++ b/.nuget/packages.config @@ -1,4 +1,4 @@ - \ No newline at end of file + diff --git a/XamlStyler.json b/XamlStyler.json new file mode 100644 index 0000000000..7981bbfd56 --- /dev/null +++ b/XamlStyler.json @@ -0,0 +1,41 @@ +{ + "AttributesTolerance": 1, + "KeepFirstAttributeOnSameLine": true, + "MaxAttributeCharactersPerLine": 0, + "MaxAttributesPerLine": 1, + "NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter", + "SeparateByGroups": false, + "AttributeIndentation": 0, + "AttributeIndentationStyle": 1, + "RemoveDesignTimeReferences": false, + "EnableAttributeReordering": true, + "AttributeOrderingRuleGroups": [ + "x:Class", + "xmlns, xmlns:x", + "xmlns:*", + "x:Key, Key, x:Name, Name, x:Uid, Uid, Title", + "Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom", + "Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight", + "Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex", + "*:*, *", + "PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint", + "mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText", + "Storyboard.*, From, To, Duration" + ], + "FirstLineAttributes": "", + "OrderAttributesByName": true, + "PutEndingBracketOnNewLine": false, + "RemoveEndingTagOfEmptyElement": true, + "SpaceBeforeClosingSlash": true, + "RootElementLineBreakRule": 0, + "ReorderVSM": 2, + "ReorderGridChildren": false, + "ReorderCanvasChildren": false, + "ReorderSetters": 0, + "FormatMarkupExtension": true, + "NoNewLineMarkupExtensions": "x:Bind, Binding", + "ThicknessSeparator": 2, + "ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin", + "FormatOnSave": true, + "CommentPadding": 2, +} diff --git a/build/scripts/Invoke-FormattingCheck.ps1 b/build/scripts/Invoke-FormattingCheck.ps1 index 8cb8e5f8ac..eb5cb3eaa5 100644 --- a/build/scripts/Invoke-FormattingCheck.ps1 +++ b/build/scripts/Invoke-FormattingCheck.ps1 @@ -3,12 +3,24 @@ # Checks for code formatting errors. Will throw exception if any are found. function Invoke-CheckBadCodeFormatting() { Import-Module ./tools/OpenConsole.psm1 - Invoke-CodeFormat + + # Don't run the XAML formatter in this step - even if it changes nothing, + # it'll still touch all the .xaml files. + Invoke-CodeFormat -IgnoreXaml + # returns a non-zero exit code if there are any diffs in the tracked files in the repo git diff-index --quiet HEAD -- if ($lastExitCode -eq 1) { + + # Write the list of files that need updating to the log + git diff-index --name-only HEAD + throw "code formatting bad, run Invoke-CodeFormat on branch" } + + # Manually check the formatting of our .xaml files, without touching them. + Verify-XamlFormat + } Invoke-CheckBadCodeFormatting diff --git a/consolegit2gitfilters.json b/consolegit2gitfilters.json index e6267ee922..5a760692bb 100644 --- a/consolegit2gitfilters.json +++ b/consolegit2gitfilters.json @@ -38,6 +38,7 @@ ".wrn", ".rec", ".err", + "XamlStyler.json", ".xlsx" ] } diff --git a/samples/ConPTY/GUIConsole/GUIConsole.WPF/App.xaml b/samples/ConPTY/GUIConsole/GUIConsole.WPF/App.xaml index e95139446b..2e0fb07efd 100644 --- a/samples/ConPTY/GUIConsole/GUIConsole.WPF/App.xaml +++ b/samples/ConPTY/GUIConsole/GUIConsole.WPF/App.xaml @@ -1,8 +1,6 @@ - - - - - + + + diff --git a/samples/ConPTY/GUIConsole/GUIConsole.WPF/MainWindow.xaml b/samples/ConPTY/GUIConsole/GUIConsole.WPF/MainWindow.xaml index 766abcfca8..2c67f1cb0e 100644 --- a/samples/ConPTY/GUIConsole/GUIConsole.WPF/MainWindow.xaml +++ b/samples/ConPTY/GUIConsole/GUIConsole.WPF/MainWindow.xaml @@ -1,84 +1,100 @@ - - - - - - - - - - - - - - - - - - - - GUIConsole - - - - - - - - - - - - - - - - - - - + - - + diff --git a/src/cascadia/TerminalControl/TSFInputControl.xaml b/src/cascadia/TerminalControl/TSFInputControl.xaml index 2633bbd126..bc7fca22bf 100644 --- a/src/cascadia/TerminalControl/TSFInputControl.xaml +++ b/src/cascadia/TerminalControl/TSFInputControl.xaml @@ -1,18 +1,17 @@ - + + TextDecorations="Underline" + TextWrapping="Wrap" /> diff --git a/src/cascadia/TerminalControl/TermControl.xaml b/src/cascadia/TerminalControl/TermControl.xaml index ac642b037f..9e2aecbc5d 100644 --- a/src/cascadia/TerminalControl/TermControl.xaml +++ b/src/cascadia/TerminalControl/TermControl.xaml @@ -1,30 +1,31 @@ - - + + + Visibility="Visible"> + CompositionScaleChanged="_SwapChainScaleChanged" + SizeChanged="_SwapChainSizeChanged"> @@ -60,10 +61,9 @@ the MIT License. See LICENSE in the project root for license information. --> - + - + FontStyle="Italic" /> @@ -71,31 +71,33 @@ the MIT License. See LICENSE in the project root for license information. --> - + + Visibility="Collapsed" /> - + PointerReleased="_ReleasePointerCapture" + SmallChange="1" + ValueChanged="_ScrollbarChangeHandler" + ViewportSize="10" /> CurrentFontInfo="_FontInfoHandler" /> - + - - - - - - + + + + - - - - - - - - - - - - - - - - + - + - + - - - @@ -142,152 +137,152 @@ the MIT License. See LICENSE in the project root for license information. --> - + + x:Uid="ColorScheme_RenameErrorTip" /> - + + PreviewKeyDown="NameBox_PreviewKeyDown" + Style="{StaticResource TextBoxSettingStyle}" /> - - - - - + - + + Style="{StaticResource GroupHeaderStyle}" /> - - + + - - + + - - + + - - - - - - - - + + + + + + + + - + + Style="{StaticResource GroupHeaderStyle}" /> - - + + - - - - + + + + - + + Grid.Column="0" + Style="{StaticResource ColorLabelStyle}" /> + Grid.Column="1" + Content="{x:Bind CurrentForegroundColor, Mode=TwoWay}" + ContentTemplate="{StaticResource ColorTableEntryTemplate}" + Style="{StaticResource ColorControlStyle}" /> - + + Grid.Column="0" + Style="{StaticResource ColorLabelStyle}" /> + Grid.Column="1" + Content="{x:Bind CurrentBackgroundColor, Mode=TwoWay}" + ContentTemplate="{StaticResource ColorTableEntryTemplate}" + Style="{StaticResource ColorControlStyle}" /> - + + Grid.Column="0" + Style="{StaticResource ColorLabelStyle}" /> - - - - + + + + + Grid.Column="1" + Content="{x:Bind CurrentSelectionBackgroundColor, Mode=TwoWay}" + ContentTemplate="{StaticResource ColorTableEntryTemplate}" + Style="{StaticResource ColorControlStyle}" /> - + + VerticalAlignment="Center" + Style="{StaticResource DisclaimerStyle}" /> + + + + + + + + + + + + + + diff --git a/src/cascadia/TerminalSettingsEditor/CommonResources.xaml b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml index fed8e83085..741c2d4a60 100644 --- a/src/cascadia/TerminalSettingsEditor/CommonResources.xaml +++ b/src/cascadia/TerminalSettingsEditor/CommonResources.xaml @@ -1,13 +1,14 @@ - - + + - + - + 14.0 @@ -15,99 +16,127 @@ the MIT License. See LICENSE in the project root for license information. --> 0,24,0,0 250 - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml index 467fe60fa0..84c1408ae7 100644 --- a/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml +++ b/src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml @@ -1,70 +1,72 @@ - - + + - + - - + + - - + + - + - + SelectedItem="{x:Bind CurrentTheme, Mode=TwoWay}" /> - + - + - + - + - + - + - + - + - + - + SelectedItem="{x:Bind CurrentTabWidthMode, Mode=TwoWay}" /> - - + + - + diff --git a/src/cascadia/TerminalSettingsEditor/Interaction.xaml b/src/cascadia/TerminalSettingsEditor/Interaction.xaml index 701e12a1dc..dcff3f70e5 100644 --- a/src/cascadia/TerminalSettingsEditor/Interaction.xaml +++ b/src/cascadia/TerminalSettingsEditor/Interaction.xaml @@ -1,63 +1,65 @@ - - + + - + - - + + - + - - + Margin="0"> + + - + - + - + - + - + - + - + - + SelectedItem="{x:Bind CurrentTabSwitcherMode, Mode=TwoWay}" /> - + - + diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml index eed1b60391..c75f4d7881 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -1,30 +1,34 @@ - - + + - + - - + + - - @@ -32,7 +36,7 @@ the MIT License. See LICENSE in the project root for license information. --> - + Style="{StaticResource ComboBoxSettingStyle}"> - + - - - - + + + + - + + Text="{x:Bind Name}" /> @@ -67,52 +69,51 @@ the MIT License. See LICENSE in the project root for license information. --> - + - + Style="{StaticResource ComboBoxSettingStyle}" /> - + - + - + - + SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}" /> - + - + SelectedItem="{x:Bind CurrentWindowingBehavior, Mode=TwoWay}" /> - + - + + Style="{StaticResource SubtitleTextBlockStyle}" /> - + - + - + - + diff --git a/src/cascadia/TerminalSettingsEditor/MainPage.xaml b/src/cascadia/TerminalSettingsEditor/MainPage.xaml index 92b824c70c..9f0fcab6f5 100644 --- a/src/cascadia/TerminalSettingsEditor/MainPage.xaml +++ b/src/cascadia/TerminalSettingsEditor/MainPage.xaml @@ -1,41 +1,42 @@ - - + + - + + TintOpacity="0.5" /> + TintOpacity="0.5" /> + TintOpacity="0.7" /> @@ -43,98 +44,102 @@ the MIT License. See LICENSE in the project root for license information. --> - + - + - + - + + Tag="Rendering_Nav"> - + + Tag="Actions_Nav"> - + - + - - + - - + + - + - - + + - + - + - - + VerticalAlignment="Center" + Style="{StaticResource DisclaimerStyle}" /> - + - - + + - + + HasSettingValue="{x:Bind State.Profile.HasColorSchemeName, Mode=OneWay}" + SettingOverrideSource="{x:Bind State.Profile.ColorSchemeNameOverrideSource, Mode=OneWay}"> - + - + - - + - + - + + IsEnabled="{x:Bind State.Profile.UsingMonospaceFont, Mode=OneWay}" /> - + - + Style="{StaticResource NumberBoxSettingStyle}" + Value="{x:Bind State.Profile.FontSize, Mode=TwoWay}" /> - - + + Style="{StaticResource ComboBoxSettingStyle}" /> - + + Style="{StaticResource CustomSliderControlGridStyle}" + Visibility="{x:Bind IsCustomFontWeight, Mode=OneWay}"> - - + + + Maximum="1000" + Minimum="0" + TickFrequency="50" + TickPlacement="Outside" + Value="{x:Bind State.Profile.FontWeight, Converter={StaticResource FontWeightConverter}, Mode=TwoWay}" /> + Text="{Binding ElementName=FontWeightSlider, Path=Value, Mode=OneWay}" /> - + - + - + - + - + - + HasSettingValue="{x:Bind State.Profile.HasCursorShape, Mode=OneWay}" + SettingOverrideSource="{x:Bind State.Profile.CursorShapeOverrideSource, Mode=OneWay}"> + - + - - + + + Minimum="1" + Value="{x:Bind State.Profile.CursorHeight, Mode=TwoWay}" /> + Style="{StaticResource SliderValueLabelStyle}" + Text="{Binding ElementName=CursorHeightSlider, Path=Value, Mode=OneWay}" /> - + - + - - + + HasSettingValue="{x:Bind State.Profile.HasBackgroundImagePath, Mode=OneWay}" + SettingOverrideSource="{x:Bind State.Profile.BackgroundImagePathOverrideSource, Mode=OneWay}"> - +