From 1d0ee2b32a38c8bac1375e7b5043c7dc3121120a Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 4 Aug 2020 14:56:12 -0700 Subject: [PATCH 01/80] Mess around with launch handoff. This doesn't work because it's loading an EXE. Needs a relocatable DLL. --- src/host/globals.h | 2 ++ src/host/srvinit.cpp | 37 +++++++++++++++++++++++++++++ src/host/srvinit.h | 8 +++++++ src/server/DeviceComm.h | 1 + src/server/IoDispatchers.cpp | 45 ++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+) diff --git a/src/host/globals.h b/src/host/globals.h index e0ed9f41164..e46625379d7 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -69,6 +69,8 @@ class Globals ApiRoutines api; + bool handoffTarget = false; + #ifdef UNIT_TESTING void EnableConptyModeForTests(std::unique_ptr vtRenderEngine); #endif diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index adead2a1db5..5f8042e7dcd 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -256,6 +256,43 @@ void ConsoleCheckDebug() #endif } +HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... + HANDLE driverInputEvent) +{ + auto& g = ServiceLocator::LocateGlobals(); + g.handoffTarget = true; + + char* ch = new char[30]; + + RETURN_IF_FAILED(ConsoleServerInitialization(Server, args)); + RETURN_IF_FAILED(g.hConsoleInputInitEvent.create(wil::EventOptions::None)); + + // Store the driver input event. It's already been told that it exists by whomever started us. + g.hInputEvent.reset(driverInputEvent); + + HANDLE const hThread = CreateThread(nullptr, 0, ConsoleIoThread, nullptr, 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. + + // See MSFT:19918626 + // Make sure to always set up the signal thread if we need to. + // Do this first, because breaking the signal pipe is used by the conpty API + // to indicate that we should close. + // The conpty i/o threads need an actual client to be connected before they + // can start, so they're started below, in ConsoleAllocateConsole + auto& gci = g.getConsoleInformation(); + RETURN_IF_FAILED(gci.GetVtIo()->Initialize(args)); + RETURN_IF_FAILED(gci.GetVtIo()->CreateAndStartSignalThread()); + + return S_OK; +} + +[[nodiscard]] bool TestFunc() +{ + return false; +} + [[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) { auto& g = ServiceLocator::LocateGlobals(); diff --git a/src/host/srvinit.h b/src/host/srvinit.h index b660d63ed81..77e3faf5285 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -26,4 +26,12 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, [[nodiscard]] NTSTATUS ConsoleAllocateConsole(PCONSOLE_API_CONNECTINFO p); [[nodiscard]] NTSTATUS RemoveConsole(_In_ ConsoleProcessHandle* ProcessData); +[[nodiscard]] bool ConsoleConnectionDeservesVisibleWindow(PCONSOLE_API_CONNECTINFO p); + +extern "C" __declspec(dllexport) HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... + HANDLE driverInputEvent); + +extern "C" __declspec(dllexport) bool TestFunc(); + void ConsoleCheckDebug(); diff --git a/src/server/DeviceComm.h b/src/server/DeviceComm.h index ec78caca5c1..adc96918f9d 100644 --- a/src/server/DeviceComm.h +++ b/src/server/DeviceComm.h @@ -43,5 +43,6 @@ class DeviceComm _Out_writes_bytes_opt_(cbOutBufferSize) PVOID pOutBuffer, _In_ DWORD cbOutBufferSize) const; + public: wil::unique_handle _Server; }; diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 40c53a9bcd5..5d52ad524b2 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -157,6 +157,51 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API goto Error; } + Globals& Globals = ServiceLocator::LocateGlobals(); + if (!Globals.handoffTarget) + /*if (!ConsoleConnectionDeservesVisibleWindow(&Cac))*/ + { + + + typedef HRESULT (*PFNHANDOFF)(HANDLE, + const ConsoleArguments* const, // this can't stay like this because ConsoleArguments could change... + HANDLE); + + typedef bool (*PFNTEST)(); + + HMODULE mod = LoadLibraryW(L"OpenConsole2.exe"); + PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); + /*PFNTEST addr = (PFNTEST)GetProcAddress(mod, "TestFunc");*/ + HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get()); + res; + if (res) + { + auto rect = til::rectangle{}; + rect += til::size{ 2, 2 }; + } + else + { + auto size = til::size{ 3, 3 }; + auto h = size.height(); + h; + } + } + + //if (ConsoleConnectionDeservesVisibleWindow(&Cac)) + //{ + // RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(_ConsoleHostPath(), + // cmd, + // nullptr, + // nullptr, + // TRUE, + // EXTENDED_STARTUPINFO_PRESENT, + // nullptr, + // nullptr, + // &siEx.StartupInfo, + // pi.addressof())); + //} + + Status = NTSTATUS_FROM_HRESULT(gci.ProcessHandleList.AllocProcessData(dwProcessId, dwThreadId, Cac.ProcessGroupId, From 5906679e4b73781ebcf0f45f974c6284e856db41 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 5 Aug 2020 15:31:17 -0700 Subject: [PATCH 02/80] reintroduce host dll project --- OpenConsole.sln | 30 ++++++++ src/host/dll/Host.DLL.rc | 70 +++++++++++++++++++ .../dll/{host.vcxproj => Host.DLL.vcxproj} | 30 +++++--- ...xproj.filters => Host.DLL.vcxproj.filters} | 0 src/host/dll/OpenConsoleDll.def | 4 ++ src/host/dll/resource.h | 14 ++++ src/host/exe/Host.EXE.vcxproj | 2 +- src/host/srvinit.cpp | 2 - 8 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 src/host/dll/Host.DLL.rc rename src/host/dll/{host.vcxproj => Host.DLL.vcxproj} (76%) rename src/host/dll/{host.vcxproj.filters => Host.DLL.vcxproj.filters} (100%) create mode 100644 src/host/dll/OpenConsoleDll.def create mode 100644 src/host/dll/resource.h diff --git a/OpenConsole.sln b/OpenConsole.sln index 4d0d2e61481..4a996479aa2 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -316,6 +316,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "s EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.DLL", "src\host\dll\Host.DLL.vcxproj", "{E437B604-3E98-4F40-A927-E173E818EA4B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -2024,6 +2026,33 @@ Global {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x64.Build.0 = Release|x64 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x86.ActiveCfg = Release|Win32 {506FD703-BAA7-4F6E-9361-64F550EC8FCA}.Release|x86.Build.0 = Release|Win32 + {E437B604-3E98-4F40-A927-E173E818EA4B}.AuditMode|Any CPU.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|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|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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2105,6 +2134,7 @@ Global {6BAE5851-50D5-4934-8D5E-30361A8A40F3} = {81C352DB-1818-45B7-A284-18E259F1CC87} {1588FD7C-241E-4E7D-9113-43735F3E6BAD} = {59840756-302F-44DF-AA47-441A9D673202} {506FD703-BAA7-4F6E-9361-64F550EC8FCA} = {59840756-302F-44DF-AA47-441A9D673202} + {E437B604-3E98-4F40-A927-E173E818EA4B} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/host/dll/Host.DLL.rc b/src/host/dll/Host.DLL.rc new file mode 100644 index 00000000000..d1494f524b3 --- /dev/null +++ b/src/host/dll/Host.DLL.rc @@ -0,0 +1,70 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" +#include "..\\resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "#include ""..\\resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "#include ""..\\res.rc""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "..\\res.rc" + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/src/host/dll/host.vcxproj b/src/host/dll/Host.DLL.vcxproj similarity index 76% rename from src/host/dll/host.vcxproj rename to src/host/dll/Host.DLL.vcxproj index 52fe65da4d3..edc00dc2c0d 100644 --- a/src/host/dll/host.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -5,37 +5,49 @@ Win32Proj host Host.DLL - ConhostV2 + OpenConsoleDll DynamicLibrary - + + + + 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} @@ -56,7 +68,7 @@ - + @@ -68,10 +80,10 @@ - %(PreprocessorDefinitions) + ..;%(AdditionalIncludeDirectories) - ConhostV2.def + OpenConsoleDll.def true type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' diff --git a/src/host/dll/host.vcxproj.filters b/src/host/dll/Host.DLL.vcxproj.filters similarity index 100% rename from src/host/dll/host.vcxproj.filters rename to src/host/dll/Host.DLL.vcxproj.filters diff --git a/src/host/dll/OpenConsoleDll.def b/src/host/dll/OpenConsoleDll.def new file mode 100644 index 00000000000..b94a2674cb5 --- /dev/null +++ b/src/host/dll/OpenConsoleDll.def @@ -0,0 +1,4 @@ +LIBRARY OpenConsoleDll + +EXPORTS + \ No newline at end of file diff --git a/src/host/dll/resource.h b/src/host/dll/resource.h new file mode 100644 index 00000000000..7d34af61baa --- /dev/null +++ b/src/host/dll/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Host.EXE.rc +#include "..\\resource.h" +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index ca5cd3f8655..798cfca3841 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -8,7 +8,7 @@ OpenConsole Application - + diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 5f8042e7dcd..fa045b36f2a 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -263,8 +263,6 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, auto& g = ServiceLocator::LocateGlobals(); g.handoffTarget = true; - char* ch = new char[30]; - RETURN_IF_FAILED(ConsoleServerInitialization(Server, args)); RETURN_IF_FAILED(g.hConsoleInputInitEvent.create(wil::EventOptions::None)); From 075be44277b283ba9e61c89663d908cd554834fc Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 Aug 2020 12:38:33 -0700 Subject: [PATCH 03/80] this works to some degree. --- src/server/IoDispatchers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 5d52ad524b2..46f4eb94b7d 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -169,13 +169,14 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API typedef bool (*PFNTEST)(); - HMODULE mod = LoadLibraryW(L"OpenConsole2.exe"); + HMODULE mod = LoadLibraryW(L"OpenConsoleDll.dll"); PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); /*PFNTEST addr = (PFNTEST)GetProcAddress(mod, "TestFunc");*/ HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get()); res; if (res) { + Sleep(INFINITE); auto rect = til::rectangle{}; rect += til::size{ 2, 2 }; } From b5054c82004cd1ff34abefcab61391d8b0556d34 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 Aug 2020 14:01:07 -0700 Subject: [PATCH 04/80] ha it works. --- OpenConsole.sln | 3 ++- src/host/srvinit.cpp | 23 ++++++++++++++--------- src/host/srvinit.h | 5 ++--- src/server/IoDispatchers.cpp | 8 ++++---- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 4a996479aa2..815f9be1f7f 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -12,6 +12,7 @@ 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 + {E437B604-3E98-4F40-A927-E173E818EA4B} = {E437B604-3E98-4F40-A927-E173E818EA4B} {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714} EndProjectSection EndProject @@ -87,8 +88,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Feature", "src\h ProjectSection(ProjectDependencies) = postProject {18D09A24-8240-42D6-8CB6-236EEE820263} = {18D09A24-8240-42D6-8CB6-236EEE820263} {FC802440-AD6A-4919-8F2C-7701F2B38D79} = {FC802440-AD6A-4919-8F2C-7701F2B38D79} - {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} = {58A03BB2-DF5A-4B66-91A0-7EF3BA01269A} + {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} = {9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.UnitTests", "src\terminal\parser\ut_parser\Parser.UnitTests.vcxproj", "{12144E07-FE63-4D33-9231-748B8D8C3792}" diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index fa045b36f2a..a5948e08d5a 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -258,7 +258,8 @@ void ConsoleCheckDebug() HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... - HANDLE driverInputEvent) + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage) { auto& g = ServiceLocator::LocateGlobals(); g.handoffTarget = true; @@ -269,7 +270,7 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, // Store the driver input event. It's already been told that it exists by whomever started us. g.hInputEvent.reset(driverInputEvent); - 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. @@ -286,11 +287,6 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, return S_OK; } -[[nodiscard]] bool TestFunc() -{ - return false; -} - [[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) { auto& g = ServiceLocator::LocateGlobals(); @@ -688,10 +684,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(); @@ -700,6 +696,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 77e3faf5285..b596096da76 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -30,8 +30,7 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, extern "C" __declspec(dllexport) HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... - HANDLE driverInputEvent); - -extern "C" __declspec(dllexport) bool TestFunc(); + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage); void ConsoleCheckDebug(); diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 46f4eb94b7d..cf6e9e93c39 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -165,16 +165,16 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API typedef HRESULT (*PFNHANDOFF)(HANDLE, const ConsoleArguments* const, // this can't stay like this because ConsoleArguments could change... - HANDLE); + HANDLE, + PCONSOLE_API_MSG); typedef bool (*PFNTEST)(); HMODULE mod = LoadLibraryW(L"OpenConsoleDll.dll"); PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); /*PFNTEST addr = (PFNTEST)GetProcAddress(mod, "TestFunc");*/ - HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get()); - res; - if (res) + HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get(), pReceiveMsg); + if (res == S_OK) { Sleep(INFINITE); auto rect = til::rectangle{}; From 47002b33fd96aa32ebcf3ff8782ead570c6efa23 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 Aug 2020 14:40:57 -0700 Subject: [PATCH 05/80] Unify these two functions. --- src/host/srvinit.cpp | 60 +++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index a5948e08d5a..dadfb835039 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -256,19 +256,29 @@ void ConsoleCheckDebug() #endif } -HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... - HANDLE driverInputEvent, - PCONSOLE_API_MSG connectMessage) +HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, + const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage) { auto& g = ServiceLocator::LocateGlobals(); - g.handoffTarget = true; - RETURN_IF_FAILED(ConsoleServerInitialization(Server, args)); RETURN_IF_FAILED(g.hConsoleInputInitEvent.create(wil::EventOptions::None)); - // Store the driver input event. It's already been told that it exists by whomever started us. - g.hInputEvent.reset(driverInputEvent); + 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)); + } HANDLE const hThread = CreateThread(nullptr, 0, ConsoleIoThread, connectMessage, 0, nullptr); RETURN_HR_IF(E_HANDLE, hThread == nullptr); @@ -287,34 +297,20 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, return S_OK; } -[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) +HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... + 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)); - - 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); - 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. + g.handoffTarget = true; - // See MSFT:19918626 - // Make sure to always set up the signal thread if we need to. - // Do this first, because breaking the signal pipe is used by the conpty API - // to indicate that we should close. - // The conpty i/o threads need an actual client to be connected before they - // can start, so they're started below, in ConsoleAllocateConsole - auto& gci = g.getConsoleInformation(); - RETURN_IF_FAILED(gci.GetVtIo()->Initialize(args)); - RETURN_IF_FAILED(gci.GetVtIo()->CreateAndStartSignalThread()); + return ConsoleCreateIoThread(Server, args, driverInputEvent, connectMessage); +} - return S_OK; +[[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) +{ + return ConsoleCreateIoThread(Server, args, INVALID_HANDLE_VALUE, nullptr); } #define SYSTEM_ROOT (L"%SystemRoot%") From dd104b4a9c2c2bcdd12adf67762d109d35c87ce3 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 6 Aug 2020 14:53:13 -0700 Subject: [PATCH 06/80] If delegation is successful, let the other thread have it. Back off. --- src/server/IoDispatchers.cpp | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index cf6e9e93c39..6c902bd1c5f 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -168,41 +168,15 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API HANDLE, PCONSOLE_API_MSG); - typedef bool (*PFNTEST)(); - HMODULE mod = LoadLibraryW(L"OpenConsoleDll.dll"); PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); - /*PFNTEST addr = (PFNTEST)GetProcAddress(mod, "TestFunc");*/ HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get(), pReceiveMsg); - if (res == S_OK) - { - Sleep(INFINITE); - auto rect = til::rectangle{}; - rect += til::size{ 2, 2 }; - } - else + if (SUCCEEDED(res)) { - auto size = til::size{ 3, 3 }; - auto h = size.height(); - h; + ExitThread(S_OK); } } - //if (ConsoleConnectionDeservesVisibleWindow(&Cac)) - //{ - // RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(_ConsoleHostPath(), - // cmd, - // nullptr, - // nullptr, - // TRUE, - // EXTENDED_STARTUPINFO_PRESENT, - // nullptr, - // nullptr, - // &siEx.StartupInfo, - // pi.addressof())); - //} - - Status = NTSTATUS_FROM_HRESULT(gci.ProcessHandleList.AllocProcessData(dwProcessId, dwThreadId, Cac.ProcessGroupId, From 5a31d988acc31ca05b5cf99954a11a2db2a5b9bd Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 7 Aug 2020 09:32:00 -0700 Subject: [PATCH 07/80] some progress --- src/cascadia/TerminalApp/AppCommandlineArgs.cpp | 11 +++++++++++ src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 ++ src/host/srvinit.cpp | 12 ++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 70e6df6940b..dd6c6fcd5dc 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -174,6 +174,10 @@ void AppCommandlineArgs::_buildParser() }; _app.add_flag_function("-v,--version", versionCallback, RS_A(L"CmdVersionDesc")); + // Incoming PTY flags + // --pty + _app.add_option("--pty", _ptySigHandle, "PTY Signal Handle"); + // Maximized and Fullscreen flags // -M,--maximized: Maximizes the window on launch // -F,--fullscreen: Fullscreens the window on launch @@ -464,6 +468,8 @@ void AppCommandlineArgs::_resetStateToDefault() _focusNextTab = false; _focusPrevTab = false; + _ptySigHandle = 0; + // DON'T clear _launchMode here! This will get called once for every // subcommand, so we don't want `wt -F new-tab ; split-pane` clearing out // the "global" fullscreen flag (-F). @@ -661,6 +667,11 @@ void AppCommandlineArgs::ValidateStartupCommands() // push the arg onto the front _startupActions.insert(_startupActions.begin(), 1, *newTabAction); } + + if (_ptySigHandle != 0) + { + + } } std::optional AppCommandlineArgs::GetLaunchMode() const noexcept diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index a0d87ffc6b8..aee51fca9ae 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -73,6 +73,8 @@ class TerminalApp::AppCommandlineArgs final CLI::App* _focusTabShort; // Are you adding a new sub-command? Make sure to update _noCommandsProvided! + int64_t _ptySigHandle; + std::string _profileName; std::string _startingDirectory; std::string _startingTitle; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index dadfb835039..094aaf46d39 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -305,6 +305,18 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, auto& g = ServiceLocator::LocateGlobals(); g.handoffTarget = true; + wil::unique_handle signalPipeTheirSide; + wil::unique_handle signalPipeOurSide; + + 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 = FALSE; + sa.lpSecurityDescriptor = nullptr; + + RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(signalPipeOurSide.addressof(), signalPipeTheirSide.addressof(), &sa, 0)); + RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(signalPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); + return ConsoleCreateIoThread(Server, args, driverInputEvent, connectMessage); } From da1ce0ffacedb6f246657549a2a474126fd22479 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 13 Jul 2020 09:12:46 -0500 Subject: [PATCH 08/80] Give the connection through to the Terminal on startup. Includes cherry-pick of Mike's changes to let intellisense work --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 1 + src/cascadia/TerminalApp/ActionArgs.cpp | 1 + src/cascadia/TerminalApp/App.cpp | 1 + .../TerminalApp/AppActionHandlers.cpp | 1 + .../TerminalApp/AppCommandlineArgs.cpp | 17 +++ src/cascadia/TerminalApp/AppCommandlineArgs.h | 4 + src/cascadia/TerminalApp/AppKeyBindings.cpp | 1 + .../AppKeyBindingsSerialization.cpp | 1 + src/cascadia/TerminalApp/AppLogic.cpp | 11 +- .../TerminalApp/AzureCloudShellGenerator.cpp | 1 + src/cascadia/TerminalApp/CascadiaSettings.cpp | 1 + .../CascadiaSettingsSerialization.cpp | 1 + src/cascadia/TerminalApp/ColorHelper.cpp | 1 + src/cascadia/TerminalApp/ColorHelper.h | 1 + .../TerminalApp/ColorPickupFlyout.cpp | 1 + src/cascadia/TerminalApp/ColorScheme.cpp | 3 + src/cascadia/TerminalApp/Command.cpp | 1 + .../CommandKeyChordVisibilityConverter.cpp | 1 + src/cascadia/TerminalApp/CommandPalette.cpp | 1 + src/cascadia/TerminalApp/Commandline.cpp | 1 + .../TerminalApp/DebugTapConnection.cpp | 1 + .../TerminalApp/DefaultProfileUtils.cpp | 1 + .../TerminalApp/GlobalAppSettings.cpp | 1 + src/cascadia/TerminalApp/JsonUtils.cpp | 126 ++++++++++++++++++ .../TerminalApp/KeyChordSerialization.cpp | 1 + .../TerminalApp/MinMaxCloseControl.cpp | 1 + .../TerminalApp/Pane.LayoutSizeNode.cpp | 1 + src/cascadia/TerminalApp/Pane.cpp | 1 + .../PowershellCoreProfileGenerator.cpp | 1 + src/cascadia/TerminalApp/Profile.cpp | 1 + .../TerminalApp/ShortcutActionDispatch.cpp | 1 + src/cascadia/TerminalApp/Tab.cpp | 1 + src/cascadia/TerminalApp/TabRowControl.cpp | 1 + src/cascadia/TerminalApp/TerminalApp.vcxproj | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 37 +++-- src/cascadia/TerminalApp/TerminalPage.h | 6 +- src/cascadia/TerminalApp/TitlebarControl.cpp | 1 + src/cascadia/TerminalApp/Utils.cpp | 19 +++ .../TerminalApp/WslDistroGenerator.cpp | 1 + src/cascadia/TerminalApp/lib/pch.h | 2 +- .../TerminalConnection/ConptyConnection.cpp | 32 ++++- .../TerminalConnection/ConptyConnection.h | 4 + .../TerminalConnection/ConptyConnection.idl | 1 + src/cascadia/wt/shim.cpp | 2 +- src/host/ConsoleArguments.cpp | 5 + src/host/ConsoleArguments.hpp | 1 + src/host/srvinit.cpp | 113 +++++++++++++++- src/server/IoDispatchers.cpp | 3 +- 48 files changed, 398 insertions(+), 20 deletions(-) create mode 100644 src/cascadia/TerminalApp/JsonUtils.cpp create mode 100644 src/cascadia/TerminalApp/Utils.cpp diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index f28bfcca8a6..d4d1c404007 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include "lib/pch.h" #include "ActionArgs.h" #include "ActionAndArgs.h" #include "ActionAndArgs.g.cpp" diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index a5a83203afa..42a8cb923cc 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "ActionArgs.h" diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp index 8e5022a69ad..707f846abd9 100644 --- a/src/cascadia/TerminalApp/App.cpp +++ b/src/cascadia/TerminalApp/App.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "App.h" #include "App.g.cpp" diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 63a2743d80b..e1e8258d4cb 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "App.h" #include "TerminalPage.h" diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index dd6c6fcd5dc..d4ed771b897 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "AppLogic.h" #include "AppCommandlineArgs.h" #include "ActionArgs.h" @@ -638,6 +639,22 @@ bool AppCommandlineArgs::ShouldExitEarly() const noexcept return _shouldExitEarly; } +bool AppCommandlineArgs::HasStartupHandles() const noexcept +{ + return _ptySigHandle != 0; +} + +winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection AppCommandlineArgs::GetStartupConnection() +{ + uint64_t ptySigHandle = (uint64_t)_ptySigHandle; + uint64_t ptyOutHandle = (uint64_t)GetStdHandle(STD_OUTPUT_HANDLE); + uint64_t ptyInHandle = (uint64_t)GetStdHandle(STD_INPUT_HANDLE); + ptySigHandle; + ptyOutHandle; + ptyInHandle; + return winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection(ptySigHandle, ptyInHandle, ptyOutHandle); +} + // Method Description: // - Ensure that the first command in our list of actions is a NewTab action. // This makes sure that if the user passes a commandline like "wt split-pane diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index aee51fca9ae..da57aa3b609 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -6,6 +6,8 @@ #include "Commandline.h" +#include + #ifdef UNIT_TESTING // fwdecl unittest classes namespace TerminalAppLocalTests @@ -35,6 +37,8 @@ class TerminalApp::AppCommandlineArgs final static std::vector BuildCommands(const std::vector& args); static std::vector BuildCommands(winrt::array_view& args); + bool HasStartupHandles() const noexcept; + winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection GetStartupConnection(); void ValidateStartupCommands(); std::vector& GetStartupActions(); const std::string& GetExitMessage(); diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 58821ac5a6a..9fef16bf61a 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "AppKeyBindings.h" #include "KeyChordSerialization.h" diff --git a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp index 6be18ca683e..a74cb84ab28 100644 --- a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp @@ -7,6 +7,7 @@ // - Mike Griese - May 2019 #include "pch.h" +#include "lib/pch.h" #include "AppKeyBindings.h" #include "ActionAndArgs.h" #include "KeyChordSerialization.h" diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 5a6ec188703..215146aab4f 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "AppLogic.h" #include "AppLogic.g.cpp" #include @@ -978,7 +979,15 @@ namespace winrt::TerminalApp::implementation if (result == 0) { _appArgs.ValidateStartupCommands(); - _root->SetStartupActions(_appArgs.GetStartupActions()); + if (_appArgs.HasStartupHandles()) + { + auto conn = _appArgs.GetStartupConnection(); + _root->SetStartupConnection(conn); + } + else + { + _root->SetStartupActions(_appArgs.GetStartupActions()); + } } return result; diff --git a/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp b/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp index b9e76dce7f0..0c9ff1f4c19 100644 --- a/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp +++ b/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index 96e947e952d..f3108a256ed 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include #include #include diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 1a8f2b6e71f..a6cbb23a850 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include #include "CascadiaSettings.h" #include "../../types/inc/utils.hpp" diff --git a/src/cascadia/TerminalApp/ColorHelper.cpp b/src/cascadia/TerminalApp/ColorHelper.cpp index 1e8d061a3c9..90066757ee1 100644 --- a/src/cascadia/TerminalApp/ColorHelper.cpp +++ b/src/cascadia/TerminalApp/ColorHelper.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include "lib/pch.h" #include "ColorHelper.h" #include diff --git a/src/cascadia/TerminalApp/ColorHelper.h b/src/cascadia/TerminalApp/ColorHelper.h index cbe6582c8d1..09f89bfa9d0 100644 --- a/src/cascadia/TerminalApp/ColorHelper.h +++ b/src/cascadia/TerminalApp/ColorHelper.h @@ -1,5 +1,6 @@ #pragma once #include "pch.h" +#include "lib/pch.h" #include diff --git a/src/cascadia/TerminalApp/ColorPickupFlyout.cpp b/src/cascadia/TerminalApp/ColorPickupFlyout.cpp index b1c15be4818..0a32f4f1e6f 100644 --- a/src/cascadia/TerminalApp/ColorPickupFlyout.cpp +++ b/src/cascadia/TerminalApp/ColorPickupFlyout.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include "lib/pch.h" #include "ColorPickupFlyout.h" #include "ColorPickupFlyout.g.cpp" #include "winrt/Windows.UI.Xaml.Media.h" diff --git a/src/cascadia/TerminalApp/ColorScheme.cpp b/src/cascadia/TerminalApp/ColorScheme.cpp index 1659013809c..589b3b11358 100644 --- a/src/cascadia/TerminalApp/ColorScheme.cpp +++ b/src/cascadia/TerminalApp/ColorScheme.cpp @@ -2,7 +2,10 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" + #include + #include "ColorScheme.h" #include "DefaultSettings.h" #include "../../types/inc/Utils.hpp" diff --git a/src/cascadia/TerminalApp/Command.cpp b/src/cascadia/TerminalApp/Command.cpp index f3fe1219126..a67373d352b 100644 --- a/src/cascadia/TerminalApp/Command.cpp +++ b/src/cascadia/TerminalApp/Command.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "Command.h" #include "Command.g.cpp" diff --git a/src/cascadia/TerminalApp/CommandKeyChordVisibilityConverter.cpp b/src/cascadia/TerminalApp/CommandKeyChordVisibilityConverter.cpp index 24af0da0029..3ea9a67724c 100644 --- a/src/cascadia/TerminalApp/CommandKeyChordVisibilityConverter.cpp +++ b/src/cascadia/TerminalApp/CommandKeyChordVisibilityConverter.cpp @@ -1,4 +1,5 @@ #include "pch.h" +#include "lib/pch.h" #include "CommandKeyChordVisibilityConverter.h" #include "CommandKeyChordVisibilityConverter.g.cpp" diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index fd0a139281b..1c0a1fce135 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "CommandPalette.h" #include "CommandPalette.g.cpp" diff --git a/src/cascadia/TerminalApp/Commandline.cpp b/src/cascadia/TerminalApp/Commandline.cpp index b40591d7f29..93e51417d97 100644 --- a/src/cascadia/TerminalApp/Commandline.cpp +++ b/src/cascadia/TerminalApp/Commandline.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "Commandline.h" using namespace TerminalApp; diff --git a/src/cascadia/TerminalApp/DebugTapConnection.cpp b/src/cascadia/TerminalApp/DebugTapConnection.cpp index 21994920ecd..5ba543f70cf 100644 --- a/src/cascadia/TerminalApp/DebugTapConnection.cpp +++ b/src/cascadia/TerminalApp/DebugTapConnection.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "DebugTapConnection.h" using namespace ::winrt::Microsoft::Terminal::TerminalConnection; diff --git a/src/cascadia/TerminalApp/DefaultProfileUtils.cpp b/src/cascadia/TerminalApp/DefaultProfileUtils.cpp index 02222fdcb61..9c99a7c6a65 100644 --- a/src/cascadia/TerminalApp/DefaultProfileUtils.cpp +++ b/src/cascadia/TerminalApp/DefaultProfileUtils.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "DefaultProfileUtils.h" #include "../../types/inc/utils.hpp" diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index dd3b17ae723..7cb0cb4b702 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "GlobalAppSettings.h" #include "../../types/inc/Utils.hpp" #include "../../inc/DefaultSettings.h" diff --git a/src/cascadia/TerminalApp/JsonUtils.cpp b/src/cascadia/TerminalApp/JsonUtils.cpp new file mode 100644 index 00000000000..1ca8fd18e2a --- /dev/null +++ b/src/cascadia/TerminalApp/JsonUtils.cpp @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "lib/pch.h" +#include "Utils.h" +#include "JsonUtils.h" +#include "../../types/inc/Utils.hpp" + +void TerminalApp::JsonUtils::GetOptionalColor(const Json::Value& json, + std::string_view key, + std::optional& target) +{ + const auto conversionFn = [](const Json::Value& value) -> til::color { + return ::Microsoft::Console::Utils::ColorFromHexString(value.asString()); + }; + GetOptionalValue(json, + key, + target, + conversionFn); +} + +void TerminalApp::JsonUtils::GetOptionalString(const Json::Value& json, + std::string_view key, + std::optional& target) +{ + const auto conversionFn = [](const Json::Value& value) -> std::wstring { + return GetWstringFromJson(value); + }; + GetOptionalValue(json, + key, + target, + conversionFn); +} + +void TerminalApp::JsonUtils::GetOptionalGuid(const Json::Value& json, + std::string_view key, + std::optional& target) +{ + const auto conversionFn = [](const Json::Value& value) -> GUID { + return ::Microsoft::Console::Utils::GuidFromString(GetWstringFromJson(value)); + }; + GetOptionalValue(json, + key, + target, + conversionFn); +} + +void TerminalApp::JsonUtils::GetOptionalDouble(const Json::Value& json, + std::string_view key, + std::optional& target) +{ + const auto conversionFn = [](const Json::Value& value) -> double { + return value.asFloat(); + }; + const auto validationFn = [](const Json::Value& value) -> bool { + return value.isNumeric(); + }; + GetOptionalValue(json, + key, + target, + conversionFn, + validationFn); +} + +void TerminalApp::JsonUtils::GetInt(const Json::Value& json, + std::string_view key, + int& target) +{ + const auto conversionFn = [](const Json::Value& value) -> int { + return value.asInt(); + }; + const auto validationFn = [](const Json::Value& value) -> bool { + return value.isInt(); + }; + GetValue(json, key, target, conversionFn, validationFn); +} + +void TerminalApp::JsonUtils::GetUInt(const Json::Value& json, + std::string_view key, + uint32_t& target) +{ + const auto conversionFn = [](const Json::Value& value) -> uint32_t { + return value.asUInt(); + }; + const auto validationFn = [](const Json::Value& value) -> bool { + return value.isUInt(); + }; + GetValue(json, key, target, conversionFn, validationFn); +} + +void TerminalApp::JsonUtils::GetDouble(const Json::Value& json, + std::string_view key, + double& target) +{ + const auto conversionFn = [](const Json::Value& value) -> double { + return value.asFloat(); + }; + const auto validationFn = [](const Json::Value& value) -> bool { + return value.isNumeric(); + }; + GetValue(json, key, target, conversionFn, validationFn); +} + +void TerminalApp::JsonUtils::GetBool(const Json::Value& json, + std::string_view key, + bool& target) +{ + const auto conversionFn = [](const Json::Value& value) -> bool { + return value.asBool(); + }; + const auto validationFn = [](const Json::Value& value) -> bool { + return value.isBool(); + }; + GetValue(json, key, target, conversionFn, validationFn); +} + +void TerminalApp::JsonUtils::GetWstring(const Json::Value& json, + std::string_view key, + std::wstring& target) +{ + const auto conversionFn = [](const Json::Value& value) -> std::wstring { + return GetWstringFromJson(value); + }; + GetValue(json, key, target, conversionFn, nullptr); +} diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.cpp b/src/cascadia/TerminalApp/KeyChordSerialization.cpp index b825c251047..2a239a3e1e5 100644 --- a/src/cascadia/TerminalApp/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalApp/KeyChordSerialization.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "KeyChordSerialization.h" using namespace winrt::Microsoft::Terminal::Settings; diff --git a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp index ee5f3e0d9b7..500c06572b0 100644 --- a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp +++ b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp @@ -6,6 +6,7 @@ // #include "pch.h" +#include "lib/pch.h" #include "MinMaxCloseControl.h" diff --git a/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp b/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp index f3cc8647ff1..5f5bf7fda86 100644 --- a/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp +++ b/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "Pane.h" Pane::LayoutSizeNode::LayoutSizeNode(const float minSize) : diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index f8e61ae8379..a7a8d7c507d 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "Pane.h" #include "Profile.h" #include "CascadiaSettings.h" diff --git a/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp b/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp index 2c2ba87d48a..681a3d28364 100644 --- a/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp +++ b/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "PowershellCoreProfileGenerator.h" #include "LegacyProfileGeneratorNamespaces.h" diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index b98efb9f691..f30a860cf14 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "Profile.h" #include "Utils.h" #include "JsonUtils.h" diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 571b4589516..9b36d35d6bc 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "ShortcutActionDispatch.h" #include "ShortcutActionDispatch.g.cpp" diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index 51e54be09ee..9fa89a4e6da 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include #include "ColorPickupFlyout.h" #include "Tab.h" diff --git a/src/cascadia/TerminalApp/TabRowControl.cpp b/src/cascadia/TerminalApp/TabRowControl.cpp index bc4d7a83968..b91d6a526f4 100644 --- a/src/cascadia/TerminalApp/TabRowControl.cpp +++ b/src/cascadia/TerminalApp/TabRowControl.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "TabRowControl.h" #include "TabRowControl.g.cpp" diff --git a/src/cascadia/TerminalApp/TerminalApp.vcxproj b/src/cascadia/TerminalApp/TerminalApp.vcxproj index 320c20a299a..845e59604eb 100644 --- a/src/cascadia/TerminalApp/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/TerminalApp.vcxproj @@ -91,7 +91,7 @@ - $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); + $(OpenConsoleDir)\cascadia\TerminalApp\lib\;$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 30689891f04..98bee158768 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "TerminalPage.h" #include "ActionAndArgs.h" #include "Utils.h" @@ -244,15 +245,24 @@ namespace winrt::TerminalApp::implementation if (_startupState == StartupState::NotInitialized) { _startupState = StartupState::InStartup; - if (_startupActions.Size() == 0) + if (_startupConnection) { - _OpenNewTab(nullptr); + _OpenNewTab(nullptr, _startupConnection); _CompleteInitialization(); } else { - _ProcessStartupActions(_startupActions, true); + if (_startupActions.Size() == 0) + { + _OpenNewTab(nullptr); + + _CompleteInitialization(); + } + else + { + _ProcessStartupActions(_startupActions, true); + } } } } @@ -578,12 +588,12 @@ 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 CascadiaSettings::BuildSettings for more details. - void TerminalPage::_OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs) + void TerminalPage::_OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) try { const auto [profileGuid, settings] = _settings->BuildSettings(newTerminalArgs); - _CreateNewTabFromSettings(profileGuid, settings); + _CreateNewTabFromSettings(profileGuid, settings, existingConnection); const uint32_t tabCount = _tabs.Size(); const bool usedManualProfile = (newTerminalArgs != nullptr) && @@ -624,13 +634,19 @@ 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, TerminalApp::TerminalSettings settings) + // - existingConnection: optionally receives a connection from the outside world instead of attempting to create one + void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings, TerminalConnection::ITerminalConnection existingConnection) { // Initialize the new tab + auto connection = existingConnection; - // Create a connection based on the values in our settings object. - auto connection = _CreateConnectionFromSettings(profileGuid, settings); + if (!connection) + { + // Create a connection based on the values in our settings object. + connection = _CreateConnectionFromSettings(profileGuid, settings); + } TerminalConnection::ITerminalConnection debugConnection{ nullptr }; if (_settings->GlobalSettings().DebugFeaturesEnabled()) @@ -1959,6 +1975,11 @@ namespace winrt::TerminalApp::implementation _alwaysOnTopChangedHandlers(*this, nullptr); } + void TerminalPage::SetStartupConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection conn) + { + _startupConnection = conn; + } + // Method Description: // - Sets the initial actions to process on startup. We'll make a copy of // this list, and process these actions when we're loaded. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 021be7a3e16..06d75babbbf 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -56,6 +56,7 @@ namespace winrt::TerminalApp::implementation bool Fullscreen() const; bool AlwaysOnTop() const; + void SetStartupConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection conn); void SetStartupActions(std::vector& actions); static std::vector ConvertExecuteCommandlineToActions(const TerminalApp::ExecuteCommandlineArgs& args); @@ -107,6 +108,7 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Controls::Grid::LayoutUpdated_revoker _layoutUpdatedRevoker; StartupState _startupState{ StartupState::NotInitialized }; + winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _startupConnection{ nullptr }; Windows::Foundation::Collections::IVector _startupActions; winrt::fire_and_forget _ProcessStartupActions(Windows::Foundation::Collections::IVector actions, const bool initial); @@ -117,8 +119,8 @@ namespace winrt::TerminalApp::implementation void _CreateNewTabFlyout(); void _OpenNewTabDropdown(); - void _OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs); - void _CreateNewTabFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings); + void _OpenNewTab(const winrt::TerminalApp::NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); + void _CreateNewTabFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection = nullptr); winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, TerminalApp::TerminalSettings settings); void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs); diff --git a/src/cascadia/TerminalApp/TitlebarControl.cpp b/src/cascadia/TerminalApp/TitlebarControl.cpp index 05806726cfe..7e8e6a222a3 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.cpp +++ b/src/cascadia/TerminalApp/TitlebarControl.cpp @@ -6,6 +6,7 @@ // #include "pch.h" +#include "lib/pch.h" #include "TitlebarControl.h" diff --git a/src/cascadia/TerminalApp/Utils.cpp b/src/cascadia/TerminalApp/Utils.cpp new file mode 100644 index 00000000000..abb8310a3f3 --- /dev/null +++ b/src/cascadia/TerminalApp/Utils.cpp @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "lib/pch.h" +#include "Utils.h" + +// Method Description: +// - Constructs a wstring from a given Json::Value object. Reads the object as +// a std::string using asString, then builds an hstring from that std::string, +// then converts that hstring into a std::wstring. +// Arguments: +// - json: the Json::Value to parse as a string +// Return Value: +// - the wstring equivalent of the value in json +std::wstring GetWstringFromJson(const Json::Value& json) +{ + return winrt::to_hstring(json.asString()).c_str(); +} diff --git a/src/cascadia/TerminalApp/WslDistroGenerator.cpp b/src/cascadia/TerminalApp/WslDistroGenerator.cpp index ab63dcf92c7..55d8d460b34 100644 --- a/src/cascadia/TerminalApp/WslDistroGenerator.cpp +++ b/src/cascadia/TerminalApp/WslDistroGenerator.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT license. #include "pch.h" +#include "lib/pch.h" #include "WslDistroGenerator.h" #include "LegacyProfileGeneratorNamespaces.h" diff --git a/src/cascadia/TerminalApp/lib/pch.h b/src/cascadia/TerminalApp/lib/pch.h index 4cb7a49f1e3..26326b13ac9 100644 --- a/src/cascadia/TerminalApp/lib/pch.h +++ b/src/cascadia/TerminalApp/lib/pch.h @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // -// pch.h +// lib/pch.h // Header for platform projection include files // diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 1fe8399b4ed..108ae66b405 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -190,6 +190,29 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation } CATCH_RETURN(); + ConptyConnection::ConptyConnection(const uint64_t hSig, + const uint64_t hIn, + const uint64_t hOut) : + _initialRows{ 25 }, + _initialCols{ 80}, + _commandline{ L"" }, + _startingDirectory{ L""}, + _startingTitle{ L"" }, + _environment{ nullptr}, + _guid{}, + _u8State{}, + _u16Str{}, + _buffer{}, + _inPipe{ (HANDLE)hIn }, + _outPipe{(HANDLE)hOut} + { + hSig; // TODO: this needs to be packed into the hpcon + if (_guid == guid{}) + { + _guid = Utils::CreateGuid(); + } + } + ConptyConnection::ConptyConnection(const hstring& commandline, const hstring& startingDirectory, const hstring& startingTitle, @@ -222,9 +245,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(); diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index b3ca0827aa8..d7343c86999 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -19,6 +19,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { struct ConptyConnection : ConptyConnectionT, ConnectionStateHolder { + ConptyConnection(const uint64_t hSig, + const uint64_t hIn, + const uint64_t hOut); + ConptyConnection( const hstring& cmdline, const hstring& startingDirectory, diff --git a/src/cascadia/TerminalConnection/ConptyConnection.idl b/src/cascadia/TerminalConnection/ConptyConnection.idl index fc53f368b6d..bdbb8415721 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.idl +++ b/src/cascadia/TerminalConnection/ConptyConnection.idl @@ -8,6 +8,7 @@ namespace Microsoft.Terminal.TerminalConnection [default_interface] runtimeclass ConptyConnection : ITerminalConnection { + ConptyConnection(UInt64 hSig, UInt64 hIn, UInt64 hOut); ConptyConnection(String cmdline, String startingDirectory, String startingTitle, IMapView environment, UInt32 rows, UInt32 columns, Guid guid); Guid Guid { get; }; }; diff --git a/src/cascadia/wt/shim.cpp b/src/cascadia/wt/shim.cpp index 0b00fcaf962..218b68a00b5 100644 --- a/src/cascadia/wt/shim.cpp +++ b/src/cascadia/wt/shim.cpp @@ -32,5 +32,5 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int) // Go! wil::unique_process_information pi; - return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); + return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi); } diff --git a/src/host/ConsoleArguments.cpp b/src/host/ConsoleArguments.cpp index 41c07c79ba1..f50c9827036 100644 --- a/src/host/ConsoleArguments.cpp +++ b/src/host/ConsoleArguments.cpp @@ -596,6 +596,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 e2e7cad2d19..8569a337d04 100644 --- a/src/host/ConsoleArguments.hpp +++ b/src/host/ConsoleArguments.hpp @@ -43,6 +43,7 @@ class ConsoleArguments bool HasSignalHandle() const; HANDLE GetSignalHandle() const; + std::wstring GetOriginalCommandLine() const; std::wstring GetClientCommandline() const; std::wstring GetVtMode() const; bool GetForceV1() const; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 094aaf46d39..478a2145628 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -297,6 +297,30 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, return S_OK; } +// Function Description: +// - Returns the path to either conhost.exe or the side-by-side OpenConsole, depending on whether this +// module is building with Windows. +// Return Value: +// - A pointer to permanent storage containing the path to the console host. +static wchar_t* _ConsoleHostPath() +{ + // Use the magic of magic statics to only calculate this once. + static wil::unique_process_heap_string consoleHostPath = []() { +#ifdef __INSIDE_WINDOWS + wil::unique_process_heap_string systemDirectory; + wil::GetSystemDirectoryW(systemDirectory); + return wil::str_concat_failfast(L"\\\\?\\", systemDirectory, L"\\conhost.exe"); +#else + // Use the STL only if we're not building in Windows. + std::filesystem::path modulePath{ "D:\\src\\terminal\\src\\cascadia\\CascadiaPackage\\bin\\x64\\Debug\\AppX\\wtd.exe"}; + //modulePath.replace_filename(L"OpenConsole.exe"); + auto modulePathAsString{ modulePath.wstring() }; + return wil::make_process_heap_string_nothrow(modulePathAsString.data(), modulePathAsString.size()); +#endif // __INSIDE_WINDOWS + }(); + return consoleHostPath.get(); +} + HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... HANDLE driverInputEvent, @@ -308,6 +332,12 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, 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. @@ -317,7 +347,88 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(signalPipeOurSide.addressof(), signalPipeTheirSide.addressof(), &sa, 0)); RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(signalPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); - return ConsoleCreateIoThread(Server, args, driverInputEvent, connectMessage); + RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(inPipeOurSide.addressof(), inPipeTheirSide.addressof(), &sa, 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(), &sa, 0)); + RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(outPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); + + // GH4061: Ensure that the path to executable in the format is escaped so C:\Program.exe cannot collide with C:\Program Files + const wchar_t* pwszFormat = L"\"%s\" --pty %d"; + // This is plenty of space to hold the formatted string + wchar_t cmd[MAX_PATH]{}; + swprintf_s(cmd, + MAX_PATH, + pwszFormat, + _ConsoleHostPath(), + signalPipeTheirSide.get()); + + STARTUPINFOEXW siEx{ 0 }; + siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW); + siEx.StartupInfo.hStdInput = inPipeTheirSide.get(); + siEx.StartupInfo.hStdOutput = outPipeTheirSide.get(); + siEx.StartupInfo.hStdError = outPipeTheirSide.get(); + siEx.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + + // Only pass the handles we actually want the conhost to know about to it: + const size_t INHERITED_HANDLES_COUNT = 3; + HANDLE inheritedHandles[INHERITED_HANDLES_COUNT]; + inheritedHandles[0] = inPipeTheirSide.get(); + inheritedHandles[1] = outPipeTheirSide.get(); + inheritedHandles[2] = signalPipeTheirSide.get(); + + // Get the size of the attribute list. We need one attribute, the handle list. + SIZE_T listSize = 0; + InitializeProcThreadAttributeList(nullptr, 1, 0, &listSize); + + // I have to use a HeapAlloc here because kernelbase can't link new[] or delete[] + PPROC_THREAD_ATTRIBUTE_LIST attrList = static_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listSize)); + RETURN_IF_NULL_ALLOC(attrList); + auto attrListDelete = wil::scope_exit([&]() noexcept { + HeapFree(GetProcessHeap(), 0, attrList); + }); + + siEx.lpAttributeList = attrList; + RETURN_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &listSize)); + // Set cleanup data for ProcThreadAttributeList when successful. + auto cleanupProcThreadAttribute = wil::scope_exit([&]() noexcept { + DeleteProcThreadAttributeList(siEx.lpAttributeList); + }); + RETURN_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(siEx.lpAttributeList, + 0, + PROC_THREAD_ATTRIBUTE_HANDLE_LIST, + inheritedHandles, + (INHERITED_HANDLES_COUNT * sizeof(HANDLE)), + nullptr, + nullptr)); + wil::unique_process_information pi; + // Call create process + RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(_ConsoleHostPath(), + cmd, + nullptr, + nullptr, + TRUE, + EXTENDED_STARTUPINFO_PRESENT, + nullptr, + nullptr, + &siEx.StartupInfo, + pi.addressof())); + + inPipeTheirSide.release(); + outPipeTheirSide.release(); + signalPipeTheirSide.release(); + + + auto originalCommandLine = args->GetOriginalCommandLine(); + + auto str2 = fmt::format(L" --headless --signal {:#x}", (int64_t)signalPipeOurSide.release()); + + originalCommandLine = originalCommandLine.append(str2); + + ConsoleArguments args2(originalCommandLine, inPipeOurSide.release(), outPipeOurSide.release()); + RETURN_IF_FAILED(args2.ParseCommandline()); + + return ConsoleCreateIoThread(Server, &args2, driverInputEvent, connectMessage); } [[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 6c902bd1c5f..80d7ac5485e 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -158,8 +158,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API } Globals& Globals = ServiceLocator::LocateGlobals(); - if (!Globals.handoffTarget) - /*if (!ConsoleConnectionDeservesVisibleWindow(&Cac))*/ + if (!Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { From c0f890c45ad071c8997ab4bb6c7b30b6eed2f63d Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 27 Aug 2020 13:53:43 -0700 Subject: [PATCH 09/80] structure of the handoff. --- .../CascadiaPackage/CascadiaPackage.wapproj | 1 + .../CascadiaPackage/Package-Dev.appxmanifest | 17 ++++++ src/host/Handoff.cpp | 24 ++++++++ src/host/Handoff.h | 19 ++++++ src/host/IConsoleHandoff.idl | 35 +++++++++++ src/host/dll/Host.DLL.vcxproj | 5 +- src/host/dll/Host.DLL.vcxproj.filters | 14 +++-- src/host/dll/OpenConsoleDll.def | 6 +- src/host/dll/dllmain.cpp | 34 +++++++++++ src/host/exe/Host.EXE.vcxproj | 2 + src/host/lib/hostlib.vcxproj | 18 +++++- src/host/lib/hostlib.vcxproj.filters | 43 +++++++++---- src/host/srvinit.cpp | 4 ++ src/host/srvinit.h | 2 + src/server/IoDispatchers.cpp | 61 ++++++++++++++----- 15 files changed, 248 insertions(+), 37 deletions(-) create mode 100644 src/host/Handoff.cpp create mode 100644 src/host/Handoff.h create mode 100644 src/host/IConsoleHandoff.idl create mode 100644 src/host/dll/dllmain.cpp diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj index 237963a6428..6288590950a 100644 --- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj +++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj @@ -66,6 +66,7 @@ + diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index 173ca496ea7..7843c3265c6 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -69,9 +69,26 @@ Enabled="false" DisplayName="ms-resource:AppNameDev" /> + + + + 1F9F2BF5-5BC3-4F17-B0E6-912413F1F451 + + + + + + + diff --git a/src/host/Handoff.cpp b/src/host/Handoff.cpp new file mode 100644 index 00000000000..34432d092cd --- /dev/null +++ b/src/host/Handoff.cpp @@ -0,0 +1,24 @@ +#include "precomp.h" + +#include "Handoff.h" + +#include "srvinit.h" + +HRESULT Handoff::EstablishHandoff(HANDLE server, + HANDLE inputEvent, + PCCONSOLE_PORTABLE_ARGUMENTS args, + PCCONSOLE_PORTABLE_ATTACH_MSG msg) +{ + ConsoleArguments consoleArgs; + // consoleArgs = *args; + CONSOLE_API_MSG apiMsg; + // apiMsg = *msg; + + ConsoleEstablishHandoff(server, &consoleArgs, inputEvent, &apiMsg); + + UNREFERENCED_PARAMETER(server); + UNREFERENCED_PARAMETER(inputEvent); + UNREFERENCED_PARAMETER(args); + UNREFERENCED_PARAMETER(msg); + return S_FALSE; +} diff --git a/src/host/Handoff.h b/src/host/Handoff.h new file mode 100644 index 00000000000..7662e1ff1a9 --- /dev/null +++ b/src/host/Handoff.h @@ -0,0 +1,19 @@ +#pragma once + +#include "IConsoleHandoff_h.h" + +using namespace Microsoft::WRL; + +struct __declspec(uuid("1F9F2BF5-5BC3-4F17-B0E6-912413F1F451")) + Handoff : public RuntimeClass, IConsoleHandoff> +{ +#pragma region IConsoleHandoff + STDMETHODIMP EstablishHandoff(HANDLE server, + HANDLE inputEvent, + PCCONSOLE_PORTABLE_ARGUMENTS args, + PCCONSOLE_PORTABLE_ATTACH_MSG msg); + +#pragma endregion +}; + +CoCreatableClass(Handoff); diff --git a/src/host/IConsoleHandoff.idl b/src/host/IConsoleHandoff.idl new file mode 100644 index 00000000000..121a3c8d9b4 --- /dev/null +++ b/src/host/IConsoleHandoff.idl @@ -0,0 +1,35 @@ +import "oaidl.idl"; +import "ocidl.idl"; + +//static constexpr GUID IID_IConsoleHandoff = { 0x2B607BC1, 0x43EB, 0x40C3, { 0x95, 0xAE, 0x28, 0x56, 0xAD, 0xDB, 0x7F, 0x23 } }; + +typedef struct _CONSOLE_PORTABLE_ARGUMENTS +{ + HANDLE input; + HANDLE output; + [string] wchar_t* argString; +} CONSOLE_PORTABLE_ARGUMENTS; + +typedef CONSOLE_PORTABLE_ARGUMENTS* PCONSOLE_PORTABLE_ARGUMENTS; +typedef const CONSOLE_PORTABLE_ARGUMENTS* PCCONSOLE_PORTABLE_ARGUMENTS; + +typedef struct _CONSOLE_PORTABLE_ATTACH_MSG +{ + DWORD foo; +} CONSOLE_PORTABLE_ATTACH_MSG; + +typedef CONSOLE_PORTABLE_ATTACH_MSG* PCONSOLE_PORTABLE_ATTACH_MSG; +typedef const CONSOLE_PORTABLE_ATTACH_MSG* PCCONSOLE_PORTABLE_ATTACH_MSG; + +// IConsoleHandoff +[ + object, + uuid(2B607BC1-43EB-40C3-95AE-2856ADDB7F23), // IID_IConsoleHandoff + local +] interface IConsoleHandoff : IUnknown +{ + HRESULT EstablishHandoff([in] HANDLE server, + [in] HANDLE inputEvent, + [in, ref] PCCONSOLE_PORTABLE_ARGUMENTS args, + [in, ref] PCCONSOLE_PORTABLE_ATTACH_MSG msg); +}; diff --git a/src/host/dll/Host.DLL.vcxproj b/src/host/dll/Host.DLL.vcxproj index edc00dc2c0d..731175d17f6 100644 --- a/src/host/dll/Host.DLL.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -6,7 +6,7 @@ host Host.DLL OpenConsoleDll - DynamicLibrary + DynamicLibrary @@ -19,6 +19,7 @@ ProgramDatabase + @@ -90,4 +91,4 @@ - + \ No newline at end of file diff --git a/src/host/dll/Host.DLL.vcxproj.filters b/src/host/dll/Host.DLL.vcxproj.filters index 6bea8807962..e95896535b8 100644 --- a/src/host/dll/Host.DLL.vcxproj.filters +++ b/src/host/dll/Host.DLL.vcxproj.filters @@ -15,10 +15,13 @@ - + Source Files - + + Source Files + + Source Files @@ -31,7 +34,7 @@ - + Source Files @@ -40,4 +43,7 @@ Resource Files - + + + + \ No newline at end of file diff --git a/src/host/dll/OpenConsoleDll.def b/src/host/dll/OpenConsoleDll.def index b94a2674cb5..08758350e34 100644 --- a/src/host/dll/OpenConsoleDll.def +++ b/src/host/dll/OpenConsoleDll.def @@ -1,4 +1,6 @@ LIBRARY OpenConsoleDll -EXPORTS - \ No newline at end of file +EXPORTS + DllGetActivationFactory PRIVATE + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE diff --git a/src/host/dll/dllmain.cpp b/src/host/dll/dllmain.cpp new file mode 100644 index 00000000000..c5945d2c680 --- /dev/null +++ b/src/host/dll/dllmain.cpp @@ -0,0 +1,34 @@ +#include "precomp.h" + +#include + +using namespace Microsoft::WRL; + +#if !defined(__WRL_CLASSIC_COM__) +STDAPI DllGetActivationFactory(_In_ HSTRING activatibleClassId, _COM_Outptr_ IActivationFactory** factory) +{ + return Module::GetModule().GetActivationFactory(activatibleClassId, factory); +} +#endif + +#if !defined(__WRL_WINRT_STRICT__) +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) +{ + return Module::GetModule().GetClassObject(rclsid, riid, ppv); +} +#endif + +STDAPI DllCanUnloadNow() +{ + return Module::GetModule().Terminate() ? S_OK : S_FALSE; +} + +STDAPI_(BOOL) +DllMain(_In_opt_ HINSTANCE hinst, DWORD reason, _In_opt_ void*) +{ + if (reason == DLL_PROCESS_ATTACH) + { + DisableThreadLibraryCalls(hinst); + } + return TRUE; +} diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index 798cfca3841..d0c153df28d 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -83,6 +83,8 @@ ..;%(AdditionalIncludeDirectories) + + true diff --git a/src/host/lib/hostlib.vcxproj b/src/host/lib/hostlib.vcxproj index adc1124195a..575680b0c62 100644 --- a/src/host/lib/hostlib.vcxproj +++ b/src/host/lib/hostlib.vcxproj @@ -6,11 +6,25 @@ hostlib Host ConhostV2Lib - StaticLibrary + StaticLibrary + + + $(SolutionDir)src\host\ + + + + + + + + + + + - + \ No newline at end of file diff --git a/src/host/lib/hostlib.vcxproj.filters b/src/host/lib/hostlib.vcxproj.filters index bd95d735163..64567a4c773 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,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -254,9 +257,6 @@ Header Files - - Header Files - Header Files @@ -332,9 +332,6 @@ Header Files - - Header Files - Header Files @@ -353,5 +350,25 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + + + Source Files + - + \ No newline at end of file diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 478a2145628..08a18531a67 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -23,6 +23,8 @@ #include "renderData.hpp" #include "../renderer/base/renderer.hpp" +#include "./lib/Handoff_h.h" + #pragma hdrstop using namespace Microsoft::Console::Interactivity; @@ -321,6 +323,8 @@ static wchar_t* _ConsoleHostPath() return consoleHostPath.get(); } + + HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... HANDLE driverInputEvent, diff --git a/src/host/srvinit.h b/src/host/srvinit.h index b596096da76..8d8e9cc53ac 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -33,4 +33,6 @@ extern "C" __declspec(dllexport) HRESULT ConsoleEstablishHandoff(_In_ HANDLE Ser HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage); + + void ConsoleCheckDebug(); diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 80d7ac5485e..971b5479f8e 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -14,6 +14,13 @@ #include "..\host\srvinit.h" #include "..\host\telemetry.hpp" +#include "..\host\IConsoleHandoff_h.h" + +//2B607BC1-43EB-40C3-95AE-2856ADDB7F23 +//1F9F2BF5-5BC3-4F17-B0E6-912413F1F451 +//const IID IID_IConsoleHandoff = { 0x2b607bc1, 0x43eb, 0x40c3, 0x95, 0xae, 0x28, 0x56, 0xad, 0xdb, 0x7f, 0x23 }; +const CLSID CLSID_Handoff = { 0x1f9f2bf5, 0x5bc3, 0x4f17, 0xb0, 0xe6, 0x91, 0x24, 0x13, 0xf1, 0xf4, 0x51 }; + #include "..\interactivity\inc\ServiceLocator.hpp" using namespace Microsoft::Console::Interactivity; @@ -67,8 +74,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa handle)); break; - case CD_IO_OBJECT_TYPE_CURRENT_OUTPUT: - { + case CD_IO_OBJECT_TYPE_CURRENT_OUTPUT: { SCREEN_INFORMATION& ScreenInformation = gci.GetActiveOutputBuffer().GetMainBuffer(); Status = NTSTATUS_FROM_HRESULT(ScreenInformation.AllocateIoHandle(ConsoleHandleData::HandleType::Output, CreateInformation->DesiredAccess, @@ -160,20 +166,47 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API Globals& Globals = ServiceLocator::LocateGlobals(); if (!Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { - - - typedef HRESULT (*PFNHANDOFF)(HANDLE, - const ConsoleArguments* const, // this can't stay like this because ConsoleArguments could change... - HANDLE, - PCONSOLE_API_MSG); - - HMODULE mod = LoadLibraryW(L"OpenConsoleDll.dll"); - PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); - HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get(), pReceiveMsg); - if (SUCCEEDED(res)) + HRESULT hr; + hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(hr)) + { + ::Microsoft::WRL::ComPtr handoff; + hr = CoCreateInstance(CLSID_Handoff, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&handoff)); + if (SUCCEEDED(hr)) + { + CONSOLE_PORTABLE_ARGUMENTS args; + // args = &Globals.launchArgs + CONSOLE_PORTABLE_ATTACH_MSG msg; + // msg = pReceiveMsg + + hr = handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), + Globals.hInputEvent.get(), + &args, + &msg); + + if (SUCCEEDED(hr)) + { + ExitThread(S_OK); + } + } + } + if (FAILED(hr)) { - ExitThread(S_OK); + LOG_HR(hr); } + + //typedef HRESULT (*PFNHANDOFF)(HANDLE, + // const ConsoleArguments* const, // this can't stay like this because ConsoleArguments could change... + // HANDLE, + // PCONSOLE_API_MSG); + + //HMODULE mod = LoadLibraryW(L"OpenConsoleDll.dll"); + //PFNHANDOFF addr = (PFNHANDOFF)GetProcAddress(mod, "ConsoleEstablishHandoff"); + //HRESULT res = addr(Globals.pDeviceComm->_Server.get(), &Globals.launchArgs, Globals.hInputEvent.get(), pReceiveMsg); + //if (SUCCEEDED(res)) + //{ + // ExitThread(S_OK); + //} } Status = NTSTATUS_FROM_HRESULT(gci.ProcessHandleList.AllocProcessData(dwProcessId, From 9ce9930979ca5735b970cae78976f8bb0cc2da5e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 31 Aug 2020 14:46:35 -0700 Subject: [PATCH 10/80] We need to GUID it differently based on each release type. --- .../CascadiaPackage/Package-Pre.appxmanifest | 20 ++++++++++++++++++ .../CascadiaPackage/Package.appxmanifest | 21 ++++++++++++++++++- src/host/dll/ConsoleComGuids.h | 13 ++++++++++-- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 57a2a38c178..319d4688a67 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -70,8 +70,28 @@ Enabled="false" DisplayName="ms-resource:AppNamePre" /> + + + + 06EC847C-C0A5-46B8-92CB-7C92F6E35CD5 + + + + + + + + + + + + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 3565188a630..71493026f7d 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -70,9 +70,28 @@ Enabled="false" DisplayName="ms-resource:AppName" /> - + + + + 2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69 + + + + + + + + + + + + diff --git a/src/host/dll/ConsoleComGuids.h b/src/host/dll/ConsoleComGuids.h index db5f55985bc..42ef9cd97b2 100644 --- a/src/host/dll/ConsoleComGuids.h +++ b/src/host/dll/ConsoleComGuids.h @@ -1,5 +1,14 @@ #pragma once -#define __CLSID_IConsoleProxy DA2E620C-0B90-45D2-8362-A5B1006D9243 #define __IID_IConsoleHandoff 2B607BC1-43EB-40C3-95AE-2856ADDB7F23 -#define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" + +#if defined(WT_ReleaseBuild) + #define __CLSID_IConsoleProxy 3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F + #define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" +#elif defined(WT_PreviewBuild) + #define __CLSID_IConsoleProxy 1833E661-CC81-4DD0-87C6-C2F74BD39EFA + #define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" +#else + #define __CLSID_IConsoleProxy DA2E620C-0B90-45D2-8362-A5B1006D9243 + #define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" +#endif From a2718949f3d9587c873a9ad7a82d9ceb8c81c19e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 31 Aug 2020 14:51:29 -0700 Subject: [PATCH 11/80] some notes. --- src/host/globals.h | 1 + src/server/IoDispatchers.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/host/globals.h b/src/host/globals.h index e5e99aaeb2e..48bff80bef1 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -70,6 +70,7 @@ class Globals ApiRoutines api; bool handoffTarget = false; + std::optional handoffClsid; #ifdef UNIT_TESTING diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 847fb47f213..8c793726931 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -160,6 +160,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API } Globals& Globals = ServiceLocator::LocateGlobals(); + // TODO: only the inside windows one should probably bother trying to delegate, the out of box one could probably assume it doesn't need to. if (Globals.handoffClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { try From c89045b1186641da45e8543822c3ce7043e1f0c5 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 31 Aug 2020 15:21:00 -0700 Subject: [PATCH 12/80] Clean up junk that made it into this branch. --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 1 - src/cascadia/TerminalApp/ActionArgs.cpp | 1 - src/cascadia/TerminalApp/App.cpp | 1 - .../TerminalApp/AppActionHandlers.cpp | 1 - .../TerminalApp/AppCommandlineArgs.cpp | 1 - src/cascadia/TerminalApp/AppKeyBindings.cpp | 1 - .../AppKeyBindingsSerialization.cpp | 1 - src/cascadia/TerminalApp/AppLogic.cpp | 1 - .../TerminalApp/AzureCloudShellGenerator.cpp | 1 - src/cascadia/TerminalApp/CascadiaSettings.cpp | 1 - .../CascadiaSettingsSerialization.cpp | 1 - src/cascadia/TerminalApp/ColorHelper.cpp | 1 - src/cascadia/TerminalApp/ColorHelper.h | 1 - .../TerminalApp/ColorPickupFlyout.cpp | 1 - src/cascadia/TerminalApp/Command.cpp | 1 - src/cascadia/TerminalApp/CommandPalette.cpp | 1 - src/cascadia/TerminalApp/Commandline.cpp | 1 - .../TerminalApp/DebugTapConnection.cpp | 1 - .../TerminalApp/DefaultProfileUtils.cpp | 1 - .../TerminalApp/GlobalAppSettings.cpp | 1 - .../TerminalApp/KeyChordSerialization.cpp | 1 - .../TerminalApp/MinMaxCloseControl.cpp | 1 - .../TerminalApp/Pane.LayoutSizeNode.cpp | 1 - src/cascadia/TerminalApp/Pane.cpp | 1 - .../PowershellCoreProfileGenerator.cpp | 1 - src/cascadia/TerminalApp/Profile.cpp | 1 - .../TerminalApp/ShortcutActionDispatch.cpp | 1 - src/cascadia/TerminalApp/Tab.cpp | 1 - src/cascadia/TerminalApp/TabRowControl.cpp | 1 - src/cascadia/TerminalApp/TerminalPage.cpp | 1 - src/cascadia/TerminalApp/TitlebarControl.cpp | 1 - .../TerminalApp/WslDistroGenerator.cpp | 1 - .../TerminalApp/dll/TerminalApp.vcxproj | 2 +- src/cascadia/TerminalApp/lib/pch.h | 74 ------------------- src/host/VtIo.cpp | 2 +- 35 files changed, 2 insertions(+), 108 deletions(-) delete mode 100644 src/cascadia/TerminalApp/lib/pch.h diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index d0f251b388d..76943897177 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -1,5 +1,4 @@ #include "pch.h" -#include "lib/pch.h" #include "ActionArgs.h" #include "ActionAndArgs.h" #include "ActionAndArgs.g.cpp" diff --git a/src/cascadia/TerminalApp/ActionArgs.cpp b/src/cascadia/TerminalApp/ActionArgs.cpp index e72ad02a5a3..6cc367634c5 100644 --- a/src/cascadia/TerminalApp/ActionArgs.cpp +++ b/src/cascadia/TerminalApp/ActionArgs.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "ActionArgs.h" diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp index 707f846abd9..8e5022a69ad 100644 --- a/src/cascadia/TerminalApp/App.cpp +++ b/src/cascadia/TerminalApp/App.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "App.h" #include "App.g.cpp" diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index b83a71bf03c..8770f6037dc 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "App.h" #include "TerminalPage.h" diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index d4ed771b897..acc5af3b8b7 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "AppLogic.h" #include "AppCommandlineArgs.h" #include "ActionArgs.h" diff --git a/src/cascadia/TerminalApp/AppKeyBindings.cpp b/src/cascadia/TerminalApp/AppKeyBindings.cpp index 023bc916aa4..166200cf132 100644 --- a/src/cascadia/TerminalApp/AppKeyBindings.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindings.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "AppKeyBindings.h" #include "KeyChordSerialization.h" diff --git a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp index 426d9c3a692..2bb507ec86f 100644 --- a/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp +++ b/src/cascadia/TerminalApp/AppKeyBindingsSerialization.cpp @@ -7,7 +7,6 @@ // - Mike Griese - May 2019 #include "pch.h" -#include "lib/pch.h" #include "AppKeyBindings.h" #include "ActionAndArgs.h" #include "KeyChordSerialization.h" diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 964b212d4a6..4fb102f7dd6 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "AppLogic.h" #include "AppLogic.g.cpp" #include diff --git a/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp b/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp index 0463adf160f..5a5fc7ba150 100644 --- a/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp +++ b/src/cascadia/TerminalApp/AzureCloudShellGenerator.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include diff --git a/src/cascadia/TerminalApp/CascadiaSettings.cpp b/src/cascadia/TerminalApp/CascadiaSettings.cpp index 80f9769885f..73bcc0e903c 100644 --- a/src/cascadia/TerminalApp/CascadiaSettings.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettings.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include #include #include diff --git a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp index 88f93647849..06dc5e55bd9 100644 --- a/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp +++ b/src/cascadia/TerminalApp/CascadiaSettingsSerialization.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include #include "CascadiaSettings.h" #include "../../types/inc/utils.hpp" diff --git a/src/cascadia/TerminalApp/ColorHelper.cpp b/src/cascadia/TerminalApp/ColorHelper.cpp index 90066757ee1..1e8d061a3c9 100644 --- a/src/cascadia/TerminalApp/ColorHelper.cpp +++ b/src/cascadia/TerminalApp/ColorHelper.cpp @@ -1,5 +1,4 @@ #include "pch.h" -#include "lib/pch.h" #include "ColorHelper.h" #include diff --git a/src/cascadia/TerminalApp/ColorHelper.h b/src/cascadia/TerminalApp/ColorHelper.h index 09f89bfa9d0..cbe6582c8d1 100644 --- a/src/cascadia/TerminalApp/ColorHelper.h +++ b/src/cascadia/TerminalApp/ColorHelper.h @@ -1,6 +1,5 @@ #pragma once #include "pch.h" -#include "lib/pch.h" #include diff --git a/src/cascadia/TerminalApp/ColorPickupFlyout.cpp b/src/cascadia/TerminalApp/ColorPickupFlyout.cpp index 0a32f4f1e6f..b1c15be4818 100644 --- a/src/cascadia/TerminalApp/ColorPickupFlyout.cpp +++ b/src/cascadia/TerminalApp/ColorPickupFlyout.cpp @@ -1,5 +1,4 @@ #include "pch.h" -#include "lib/pch.h" #include "ColorPickupFlyout.h" #include "ColorPickupFlyout.g.cpp" #include "winrt/Windows.UI.Xaml.Media.h" diff --git a/src/cascadia/TerminalApp/Command.cpp b/src/cascadia/TerminalApp/Command.cpp index ad82aefb9a3..2c66cdf7dd4 100644 --- a/src/cascadia/TerminalApp/Command.cpp +++ b/src/cascadia/TerminalApp/Command.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "Command.h" #include "Command.g.cpp" diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 37d329789e8..307ca975ba2 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "CommandPalette.h" #include "ActionAndArgs.h" #include "ActionArgs.h" diff --git a/src/cascadia/TerminalApp/Commandline.cpp b/src/cascadia/TerminalApp/Commandline.cpp index 93e51417d97..b40591d7f29 100644 --- a/src/cascadia/TerminalApp/Commandline.cpp +++ b/src/cascadia/TerminalApp/Commandline.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "Commandline.h" using namespace TerminalApp; diff --git a/src/cascadia/TerminalApp/DebugTapConnection.cpp b/src/cascadia/TerminalApp/DebugTapConnection.cpp index 8cceb56f074..d149ad46213 100644 --- a/src/cascadia/TerminalApp/DebugTapConnection.cpp +++ b/src/cascadia/TerminalApp/DebugTapConnection.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "DebugTapConnection.h" #include "Utils.h" diff --git a/src/cascadia/TerminalApp/DefaultProfileUtils.cpp b/src/cascadia/TerminalApp/DefaultProfileUtils.cpp index 5888f5782ec..18c59ef6e88 100644 --- a/src/cascadia/TerminalApp/DefaultProfileUtils.cpp +++ b/src/cascadia/TerminalApp/DefaultProfileUtils.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "DefaultProfileUtils.h" #include "../../types/inc/utils.hpp" diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 72c6bb64816..7507e83bdc6 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "GlobalAppSettings.h" #include "../../types/inc/Utils.hpp" #include "../../inc/DefaultSettings.h" diff --git a/src/cascadia/TerminalApp/KeyChordSerialization.cpp b/src/cascadia/TerminalApp/KeyChordSerialization.cpp index 0c69b914b73..16e9732a57f 100644 --- a/src/cascadia/TerminalApp/KeyChordSerialization.cpp +++ b/src/cascadia/TerminalApp/KeyChordSerialization.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "KeyChordSerialization.h" using namespace winrt::Microsoft::Terminal::TerminalControl; diff --git a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp index 500c06572b0..ee5f3e0d9b7 100644 --- a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp +++ b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp @@ -6,7 +6,6 @@ // #include "pch.h" -#include "lib/pch.h" #include "MinMaxCloseControl.h" diff --git a/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp b/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp index 5f5bf7fda86..f3cc8647ff1 100644 --- a/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp +++ b/src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "Pane.h" Pane::LayoutSizeNode::LayoutSizeNode(const float minSize) : diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index c2788591894..754c7e56c52 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "Pane.h" #include "Profile.h" #include "CascadiaSettings.h" diff --git a/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp b/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp index 39d4d761d83..364a42e0c19 100644 --- a/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp +++ b/src/cascadia/TerminalApp/PowershellCoreProfileGenerator.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "PowershellCoreProfileGenerator.h" #include "LegacyProfileGeneratorNamespaces.h" diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index 935513338ae..c515c4cd414 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "Profile.h" #include "Utils.h" #include "JsonUtils.h" diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 43753400a57..cce86db1988 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "ShortcutActionDispatch.h" #include "ShortcutActionDispatch.g.cpp" diff --git a/src/cascadia/TerminalApp/Tab.cpp b/src/cascadia/TerminalApp/Tab.cpp index ba01d3b1334..43f29440745 100644 --- a/src/cascadia/TerminalApp/Tab.cpp +++ b/src/cascadia/TerminalApp/Tab.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include #include "ColorPickupFlyout.h" #include "Tab.h" diff --git a/src/cascadia/TerminalApp/TabRowControl.cpp b/src/cascadia/TerminalApp/TabRowControl.cpp index b91d6a526f4..bc4d7a83968 100644 --- a/src/cascadia/TerminalApp/TabRowControl.cpp +++ b/src/cascadia/TerminalApp/TabRowControl.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "TabRowControl.h" #include "TabRowControl.g.cpp" diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index f9ac37f3efe..70497fb065f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "TerminalPage.h" #include "ActionAndArgs.h" #include "Utils.h" diff --git a/src/cascadia/TerminalApp/TitlebarControl.cpp b/src/cascadia/TerminalApp/TitlebarControl.cpp index 7e8e6a222a3..05806726cfe 100644 --- a/src/cascadia/TerminalApp/TitlebarControl.cpp +++ b/src/cascadia/TerminalApp/TitlebarControl.cpp @@ -6,7 +6,6 @@ // #include "pch.h" -#include "lib/pch.h" #include "TitlebarControl.h" diff --git a/src/cascadia/TerminalApp/WslDistroGenerator.cpp b/src/cascadia/TerminalApp/WslDistroGenerator.cpp index db67cb25717..3f2c655fecb 100644 --- a/src/cascadia/TerminalApp/WslDistroGenerator.cpp +++ b/src/cascadia/TerminalApp/WslDistroGenerator.cpp @@ -2,7 +2,6 @@ // Licensed under the MIT license. #include "pch.h" -#include "lib/pch.h" #include "WslDistroGenerator.h" #include "LegacyProfileGeneratorNamespaces.h" diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index ba27e6f3260..8ff76f91d3f 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -90,7 +90,7 @@ - $(OpenConsoleDir)\cascadia\TerminalApp\lib\;$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); + $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) diff --git a/src/cascadia/TerminalApp/lib/pch.h b/src/cascadia/TerminalApp/lib/pch.h deleted file mode 100644 index 26326b13ac9..00000000000 --- a/src/cascadia/TerminalApp/lib/pch.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. -// -// lib/pch.h -// Header for platform projection include files -// - -#pragma once - -#define WIN32_LEAN_AND_MEAN - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#define BLOCK_TIL -#include -// This is inexplicable, but for whatever reason, cppwinrt conflicts with the -// SDK definition of this function, so the only fix is to undef it. -// from WinBase.h -// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime -#ifdef GetCurrentTime -#undef GetCurrentTime -#endif - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "winrt/Windows.UI.Xaml.Markup.h" -#include "winrt/Windows.UI.Xaml.Documents.h" -#include "winrt/Windows.UI.Xaml.Automation.h" -#include -#include - -#include -#include -#include -#include - -#include - -#include - -// Including TraceLogging essentials for the binary -#include -#include -TRACELOGGING_DECLARE_PROVIDER(g_hTerminalAppProvider); -#include -#include - -// JsonCpp -#include - -#include - -#include -#include - -#include - -// Manually include til after we include Windows.Foundation to give it winrt superpowers -#include "til.h" diff --git a/src/host/VtIo.cpp b/src/host/VtIo.cpp index 4208e9af17b..17789de025f 100644 --- a/src/host/VtIo.cpp +++ b/src/host/VtIo.cpp @@ -106,7 +106,7 @@ VtIo::VtIo() : const std::wstring& VtMode, _In_opt_ const HANDLE SignalHandle) { -// FAIL_FAST_IF_MSG(_initialized, "Someone attempted to double-_Initialize VtIo"); + FAIL_FAST_IF_MSG(_initialized, "Someone attempted to double-_Initialize VtIo"); RETURN_IF_FAILED(ParseIoMode(VtMode, _IoMode)); From 9a49a557dd711026183d27da7d693ec06db45618 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 31 Aug 2020 15:22:45 -0700 Subject: [PATCH 13/80] I don't think these are cpp anymore --- src/cascadia/TerminalApp/JsonUtils.cpp | 126 ------------------------- 1 file changed, 126 deletions(-) delete mode 100644 src/cascadia/TerminalApp/JsonUtils.cpp diff --git a/src/cascadia/TerminalApp/JsonUtils.cpp b/src/cascadia/TerminalApp/JsonUtils.cpp deleted file mode 100644 index 1ca8fd18e2a..00000000000 --- a/src/cascadia/TerminalApp/JsonUtils.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT license. - -#include "pch.h" -#include "lib/pch.h" -#include "Utils.h" -#include "JsonUtils.h" -#include "../../types/inc/Utils.hpp" - -void TerminalApp::JsonUtils::GetOptionalColor(const Json::Value& json, - std::string_view key, - std::optional& target) -{ - const auto conversionFn = [](const Json::Value& value) -> til::color { - return ::Microsoft::Console::Utils::ColorFromHexString(value.asString()); - }; - GetOptionalValue(json, - key, - target, - conversionFn); -} - -void TerminalApp::JsonUtils::GetOptionalString(const Json::Value& json, - std::string_view key, - std::optional& target) -{ - const auto conversionFn = [](const Json::Value& value) -> std::wstring { - return GetWstringFromJson(value); - }; - GetOptionalValue(json, - key, - target, - conversionFn); -} - -void TerminalApp::JsonUtils::GetOptionalGuid(const Json::Value& json, - std::string_view key, - std::optional& target) -{ - const auto conversionFn = [](const Json::Value& value) -> GUID { - return ::Microsoft::Console::Utils::GuidFromString(GetWstringFromJson(value)); - }; - GetOptionalValue(json, - key, - target, - conversionFn); -} - -void TerminalApp::JsonUtils::GetOptionalDouble(const Json::Value& json, - std::string_view key, - std::optional& target) -{ - const auto conversionFn = [](const Json::Value& value) -> double { - return value.asFloat(); - }; - const auto validationFn = [](const Json::Value& value) -> bool { - return value.isNumeric(); - }; - GetOptionalValue(json, - key, - target, - conversionFn, - validationFn); -} - -void TerminalApp::JsonUtils::GetInt(const Json::Value& json, - std::string_view key, - int& target) -{ - const auto conversionFn = [](const Json::Value& value) -> int { - return value.asInt(); - }; - const auto validationFn = [](const Json::Value& value) -> bool { - return value.isInt(); - }; - GetValue(json, key, target, conversionFn, validationFn); -} - -void TerminalApp::JsonUtils::GetUInt(const Json::Value& json, - std::string_view key, - uint32_t& target) -{ - const auto conversionFn = [](const Json::Value& value) -> uint32_t { - return value.asUInt(); - }; - const auto validationFn = [](const Json::Value& value) -> bool { - return value.isUInt(); - }; - GetValue(json, key, target, conversionFn, validationFn); -} - -void TerminalApp::JsonUtils::GetDouble(const Json::Value& json, - std::string_view key, - double& target) -{ - const auto conversionFn = [](const Json::Value& value) -> double { - return value.asFloat(); - }; - const auto validationFn = [](const Json::Value& value) -> bool { - return value.isNumeric(); - }; - GetValue(json, key, target, conversionFn, validationFn); -} - -void TerminalApp::JsonUtils::GetBool(const Json::Value& json, - std::string_view key, - bool& target) -{ - const auto conversionFn = [](const Json::Value& value) -> bool { - return value.asBool(); - }; - const auto validationFn = [](const Json::Value& value) -> bool { - return value.isBool(); - }; - GetValue(json, key, target, conversionFn, validationFn); -} - -void TerminalApp::JsonUtils::GetWstring(const Json::Value& json, - std::string_view key, - std::wstring& target) -{ - const auto conversionFn = [](const Json::Value& value) -> std::wstring { - return GetWstringFromJson(value); - }; - GetValue(json, key, target, conversionFn, nullptr); -} From f5510b39d1fa8b50432e03380b8b517cd8f54eeb Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Mon, 31 Aug 2020 15:23:29 -0700 Subject: [PATCH 14/80] revert changes here. --- src/cascadia/TerminalApp/dll/TerminalApp.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj index 8ff76f91d3f..8d8962cca79 100644 --- a/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj +++ b/src/cascadia/TerminalApp/dll/TerminalApp.vcxproj @@ -90,7 +90,7 @@ - $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); + $(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories); User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies) From 0127fa0a88a8575e8276ea7ed1eff7bf105b07fe Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 1 Sep 2020 15:12:14 -0700 Subject: [PATCH 15/80] A bunch of work to COM-server-ify the Terminal part of things. --- .../CascadiaPackage/Package-Dev.appxmanifest | 19 ++- .../CascadiaPackage/Package-Pre.appxmanifest | 19 ++- .../CascadiaPackage/Package.appxmanifest | 19 ++- .../TerminalApp/AppActionHandlers.cpp | 7 + .../TerminalApp/AppCommandlineArgs.cpp | 34 +--- src/cascadia/TerminalApp/AppCommandlineArgs.h | 4 - src/cascadia/TerminalApp/AppLogic.cpp | 10 +- .../Resources/en-US/Resources.resw | 65 ++++---- .../TerminalApp/ShortcutActionDispatch.cpp | 5 + .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 4 +- src/cascadia/TerminalApp/TerminalPage.cpp | 63 +++++--- src/cascadia/TerminalApp/TerminalPage.h | 11 +- .../TerminalConnection/CTerminalHandoff.cpp | 62 ++++++++ .../TerminalConnection/CTerminalHandoff.h | 22 +++ .../TerminalConnection/ConptyConnection.cpp | 26 +++ .../TerminalConnection/ConptyConnection.h | 16 +- .../TerminalConnection/ConptyConnection.idl | 11 +- .../ITerminalConnection.idl | 2 + .../TerminalConnection.vcxproj | 5 +- .../TerminalConnection.vcxproj.filters | 6 +- src/host/dll/ConsoleComGuids.h | 4 + src/host/dll/Host.DLL.vcxproj | 4 + src/host/dll/Host.DLL.vcxproj.filters | 12 ++ src/host/dll/ITerminalHandoff.idl | 15 ++ src/host/exe/CConsoleHandoff.cpp | 2 +- src/host/globals.h | 3 +- src/host/srvinit.cpp | 109 +++---------- src/host/ut_host/ConsoleArgumentsTests.cpp | 150 ++++++++++++------ src/propslib/DelegationConfig.cpp | 16 +- src/propslib/DelegationConfig.hpp | 6 +- src/server/IoDispatchers.cpp | 4 +- 32 files changed, 480 insertions(+), 256 deletions(-) create mode 100644 src/cascadia/TerminalConnection/CTerminalHandoff.cpp create mode 100644 src/cascadia/TerminalConnection/CTerminalHandoff.h create mode 100644 src/host/dll/ITerminalHandoff.idl diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index cf626c525b8..bc279140644 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -70,7 +70,7 @@ DisplayName="ms-resource:AppNameDev" /> - 1F9F2BF5-5BC3-4F17-B0E6-912413F1F451 - + + + + + + E7B98685-0CC0-45D6-8F4C-B7C863C03DE2 + + + @@ -91,6 +103,9 @@ + + + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 319d4688a67..8b34a0a6e5b 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -71,7 +71,7 @@ DisplayName="ms-resource:AppNamePre" /> - 06EC847C-C0A5-46B8-92CB-7C92F6E35CD5 - + + + + + + 86633F1F-6454-40EC-89CE-DA4EBA977EE2 + + + @@ -92,6 +104,9 @@ + + + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 71493026f7d..5c641ecf21b 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -71,7 +71,7 @@ DisplayName="ms-resource:AppName" /> - 2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69 - + + + + + + E12CFF52-A866-4C77-9A90-F570A7AA2C6B + + + @@ -92,6 +104,9 @@ + + + diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 8770f6037dc..7a220997e9c 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -495,4 +495,11 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + + void TerminalPage::_HandleToggleInboundPty(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + ToggleInboundPty(); + args.Handled(true); + } } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index acc5af3b8b7..08f8cd846ca 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -174,9 +174,14 @@ void AppCommandlineArgs::_buildParser() }; _app.add_flag_function("-v,--version", versionCallback, RS_A(L"CmdVersionDesc")); - // Incoming PTY flags - // --pty - _app.add_option("--pty", _ptySigHandle, "PTY Signal Handle"); + // Started explicitly as a COM server for incoming PTY flags + // /Embedding (we don't pick this, it's just how COM does it.) + auto comEmbeddingCallback = [this](int64_t /*count*/) { + auto embeddingAction = winrt::make_self(); + embeddingAction->Action(ShortcutAction::ToggleInboundPty); + _startupActions.push_back(*embeddingAction); + }; + _app.add_flag_function("--embedding", comEmbeddingCallback, RS_A(L"CmdEmbeddingDesc")); // Maximized and Fullscreen flags // -M,--maximized: Maximizes the window on launch @@ -468,8 +473,6 @@ void AppCommandlineArgs::_resetStateToDefault() _focusNextTab = false; _focusPrevTab = false; - _ptySigHandle = 0; - // DON'T clear _launchMode here! This will get called once for every // subcommand, so we don't want `wt -F new-tab ; split-pane` clearing out // the "global" fullscreen flag (-F). @@ -638,22 +641,6 @@ bool AppCommandlineArgs::ShouldExitEarly() const noexcept return _shouldExitEarly; } -bool AppCommandlineArgs::HasStartupHandles() const noexcept -{ - return _ptySigHandle != 0; -} - -winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection AppCommandlineArgs::GetStartupConnection() -{ - uint64_t ptySigHandle = (uint64_t)_ptySigHandle; - uint64_t ptyOutHandle = (uint64_t)GetStdHandle(STD_OUTPUT_HANDLE); - uint64_t ptyInHandle = (uint64_t)GetStdHandle(STD_INPUT_HANDLE); - ptySigHandle; - ptyOutHandle; - ptyInHandle; - return winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection(ptySigHandle, ptyInHandle, ptyOutHandle); -} - // Method Description: // - Ensure that the first command in our list of actions is a NewTab action. // This makes sure that if the user passes a commandline like "wt split-pane @@ -683,11 +670,6 @@ void AppCommandlineArgs::ValidateStartupCommands() // push the arg onto the front _startupActions.insert(_startupActions.begin(), 1, *newTabAction); } - - if (_ptySigHandle != 0) - { - - } } std::optional AppCommandlineArgs::GetLaunchMode() const noexcept diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index da57aa3b609..7b571788c15 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -37,8 +37,6 @@ class TerminalApp::AppCommandlineArgs final static std::vector BuildCommands(const std::vector& args); static std::vector BuildCommands(winrt::array_view& args); - bool HasStartupHandles() const noexcept; - winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection GetStartupConnection(); void ValidateStartupCommands(); std::vector& GetStartupActions(); const std::string& GetExitMessage(); @@ -77,8 +75,6 @@ class TerminalApp::AppCommandlineArgs final CLI::App* _focusTabShort; // Are you adding a new sub-command? Make sure to update _noCommandsProvided! - int64_t _ptySigHandle; - std::string _profileName; std::string _startingDirectory; std::string _startingTitle; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 4fb102f7dd6..2a02e80dd13 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -989,15 +989,7 @@ namespace winrt::TerminalApp::implementation if (result == 0) { _appArgs.ValidateStartupCommands(); - if (_appArgs.HasStartupHandles()) - { - auto conn = _appArgs.GetStartupConnection(); - _root->SetStartupConnection(conn); - } - else - { - _root->SetStartupActions(_appArgs.GetStartupActions()); - } + _root->SetStartupActions(_appArgs.GetStartupActions()); } return result; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index ce6b1d0e656..436db84084d 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - @@ -204,12 +204,12 @@ Warnings were found while parsing your keybindings: - • Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array. - {Locked="\"keys\"","•"} This glyph is a bullet, used in a bulleted list. + • Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array. + {Locked="\"keys\"","•"} This glyph is a bullet, used in a bulleted list. - • Found a keybinding that was missing a required parameter value. This keybinding will be ignored. - {Locked="•"} This glyph is a bullet, used in a bulleted list. + • Found a keybinding that was missing a required parameter value. This keybinding will be ignored. + {Locked="•"} This glyph is a bullet, used in a bulleted list. The "globals" property is deprecated - your settings might need updating. @@ -652,4 +652,7 @@ Close all tabs after the current tab + + Listens for inbound pty connections + \ No newline at end of file diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index cce86db1988..a65724220c6 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -231,6 +231,11 @@ namespace winrt::TerminalApp::implementation _TabSearchHandlers(*this, *eventArgs); break; } + case ShortcutAction::ToggleInboundPty: + { + _ToggleInboundPtyHandlers(*this, *eventArgs); + break; + } default: return false; } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index caecb41ef77..d16e530be54 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -61,6 +61,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(CloseOtherTabs, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(CloseTabsAfter, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(TabSearch, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ToggleInboundPty, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 48d9eb923ce..d03dacef34c 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -46,7 +46,8 @@ namespace TerminalApp ToggleCommandPalette, CloseOtherTabs, CloseTabsAfter, - TabSearch + TabSearch, + ToggleInboundPty }; [default_interface] runtimeclass ActionAndArgs { @@ -98,5 +99,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler CloseOtherTabs; event Windows.Foundation.TypedEventHandler CloseTabsAfter; event Windows.Foundation.TypedEventHandler TabSearch; + event Windows.Foundation.TypedEventHandler ToggleInboundPty; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 70497fb065f..b594ca2982f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -195,6 +195,10 @@ namespace winrt::TerminalApp::implementation // Hookup our event handlers to the ShortcutActionDispatch _RegisterActionCallbacks(); + // Hook up inbound PTY event handlers + InboundPtyChanged({ this, &TerminalPage::_OnInboundPtyChanged }); + //Microsoft::Terminal::TerminalConnection::ConptyConnection::NewConnection(&TerminalPage::_OnNewConnection); + //Event Bindings (Early) _newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) { if (auto page{ weakThis.get() }) @@ -284,24 +288,15 @@ namespace winrt::TerminalApp::implementation if (_startupState == StartupState::NotInitialized) { _startupState = StartupState::InStartup; - if (_startupConnection) + if (_startupActions.Size() == 0) { - _OpenNewTab(nullptr, _startupConnection); + _OpenNewTab(nullptr); _CompleteInitialization(); } else { - if (_startupActions.Size() == 0) - { - _OpenNewTab(nullptr); - - _CompleteInitialization(); - } - else - { - _ProcessStartupActions(_startupActions, true); - } + _ProcessStartupActions(_startupActions, true); } } } @@ -339,7 +334,7 @@ namespace winrt::TerminalApp::implementation } else { - return; + co_return; } } } @@ -951,6 +946,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->CloseOtherTabs({ this, &TerminalPage::_HandleCloseOtherTabs }); _actionDispatch->CloseTabsAfter({ this, &TerminalPage::_HandleCloseTabsAfter }); _actionDispatch->TabSearch({ this, &TerminalPage::_HandleOpenTabSearch }); + _actionDispatch->ToggleInboundPty({ this, &TerminalPage::_HandleToggleInboundPty }); } // Method Description: @@ -2069,11 +2065,6 @@ namespace winrt::TerminalApp::implementation _alwaysOnTopChangedHandlers(*this, nullptr); } - void TerminalPage::SetStartupConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection conn) - { - _startupConnection = conn; - } - // This is a helper to aid in sorting commands by their `Name`s, alphabetically. static bool _compareSchemeNames(const winrt::TerminalApp::ColorScheme& lhs, const winrt::TerminalApp::ColorScheme& rhs) { @@ -2241,6 +2232,18 @@ namespace winrt::TerminalApp::implementation _alwaysOnTopChangedHandlers(*this, nullptr); } + // Method Description: + // - Toggles inbound pty mode. Raises InboundPtyChanged event. + // Arguments: + // - + // Return Value: + // - + void TerminalPage::ToggleInboundPty() + { + _isInboundPty = !_isInboundPty; + _inboundPtyChangedHandlers(*this, nullptr); + } + // Method Description: // - Returns a com_ptr to the implementation type of the tab at the given index // Arguments: @@ -2495,6 +2498,29 @@ namespace winrt::TerminalApp::implementation return _isAlwaysOnTop; } + bool TerminalPage::InboundPty() const + { + return _isInboundPty; + } + + + void TerminalPage::_OnInboundPtyChanged(const IInspectable& /*sender*/, + const IInspectable& /*eventArgs*/) + { + if (InboundPty()) + { + ConptyConnection::StartInboundListener(); + } + else + { + ConptyConnection::StopInboundListener(); + } + } + + //void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection /*connection*/) + //{ + //} + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. @@ -2504,4 +2530,5 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, InboundPtyChanged, _inboundPtyChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 26b5d2ab088..47177c325a0 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -9,6 +9,7 @@ #include "Profile.h" #include +//#include #include "AppCommandlineArgs.h" @@ -53,11 +54,12 @@ namespace winrt::TerminalApp::implementation void ToggleFocusMode(); void ToggleFullscreen(); void ToggleAlwaysOnTop(); + void ToggleInboundPty(); bool FocusMode() const; bool Fullscreen() const; bool AlwaysOnTop() const; + bool InboundPty() const; - void SetStartupConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection conn); void SetStartupActions(std::vector& actions); static std::vector ConvertExecuteCommandlineToActions(const TerminalApp::ExecuteCommandlineArgs& args); @@ -71,6 +73,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(InboundPtyChanged, _inboundPtyChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); private: @@ -96,6 +99,7 @@ namespace winrt::TerminalApp::implementation bool _isInFocusMode{ false }; bool _isFullscreen{ false }; bool _isAlwaysOnTop{ false }; + bool _isInboundPty{ false }; bool _rearranging; std::optional _rearrangeFrom; @@ -109,7 +113,6 @@ namespace winrt::TerminalApp::implementation winrt::Windows::UI::Xaml::Controls::Grid::LayoutUpdated_revoker _layoutUpdatedRevoker; StartupState _startupState{ StartupState::NotInitialized }; - winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _startupConnection{ nullptr }; Windows::Foundation::Collections::IVector _startupActions; winrt::fire_and_forget _ProcessStartupActions(Windows::Foundation::Collections::IVector actions, const bool initial); @@ -201,6 +204,9 @@ namespace winrt::TerminalApp::implementation void _UnZoomIfNeeded(); + void _OnInboundPtyChanged(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 TerminalApp::ActionEventArgs& args); @@ -240,6 +246,7 @@ namespace winrt::TerminalApp::implementation void _HandleCloseOtherTabs(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleCloseTabsAfter(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleOpenTabSearch(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleToggleInboundPty(const IInspectable& sender, const TerminalApp::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 00000000000..8e7bc18ebd1 --- /dev/null +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -0,0 +1,62 @@ +#include "pch.h" + +#include "CTerminalHandoff.h" + +static NewHandoff _pfnHandoff = nullptr; + +// Routine Description: +// - Called back when COM says there is nothing left for our server to do and we can tear down. +void _releaseNotifier() noexcept +{ + CTerminalHandoff::StopListening(); +} + +HRESULT CTerminalHandoff::StartListening(NewHandoff pfnHandoff) +{ + RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); + + RETURN_IF_FAILED(Module::Create(&_releaseNotifier).RegisterObjects()); + + _pfnHandoff = pfnHandoff; + + return S_OK; +} + +HRESULT CTerminalHandoff::StopListening() +{ + _pfnHandoff = nullptr; + + RETURN_IF_FAILED(Module::Create(&_releaseNotifier).UnregisterObjects()); + + CoUninitialize(); + + 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` +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; +} + +HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) +{ + // 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)); + + // Call registered handler from when we started listening. + return _pfnHandoff(in, out, signal); +} diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h new file mode 100644 index 00000000000..87ef57ed803 --- /dev/null +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -0,0 +1,22 @@ +#pragma once + +#include "..\host\dll\ITerminalHandoff_h.h" + +using namespace Microsoft::WRL; + +typedef HRESULT (*NewHandoff)(HANDLE, HANDLE, HANDLE); + +struct __declspec(uuid(__CLSID_CTerminalHandoff)) + CTerminalHandoff : public RuntimeClass, ITerminalHandoff> +{ +#pragma region ITerminalHandoff + STDMETHODIMP EstablishHandoff(HANDLE in, + HANDLE out, + HANDLE signal); +#pragma endregion + + static HRESULT StartListening(NewHandoff pfnHandoff); + static HRESULT StopListening(); +}; + +CoCreatableClass(CTerminalHandoff); diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 3a665c908fb..e48303f8cd3 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -13,6 +13,7 @@ #include #include "ConptyConnection.g.cpp" +#include "CTerminalHandoff.h" #include "../../types/inc/utils.hpp" #include "../../types/inc/Environment.hpp" @@ -481,4 +482,29 @@ 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) noexcept + try + { + UNREFERENCED_PARAMETER(in); + UNREFERENCED_PARAMETER(out); + UNREFERENCED_PARAMETER(signal); + //_newConnectionHandlers(in, out, signal); + return S_FALSE; + } + CATCH_RETURN() + + void ConptyConnection::StartInboundListener() + { + THROW_IF_FAILED(CTerminalHandoff::StartListening(&ConptyConnection::NewHandoff)); + } + + void ConptyConnection::StopInboundListener() + { + THROW_IF_FAILED(CTerminalHandoff::StopListening()); + } } diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index d7343c86999..622fcddad97 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -19,10 +19,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { struct ConptyConnection : ConptyConnectionT, ConnectionStateHolder { - ConptyConnection(const uint64_t hSig, - const uint64_t hIn, - const uint64_t hOut); - ConptyConnection( const hstring& cmdline, const hstring& startingDirectory, @@ -39,13 +35,25 @@ 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: + ConptyConnection(const uint64_t hSig, + const uint64_t hIn, + const uint64_t hOut); + HRESULT _LaunchAttachedClient() noexcept; void _indicateExitWithStatus(unsigned int status) noexcept; void _ClientTerminated() noexcept; + static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept; + uint32_t _initialRows{}; uint32_t _initialCols{}; hstring _commandline; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.idl b/src/cascadia/TerminalConnection/ConptyConnection.idl index bdbb8415721..766c7263a50 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.idl +++ b/src/cascadia/TerminalConnection/ConptyConnection.idl @@ -5,12 +5,13 @@ import "ITerminalConnection.idl"; namespace Microsoft.Terminal.TerminalConnection { - [default_interface] - runtimeclass ConptyConnection : ITerminalConnection + [default_interface] runtimeclass ConptyConnection : ITerminalConnection { - ConptyConnection(UInt64 hSig, UInt64 hIn, UInt64 hOut); - 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 398724cd882..e485cc06dbb 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 9c3713ea0b2..1a08b7ffb22 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj @@ -21,6 +21,7 @@ AzureConnection.idl + ConptyConnection.idl @@ -33,6 +34,7 @@ + AzureConnection.idl @@ -96,6 +98,5 @@ - - + \ No newline at end of file diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters index 13132925970..c8183b91ec6 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj.filters @@ -19,6 +19,7 @@ + @@ -26,6 +27,7 @@ + @@ -41,8 +43,6 @@ - - Resources\en-US - + \ No newline at end of file diff --git a/src/host/dll/ConsoleComGuids.h b/src/host/dll/ConsoleComGuids.h index 42ef9cd97b2..8db8fcdcae3 100644 --- a/src/host/dll/ConsoleComGuids.h +++ b/src/host/dll/ConsoleComGuids.h @@ -1,14 +1,18 @@ #pragma once #define __IID_IConsoleHandoff 2B607BC1-43EB-40C3-95AE-2856ADDB7F23 +#define __IID_ITerminalHandoff F89E4430-FF48-4DD7-A22C-182B546A8BA2 #if defined(WT_ReleaseBuild) #define __CLSID_IConsoleProxy 3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F #define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" + #define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" #elif defined(WT_PreviewBuild) #define __CLSID_IConsoleProxy 1833E661-CC81-4DD0-87C6-C2F74BD39EFA #define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" + #define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" #else #define __CLSID_IConsoleProxy DA2E620C-0B90-45D2-8362-A5B1006D9243 #define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" + #define __CLSID_CTerminalHandoff "E7B98685-0CC0-45D6-8F4C-B7C863C03DE2" #endif diff --git a/src/host/dll/Host.DLL.vcxproj b/src/host/dll/Host.DLL.vcxproj index d4ea3055279..2238d6c219b 100644 --- a/src/host/dll/Host.DLL.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -13,6 +13,8 @@ + + @@ -23,9 +25,11 @@ + + diff --git a/src/host/dll/Host.DLL.vcxproj.filters b/src/host/dll/Host.DLL.vcxproj.filters index d12ef1f9ac9..5683f7050b1 100644 --- a/src/host/dll/Host.DLL.vcxproj.filters +++ b/src/host/dll/Host.DLL.vcxproj.filters @@ -24,6 +24,12 @@ Source Files + + Source Files + + + Source Files + @@ -45,10 +51,16 @@ Header Files + + Header Files + Source Files + + Source Files + \ No newline at end of file diff --git a/src/host/dll/ITerminalHandoff.idl b/src/host/dll/ITerminalHandoff.idl new file mode 100644 index 00000000000..e99388726bc --- /dev/null +++ b/src/host/dll/ITerminalHandoff.idl @@ -0,0 +1,15 @@ +import "oaidl.idl"; +import "ocidl.idl"; + +#include "ConsoleComGuids.h" +cpp_quote("#include \"ConsoleComGuids.h\"") + +[ + object, + uuid(__IID_ITerminalHandoff) +] interface ITerminalHandoff : IUnknown +{ + HRESULT EstablishHandoff([in, system_handle(sh_file)] HANDLE in, + [in, system_handle(sh_file)] HANDLE out, + [in, system_handle(sh_file)] HANDLE signal); +}; diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 0ef07fd8d1b..cba38356d3f 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -8,7 +8,7 @@ wil::unique_event _exitEvent; // Routine Description: -// - Called back whne COM says there is nothing left for our server to do and we can tear down. +// - Called back when COM says there is nothing left for our server to do and we can tear down. void _releaseNotifier() noexcept { _exitEvent.SetEvent(); diff --git a/src/host/globals.h b/src/host/globals.h index 48bff80bef1..c162feb2324 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -71,7 +71,8 @@ class Globals bool handoffTarget = false; - std::optional handoffClsid; + std::optional handoffConsoleClsid; + std::optional handoffTerminalClsid; #ifdef UNIT_TESTING void EnableConptyModeForTests(std::unique_ptr vtRenderEngine); diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 586e2c6f5b9..0d4d749b016 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -24,7 +24,7 @@ #include "renderData.hpp" #include "../renderer/base/renderer.hpp" -#include "./lib/Handoff_h.h" +#include "..\host\dll\ITerminalHandoff_h.h" #pragma hdrstop @@ -51,9 +51,13 @@ try FontInfoBase::s_SetFontDefaultList(Globals.pFontDefaultList); IID delegationClsid; - if (SUCCEEDED(DelegationConfig::s_Get(delegationClsid))) + if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) { - Globals.handoffClsid = delegationClsid; + Globals.handoffConsoleClsid = delegationClsid; + } + if (SUCCEEDED(DelegationConfig::s_GetTerminal(delegationClsid))) + { + Globals.handoffTerminalClsid = delegationClsid; } // Removed allocation of scroll buffer here. @@ -304,38 +308,20 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, return S_OK; } -// Function Description: -// - Returns the path to either conhost.exe or the side-by-side OpenConsole, depending on whether this -// module is building with Windows. -// Return Value: -// - A pointer to permanent storage containing the path to the console host. -static wchar_t* _ConsoleHostPath() -{ - // Use the magic of magic statics to only calculate this once. - static wil::unique_process_heap_string consoleHostPath = []() { -#ifdef __INSIDE_WINDOWS - wil::unique_process_heap_string systemDirectory; - wil::GetSystemDirectoryW(systemDirectory); - return wil::str_concat_failfast(L"\\\\?\\", systemDirectory, L"\\conhost.exe"); -#else - // Use the STL only if we're not building in Windows. - std::filesystem::path modulePath{ "D:\\src\\terminal\\src\\cascadia\\CascadiaPackage\\bin\\x64\\Debug\\AppX\\wtd.exe" }; - //modulePath.replace_filename(L"OpenConsole.exe"); - auto modulePathAsString{ modulePath.wstring() }; - return wil::make_process_heap_string_nothrow(modulePathAsString.data(), modulePathAsString.size()); -#endif // __INSIDE_WINDOWS - }(); - return consoleHostPath.get(); -} - HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage) +try { auto& g = ServiceLocator::LocateGlobals(); g.handoffTarget = true; + if (!g.handoffTerminalClsid) + { + return E_NOT_SET; + } + wil::unique_handle signalPipeTheirSide; wil::unique_handle signalPipeOurSide; @@ -360,66 +346,14 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(outPipeTheirSide.addressof(), outPipeOurSide.addressof(), &sa, 0)); RETURN_IF_WIN32_BOOL_FALSE(SetHandleInformation(outPipeTheirSide.get(), HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)); - // GH4061: Ensure that the path to executable in the format is escaped so C:\Program.exe cannot collide with C:\Program Files - const wchar_t* pwszFormat = L"\"%s\" --pty %d"; - // This is plenty of space to hold the formatted string - wchar_t cmd[MAX_PATH]{}; - swprintf_s(cmd, - MAX_PATH, - pwszFormat, - _ConsoleHostPath(), - signalPipeTheirSide.get()); - - STARTUPINFOEXW siEx{ 0 }; - siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW); - siEx.StartupInfo.hStdInput = inPipeTheirSide.get(); - siEx.StartupInfo.hStdOutput = outPipeTheirSide.get(); - siEx.StartupInfo.hStdError = outPipeTheirSide.get(); - siEx.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - - // Only pass the handles we actually want the conhost to know about to it: - const size_t INHERITED_HANDLES_COUNT = 3; - HANDLE inheritedHandles[INHERITED_HANDLES_COUNT]; - inheritedHandles[0] = inPipeTheirSide.get(); - inheritedHandles[1] = outPipeTheirSide.get(); - inheritedHandles[2] = signalPipeTheirSide.get(); - - // Get the size of the attribute list. We need one attribute, the handle list. - SIZE_T listSize = 0; - InitializeProcThreadAttributeList(nullptr, 1, 0, &listSize); - - // I have to use a HeapAlloc here because kernelbase can't link new[] or delete[] - PPROC_THREAD_ATTRIBUTE_LIST attrList = static_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, listSize)); - RETURN_IF_NULL_ALLOC(attrList); - auto attrListDelete = wil::scope_exit([&]() noexcept { - HeapFree(GetProcessHeap(), 0, attrList); - }); - - siEx.lpAttributeList = attrList; - RETURN_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &listSize)); - // Set cleanup data for ProcThreadAttributeList when successful. - auto cleanupProcThreadAttribute = wil::scope_exit([&]() noexcept { - DeleteProcThreadAttributeList(siEx.lpAttributeList); - }); - RETURN_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(siEx.lpAttributeList, - 0, - PROC_THREAD_ATTRIBUTE_HANDLE_LIST, - inheritedHandles, - (INHERITED_HANDLES_COUNT * sizeof(HANDLE)), - nullptr, - nullptr)); - wil::unique_process_information pi; - // Call create process - RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(_ConsoleHostPath(), - cmd, - nullptr, - nullptr, - TRUE, - EXTENDED_STARTUPINFO_PRESENT, - nullptr, - nullptr, - &siEx.StartupInfo, - pi.addressof())); + auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + ::Microsoft::WRL::ComPtr handoff; + + RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); + + RETURN_IF_FAILED(handoff->EstablishHandoff(inPipeTheirSide.get(), + outPipeTheirSide.get(), + signalPipeTheirSide.get())); inPipeTheirSide.release(); outPipeTheirSide.release(); @@ -436,6 +370,7 @@ HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, return ConsoleCreateIoThread(Server, &args2, driverInputEvent, connectMessage); } +CATCH_RETURN() [[nodiscard]] HRESULT ConsoleCreateIoThreadLegacy(_In_ HANDLE Server, const ConsoleArguments* const args) { diff --git a/src/host/ut_host/ConsoleArgumentsTests.cpp b/src/host/ut_host/ConsoleArgumentsTests.cpp index 05fecd01141..65dc2fd9cfa 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/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 97c745a8bc6..2cbd570e183 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -9,7 +9,17 @@ #pragma hdrstop -[[nodiscard]] HRESULT DelegationConfig::s_Get(IID& iid) +[[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) +{ + return s_Get(L"DelegationConsole", iid); +} + +[[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) +{ + return s_Get(L"DelegationTerminal", iid); +} + +[[nodiscard]] HRESULT DelegationConfig::s_Get(PCWSTR value, IID& iid) { wil::unique_hkey currentUserKey; wil::unique_hkey consoleKey; @@ -21,7 +31,7 @@ DWORD bytesNeeded = 0; NTSTATUS result = RegistrySerialization::s_QueryValue(startupKey.get(), - L"DelegationConsole", + value, 0, REG_SZ, nullptr, @@ -37,7 +47,7 @@ DWORD bytesUsed = 0; RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_QueryValue(startupKey.get(), - L"DelegationConsole", + value, bytesNeeded, REG_SZ, reinterpret_cast(buffer.get()), diff --git a/src/propslib/DelegationConfig.hpp b/src/propslib/DelegationConfig.hpp index e4b7000c238..25cbcdaa797 100644 --- a/src/propslib/DelegationConfig.hpp +++ b/src/propslib/DelegationConfig.hpp @@ -18,5 +18,9 @@ Author(s): class DelegationConfig { public: - [[nodiscard]] static HRESULT s_Get(IID& iid); + [[nodiscard]] static HRESULT s_GetConsole(IID& iid); + [[nodiscard]] static HRESULT s_GetTerminal(IID& iid); + +private: + [[nodiscard]] static HRESULT s_Get(PCWSTR value, IID& iid); }; diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 8c793726931..58117fab192 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -161,14 +161,14 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API Globals& Globals = ServiceLocator::LocateGlobals(); // TODO: only the inside windows one should probably bother trying to delegate, the out of box one could probably assume it doesn't need to. - if (Globals.handoffClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) + if (Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { try { auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); ::Microsoft::WRL::ComPtr handoff; - THROW_IF_FAILED(CoCreateInstance(Globals.handoffClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); + THROW_IF_FAILED(CoCreateInstance(Globals.handoffConsoleClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); // Pack up just enough of the attach message for the other console to process it. // NOTE: It can and will pick up the size/title/etc parameters from the driver again. From 4f408183eeb8c7e8a85f20dd11284a5e85ba39a6 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 1 Sep 2020 16:35:55 -0700 Subject: [PATCH 16/80] Try manual registration. --- .../TerminalConnection/CTerminalHandoff.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 8e7bc18ebd1..44a31bc0e4e 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -4,6 +4,8 @@ static NewHandoff _pfnHandoff = nullptr; +static DWORD g_cTerminalHandoffRegistration = 0; + // Routine Description: // - Called back when COM says there is nothing left for our server to do and we can tear down. void _releaseNotifier() noexcept @@ -15,7 +17,13 @@ HRESULT CTerminalHandoff::StartListening(NewHandoff pfnHandoff) { RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); - RETURN_IF_FAILED(Module::Create(&_releaseNotifier).RegisterObjects()); + 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; @@ -26,7 +34,11 @@ HRESULT CTerminalHandoff::StopListening() { _pfnHandoff = nullptr; - RETURN_IF_FAILED(Module::Create(&_releaseNotifier).UnregisterObjects()); + if (g_cTerminalHandoffRegistration) + { + RETURN_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); + g_cTerminalHandoffRegistration = 0; + } CoUninitialize(); From b1c56b28e68b8d419c89c069e860c1a61000663e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 2 Sep 2020 14:23:06 -0700 Subject: [PATCH 17/80] reguid interface, mess around with terminal handoff to make it work... it finally works with the correct ndr version.... still need to manually patch that. also need to dump dummy call to interface. also fixed arg parser sort of. --- OpenConsole.sln | 3 ++ .../CascadiaPackage/Package-Dev.appxmanifest | 10 ++-- .../CascadiaPackage/Package-Pre.appxmanifest | 4 +- .../CascadiaPackage/Package.appxmanifest | 4 +- .../TerminalApp/AppCommandlineArgs.cpp | 18 +++++-- .../TerminalConnection/CTerminalHandoff.cpp | 12 ++++- .../TerminalConnection/CTerminalHandoff.h | 2 + .../TerminalConnection/ConptyConnection.cpp | 9 ++-- .../TerminalConnection/ConptyConnection.h | 7 +-- src/host/dll/ConsoleComGuids.h | 6 +-- src/host/dll/ITerminalHandoff.idl | 8 +-- src/host/srvinit.cpp | 25 +++++---- src/server/IoDispatchers.cpp | 51 ++++++++++--------- 13 files changed, 97 insertions(+), 62 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 9c85c208a80..83039fea8cf 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -105,6 +105,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 + {E437B604-3E98-4F40-A927-E173E818EA4B} = {E437B604-3E98-4F40-A927-E173E818EA4B} + 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 diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index bc279140644..80e880e0e26 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -93,9 +93,9 @@ - - - + + + @@ -103,8 +103,8 @@ - - + + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 8b34a0a6e5b..701ff3683da 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -96,7 +96,7 @@ - + @@ -104,7 +104,7 @@ - + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 5c641ecf21b..872fea9745b 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -96,7 +96,7 @@ - + @@ -104,7 +104,7 @@ - + diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 08f8cd846ca..7b064e9c984 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -176,12 +176,20 @@ void AppCommandlineArgs::_buildParser() // Started explicitly as a COM server for incoming PTY flags // /Embedding (we don't pick this, it's just how COM does it.) - auto comEmbeddingCallback = [this](int64_t /*count*/) { - auto embeddingAction = winrt::make_self(); - embeddingAction->Action(ShortcutAction::ToggleInboundPty); - _startupActions.push_back(*embeddingAction); + auto comEmbeddingCallback = [this](std::string param) { + if ("mbedding" == param) + { + auto embeddingAction = winrt::make_self(); + embeddingAction->Action(ShortcutAction::ToggleInboundPty); + _startupActions.push_back(*embeddingAction); + } + else + { + throw CLI::ParseError(fmt::format("Invalid call to COM server with {}", param), E_INVALIDARG); + } }; - _app.add_flag_function("--embedding", comEmbeddingCallback, RS_A(L"CmdEmbeddingDesc")); + + _app.add_option_function("-E", comEmbeddingCallback, RS_A(L"CmdEmbeddingDesc")); // Maximized and Fullscreen flags // -M,--maximized: Maximizes the window on launch diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 44a31bc0e4e..0125256fe93 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -15,8 +15,11 @@ void _releaseNotifier() noexcept HRESULT CTerminalHandoff::StartListening(NewHandoff pfnHandoff) { - RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); + // has to be because the rest of TerminalConnection is apartment threaded already + // also is it really necessary if the rest of it already is? + RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + // We could probably hold this in a static... auto classFactory = Make>(); RETURN_IF_NULL_ALLOC(classFactory); @@ -71,4 +74,11 @@ HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) // Call registered handler from when we started listening. return _pfnHandoff(in, out, signal); + + //return S_OK; +} + +HRESULT CTerminalHandoff::DoNothing() +{ + return S_FALSE; } diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 87ef57ed803..aeb37c6146b 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -13,6 +13,8 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) STDMETHODIMP EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal); + + STDMETHODIMP DoNothing(); #pragma endregion static HRESULT StartListening(NewHandoff pfnHandoff); diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index e48303f8cd3..94f10eebc6d 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -490,11 +490,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept try { - UNREFERENCED_PARAMETER(in); - UNREFERENCED_PARAMETER(out); - UNREFERENCED_PARAMETER(signal); - //_newConnectionHandlers(in, out, signal); - return S_FALSE; + auto conn = winrt::make((uint64_t)in, (uint64_t)out, (uint64_t)signal); + _newConnectionHandlers(conn); + + return S_OK; } CATCH_RETURN() diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 622fcddad97..bcbcc7cdf9d 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -19,6 +19,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { struct ConptyConnection : ConptyConnectionT, ConnectionStateHolder { + ConptyConnection(const uint64_t hSig, + const uint64_t hIn, + const uint64_t hOut); + ConptyConnection( const hstring& cmdline, const hstring& startingDirectory, @@ -44,9 +48,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler); private: - ConptyConnection(const uint64_t hSig, - const uint64_t hIn, - const uint64_t hOut); HRESULT _LaunchAttachedClient() noexcept; void _indicateExitWithStatus(unsigned int status) noexcept; diff --git a/src/host/dll/ConsoleComGuids.h b/src/host/dll/ConsoleComGuids.h index 8db8fcdcae3..589dc717270 100644 --- a/src/host/dll/ConsoleComGuids.h +++ b/src/host/dll/ConsoleComGuids.h @@ -1,7 +1,7 @@ #pragma once #define __IID_IConsoleHandoff 2B607BC1-43EB-40C3-95AE-2856ADDB7F23 -#define __IID_ITerminalHandoff F89E4430-FF48-4DD7-A22C-182B546A8BA2 +#define __IID_ITerminalHandoff FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74 #if defined(WT_ReleaseBuild) #define __CLSID_IConsoleProxy 3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F @@ -12,7 +12,7 @@ #define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" #define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" #else - #define __CLSID_IConsoleProxy DA2E620C-0B90-45D2-8362-A5B1006D9243 + #define __CLSID_IConsoleProxy DEC4804D-56D1-4F73-9FBE-6828E7C85C56 #define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" - #define __CLSID_CTerminalHandoff "E7B98685-0CC0-45D6-8F4C-B7C863C03DE2" + #define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" #endif diff --git a/src/host/dll/ITerminalHandoff.idl b/src/host/dll/ITerminalHandoff.idl index e99388726bc..ca60188e749 100644 --- a/src/host/dll/ITerminalHandoff.idl +++ b/src/host/dll/ITerminalHandoff.idl @@ -9,7 +9,9 @@ cpp_quote("#include \"ConsoleComGuids.h\"") uuid(__IID_ITerminalHandoff) ] interface ITerminalHandoff : IUnknown { - HRESULT EstablishHandoff([in, system_handle(sh_file)] HANDLE in, - [in, system_handle(sh_file)] HANDLE out, - [in, system_handle(sh_file)] HANDLE signal); + HRESULT DoNothing(); + + HRESULT EstablishHandoff([in, system_handle(sh_pipe)] HANDLE in, + [in, system_handle(sh_pipe)] HANDLE out, + [in, system_handle(sh_pipe)] HANDLE signal); }; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 0d4d749b016..6ba48c6eb4c 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -331,25 +331,30 @@ try 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 = FALSE; - sa.lpSecurityDescriptor = nullptr; + //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(), &sa, 0)); + 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(), &sa, 0)); + 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(), &sa, 0)); + 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)); - auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + auto coinit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); ::Microsoft::WRL::ComPtr handoff; - RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); + RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); + + handoff->AddRef(); + handoff->DoNothing(); + + /*handoff->EstablishHandoff((HANDLE)4, (HANDLE)8, (HANDLE)12);*/ RETURN_IF_FAILED(handoff->EstablishHandoff(inPipeTheirSide.get(), outPipeTheirSide.get(), diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 58117fab192..37ae586af89 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -18,6 +18,8 @@ #include "..\interactivity\inc\ServiceLocator.hpp" +#include "..\host\exe\CConsoleHandoff.h" + using namespace Microsoft::Console::Interactivity; // From ntstatus.h, which we cannot include without causing a bunch of other conflicts. So we just include the one code we need. @@ -161,32 +163,35 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API Globals& Globals = ServiceLocator::LocateGlobals(); // TODO: only the inside windows one should probably bother trying to delegate, the out of box one could probably assume it doesn't need to. - if (Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) + if (!Globals.launchArgs.IsHeadless() && Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { try { - auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); - ::Microsoft::WRL::ComPtr handoff; - - THROW_IF_FAILED(CoCreateInstance(Globals.handoffConsoleClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); - - // Pack up just enough of the attach message for the other console to process it. - // NOTE: It can and will pick up the size/title/etc parameters from the driver again. - CONSOLE_PORTABLE_ATTACH_MSG msg; - msg.IdHighPart = pReceiveMsg->Descriptor.Identifier.HighPart; - msg.IdLowPart = pReceiveMsg->Descriptor.Identifier.LowPart; - msg.Process = pReceiveMsg->Descriptor.Process; - msg.Object = pReceiveMsg->Descriptor.Object; - msg.Function = pReceiveMsg->Descriptor.Function; - msg.InputSize = pReceiveMsg->Descriptor.InputSize; - msg.OutputSize = pReceiveMsg->Descriptor.OutputSize; - - THROW_IF_FAILED(handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), - Globals.hInputEvent.get(), - Globals.launchArgs.GetVtInHandle(), - Globals.launchArgs.GetVtOutHandle(), - L"test", // TODO: this and the VT args aren't right yet. - &msg)); + //auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + //::Microsoft::WRL::ComPtr handoff; + + //THROW_IF_FAILED(CoCreateInstance(Globals.handoffConsoleClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); + + //// Pack up just enough of the attach message for the other console to process it. + //// NOTE: It can and will pick up the size/title/etc parameters from the driver again. + //CONSOLE_PORTABLE_ATTACH_MSG msg; + //msg.IdHighPart = pReceiveMsg->Descriptor.Identifier.HighPart; + //msg.IdLowPart = pReceiveMsg->Descriptor.Identifier.LowPart; + //msg.Process = pReceiveMsg->Descriptor.Process; + //msg.Object = pReceiveMsg->Descriptor.Object; + //msg.Function = pReceiveMsg->Descriptor.Function; + //msg.InputSize = pReceiveMsg->Descriptor.InputSize; + //msg.OutputSize = pReceiveMsg->Descriptor.OutputSize; + + //THROW_IF_FAILED(handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), + // Globals.hInputEvent.get(), + // Globals.launchArgs.GetVtInHandle(), + // Globals.launchArgs.GetVtOutHandle(), + // L"test", // TODO: this and the VT args aren't right yet. + // &msg)); + + ConsoleArguments args; + THROW_IF_FAILED(ConsoleEstablishHandoff(Globals.pDeviceComm->_Server.get(), &args, Globals.hInputEvent.get(), pReceiveMsg)); ExitThread(S_OK); } From 4286f61ef4748efa901d4f6119de98af3e50ebf2 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 2 Sep 2020 15:49:38 -0700 Subject: [PATCH 18/80] Okay this works. -Embedding if found skips other arg parsing. No new tabs are made for embedding... and it totally works. Except Terminal can't read from the pipes it was given. So gotta figure that one out. --- .../TerminalApp/AppCommandlineArgs.cpp | 19 ++++++++++++------- src/cascadia/TerminalApp/TerminalPage.cpp | 10 ++++++---- src/cascadia/TerminalApp/TerminalPage.h | 2 +- src/host/srvinit.cpp | 15 +++++---------- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 7b064e9c984..c19ec5e903d 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -183,13 +183,7 @@ void AppCommandlineArgs::_buildParser() embeddingAction->Action(ShortcutAction::ToggleInboundPty); _startupActions.push_back(*embeddingAction); } - else - { - throw CLI::ParseError(fmt::format("Invalid call to COM server with {}", param), E_INVALIDARG); - } }; - - _app.add_option_function("-E", comEmbeddingCallback, RS_A(L"CmdEmbeddingDesc")); // Maximized and Fullscreen flags // -M,--maximized: Maximizes the window on launch @@ -666,7 +660,7 @@ 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) + (_startupActions.front().Action() != ShortcutAction::NewTab && _startupActions.front().Action() != ShortcutAction::ToggleInboundPty)) { // Build the NewTab action from the values we've parsed on the commandline. auto newTabAction = winrt::make_self(); @@ -700,6 +694,17 @@ std::optional AppCommandlineArgs::GetLaunchMode( // - 0 if the commandline was successfully parsed int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { + for (auto& arg : args) + { + if (arg == L"-Embedding") + { + auto embeddingAction = winrt::make_self(); + embeddingAction->Action(ShortcutAction::ToggleInboundPty); + _startupActions.push_back(*embeddingAction); + return 0; + } + } + auto commands = ::TerminalApp::AppCommandlineArgs::BuildCommands(args); for (auto& cmdBlob : commands) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index b594ca2982f..479602b28a9 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -197,7 +197,7 @@ namespace winrt::TerminalApp::implementation // Hook up inbound PTY event handlers InboundPtyChanged({ this, &TerminalPage::_OnInboundPtyChanged }); - //Microsoft::Terminal::TerminalConnection::ConptyConnection::NewConnection(&TerminalPage::_OnNewConnection); + TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection }); //Event Bindings (Early) _newTabButton.Click([weakThis{ get_weak() }](auto&&, auto&&) { @@ -2517,9 +2517,11 @@ namespace winrt::TerminalApp::implementation } } - //void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection /*connection*/) - //{ - //} + void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection) + { + // TODO: this should probably use a more reasonable profile than nullptr. + _OpenNewTab(nullptr, connection); + } // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 47177c325a0..fab0922829f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -205,7 +205,7 @@ namespace winrt::TerminalApp::implementation void _UnZoomIfNeeded(); void _OnInboundPtyChanged(const IInspectable& sender, const IInspectable& eventArgs); - //void _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection); + void _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection); #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 6ba48c6eb4c..2f0a1cb11ca 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -331,11 +331,11 @@ try 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; + 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)); @@ -351,11 +351,6 @@ try RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); - handoff->AddRef(); - handoff->DoNothing(); - - /*handoff->EstablishHandoff((HANDLE)4, (HANDLE)8, (HANDLE)12);*/ - RETURN_IF_FAILED(handoff->EstablishHandoff(inPipeTheirSide.get(), outPipeTheirSide.get(), signalPipeTheirSide.get())); From 3ca748be4bcd49d73605d6a3b90990076c2067ee Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 2 Sep 2020 17:00:28 -0700 Subject: [PATCH 19/80] u wot m8. it works. --- .../TerminalConnection/ConptyConnection.cpp | 2 +- src/host/exe/CConsoleHandoff.cpp | 22 +++++++-- src/host/srvinit.cpp | 12 ++++- src/server/IoDispatchers.cpp | 49 ++++++++++--------- 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 94f10eebc6d..5edc160eeca 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -490,7 +490,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept try { - auto conn = winrt::make((uint64_t)in, (uint64_t)out, (uint64_t)signal); + auto conn = winrt::make((uint64_t)signal, (uint64_t)in, (uint64_t)out); _newConnectionHandlers(conn); return S_OK; diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index cba38356d3f..99905d59e99 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -14,6 +14,8 @@ void _releaseNotifier() noexcept _exitEvent.SetEvent(); } +DWORD g_cTerminalHandoffRegistration = 0; + // Routine Description: // - Performs registrations for our COM types and waits until COM tells us we're done being a server. // Return Value: @@ -23,13 +25,27 @@ try { _exitEvent.create(); - auto uninit = wil::CoInitializeEx(COINIT_MULTITHREADED); + + // has to be because the rest of TerminalConnection is apartment threaded already + // also is it really necessary if the rest of it already is? + RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); + + // We could probably hold this in a static... + auto classFactory = Make>(); + RETURN_IF_NULL_ALLOC(classFactory); + + ComPtr unk; + RETURN_IF_FAILED(classFactory.As(&unk)); + + RETURN_IF_FAILED(CoRegisterClassObject(__uuidof(CConsoleHandoff), unk.Get(), CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &g_cTerminalHandoffRegistration)); + + /* auto uninit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); auto& module = Module::Create(&_releaseNotifier); - RETURN_IF_FAILED(module.RegisterObjects()); + RETURN_IF_FAILED(module.RegisterObjects());*/ _exitEvent.wait(); - RETURN_IF_FAILED(module.UnregisterObjects()); + //RETURN_IF_FAILED(module.UnregisterObjects()); return S_OK; } diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 2f0a1cb11ca..11fda7164a6 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -50,6 +50,7 @@ try FontInfoBase::s_SetFontDefaultList(Globals.pFontDefaultList); + // TODO: This is looked up twice in the middle hop console. IID delegationClsid; if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) { @@ -317,6 +318,16 @@ try auto& g = ServiceLocator::LocateGlobals(); g.handoffTarget = true; + IID delegationClsid; + if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) + { + g.handoffConsoleClsid = delegationClsid; + } + if (SUCCEEDED(DelegationConfig::s_GetTerminal(delegationClsid))) + { + g.handoffTerminalClsid = delegationClsid; + } + if (!g.handoffTerminalClsid) { return E_NOT_SET; @@ -346,7 +357,6 @@ try 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)); - auto coinit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); ::Microsoft::WRL::ComPtr handoff; RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 37ae586af89..302dc47b3c5 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -167,31 +167,32 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API { try { - //auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); - //::Microsoft::WRL::ComPtr handoff; - - //THROW_IF_FAILED(CoCreateInstance(Globals.handoffConsoleClsid.value(), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&handoff))); - - //// Pack up just enough of the attach message for the other console to process it. - //// NOTE: It can and will pick up the size/title/etc parameters from the driver again. - //CONSOLE_PORTABLE_ATTACH_MSG msg; - //msg.IdHighPart = pReceiveMsg->Descriptor.Identifier.HighPart; - //msg.IdLowPart = pReceiveMsg->Descriptor.Identifier.LowPart; - //msg.Process = pReceiveMsg->Descriptor.Process; - //msg.Object = pReceiveMsg->Descriptor.Object; - //msg.Function = pReceiveMsg->Descriptor.Function; - //msg.InputSize = pReceiveMsg->Descriptor.InputSize; - //msg.OutputSize = pReceiveMsg->Descriptor.OutputSize; - - //THROW_IF_FAILED(handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), - // Globals.hInputEvent.get(), - // Globals.launchArgs.GetVtInHandle(), - // Globals.launchArgs.GetVtOutHandle(), - // L"test", // TODO: this and the VT args aren't right yet. - // &msg)); - - ConsoleArguments args; + auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + ::Microsoft::WRL::ComPtr handoff; + + THROW_IF_FAILED(CoCreateInstance(Globals.handoffConsoleClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); + + // Pack up just enough of the attach message for the other console to process it. + // NOTE: It can and will pick up the size/title/etc parameters from the driver again. + CONSOLE_PORTABLE_ATTACH_MSG msg; + msg.IdHighPart = pReceiveMsg->Descriptor.Identifier.HighPart; + msg.IdLowPart = pReceiveMsg->Descriptor.Identifier.LowPart; + msg.Process = pReceiveMsg->Descriptor.Process; + msg.Object = pReceiveMsg->Descriptor.Object; + msg.Function = pReceiveMsg->Descriptor.Function; + msg.InputSize = pReceiveMsg->Descriptor.InputSize; + msg.OutputSize = pReceiveMsg->Descriptor.OutputSize; + + THROW_IF_FAILED(handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), + Globals.hInputEvent.get(), + Globals.launchArgs.GetVtInHandle(), + Globals.launchArgs.GetVtOutHandle(), + L"test", // TODO: this and the VT args aren't right yet. + &msg)); + + /*ConsoleArguments args; THROW_IF_FAILED(ConsoleEstablishHandoff(Globals.pDeviceComm->_Server.get(), &args, Globals.hInputEvent.get(), pReceiveMsg)); + UnlockConsole();*/ ExitThread(S_OK); } From dceadd8b68a35ef40f64a652b3a7ac0acc884636 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 3 Sep 2020 11:40:14 -0700 Subject: [PATCH 20/80] Stuff this in from Dustin --- src/host/exe/CConsoleHandoff.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 99905d59e99..dfdb0660d98 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -16,6 +16,30 @@ void _releaseNotifier() noexcept DWORD g_cTerminalHandoffRegistration = 0; +template +class DefaultOutOfProcModuleWithRegistrationFlag; + +template> +class OutOfProcModuleWithRegistrationFlag : public Microsoft::WRL::Module +{ +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> +{ +}; + +int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) +{ + OutOfProcModuleWithRegistrationFlag::Create(); +} + // Routine Description: // - Performs registrations for our COM types and waits until COM tells us we're done being a server. // Return Value: From 7f54db2d5d41e895f98573850b3741fd2ddc6e05 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 10 Sep 2020 10:49:25 -0700 Subject: [PATCH 21/80] Fix vtable problem for 0xa0000 ndr version by specifying NT target version explicitly. --- src/common.build.pre.props | 3 ++ src/host/dll/Host.DLL.vcxproj | 2 +- src/host/exe/CConsoleHandoff.cpp | 46 ++++++++++++------------- src/host/srvinit.cpp | 59 ++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 24 deletions(-) diff --git a/src/common.build.pre.props b/src/common.build.pre.props index fc209613749..d89221c3dc4 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -70,6 +70,9 @@ + + /target NT100 %(AdditionalOptions) + Use Level4 diff --git a/src/host/dll/Host.DLL.vcxproj b/src/host/dll/Host.DLL.vcxproj index 2238d6c219b..cb9d4ff5647 100644 --- a/src/host/dll/Host.DLL.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -50,4 +50,4 @@ - \ No newline at end of file + diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index dfdb0660d98..18ee1b94b84 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -16,29 +16,29 @@ void _releaseNotifier() noexcept DWORD g_cTerminalHandoffRegistration = 0; -template -class DefaultOutOfProcModuleWithRegistrationFlag; - -template> -class OutOfProcModuleWithRegistrationFlag : public Microsoft::WRL::Module -{ -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> -{ -}; - -int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) -{ - OutOfProcModuleWithRegistrationFlag::Create(); -} +//template +//class DefaultOutOfProcModuleWithRegistrationFlag; +// +//template> +//class OutOfProcModuleWithRegistrationFlag : public Microsoft::WRL::Module +//{ +//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> +//{ +//}; +// +//int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) +//{ +// OutOfProcModuleWithRegistrationFlag::Create(); +//} // Routine Description: // - Performs registrations for our COM types and waits until COM tells us we're done being a server. diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 11fda7164a6..5f1b00f4420 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -26,6 +26,12 @@ #include "..\host\dll\ITerminalHandoff_h.h" +#include +#include +#include +#include +#include + #pragma hdrstop using namespace Microsoft::Console::Interactivity; @@ -34,6 +40,57 @@ using namespace Microsoft::Console::Render; const UINT CONSOLE_EVENT_FAILURE_ID = 21790; const UINT CONSOLE_LPC_PORT_FAILURE_ID = 21791; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::AppExtensions; + +HRESULT LookupCatalog() +{ + auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + + ComPtr catalogStatics; + RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_AppExtensions_AppExtensionCatalog).Get(), &catalogStatics)); + + ComPtr catalog; + RETURN_IF_FAILED(catalogStatics->Open(HStringReference(L"com.microsoft.windows.console.host").Get(), &catalog)); + + ComPtr*>> findOperation; + RETURN_IF_FAILED(catalog->FindAllAsync(&findOperation)); + + ComPtr> extensionList; + RETURN_IF_FAILED(wil::wait_for_completion_nothrow(findOperation.Get(), &extensionList)); + + UINT extensionCount; + RETURN_IF_FAILED(extensionList->get_Size(&extensionCount)); + for (UINT index = 0; index < extensionCount; index++) + { + ComPtr extension; + RETURN_IF_FAILED(extensionList->GetAt(index, &extension)); + + ComPtr extensionPackage; + RETURN_IF_FAILED(extension->get_Package(&extensionPackage)); + + ComPtr extensionPackageId; + RETURN_IF_FAILED(extensionPackage->get_Id(&extensionPackageId)); + + HString publisherId; + RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf())); + + // PackageId.Name + HString name; + RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf())); + + // PackageId.Version + PackageVersion version; + RETURN_IF_FAILED(extensionPackageId->get_Version(&version)); + } + + return S_OK; +} + [[nodiscard]] HRESULT ConsoleServerInitialization(_In_ HANDLE Server, const ConsoleArguments* const args) try { @@ -50,6 +107,8 @@ try FontInfoBase::s_SetFontDefaultList(Globals.pFontDefaultList); + //LookupCatalog(); + // TODO: This is looked up twice in the middle hop console. IID delegationClsid; if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) From a510cd588f91c1010fd9167e52d5144505d54021 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 10 Sep 2020 15:08:17 -0700 Subject: [PATCH 22/80] Some cleanup of things. --- .../CascadiaPackage/Package-Dev.appxmanifest | 2 +- .../CascadiaPackage/Package-Pre.appxmanifest | 2 +- .../CascadiaPackage/Package.appxmanifest | 2 +- .../TerminalApp/AppCommandlineArgs.cpp | 11 --- src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 - src/cascadia/TerminalApp/TerminalPage.h | 1 - .../TerminalConnection/CTerminalHandoff.cpp | 43 +++++------ .../TerminalConnection/CTerminalHandoff.h | 5 +- .../TerminalConnection/ConptyConnection.cpp | 4 +- src/host/dll/Host.DLL.vcxproj | 8 +-- src/host/dll/Host.DLL.vcxproj.filters | 10 +-- src/host/dll/ITerminalHandoff.idl | 2 - ...penConsoleDll.def => OpenConsoleProxy.def} | 0 src/host/exe/CConsoleHandoff.cpp | 71 ++++++++----------- src/host/srvinit.h | 10 ++- src/server/IoDispatchers.cpp | 9 +-- 16 files changed, 73 insertions(+), 109 deletions(-) rename src/host/dll/{OpenConsoleDll.def => OpenConsoleProxy.def} (100%) diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index 80e880e0e26..cd822e9ac06 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -93,7 +93,7 @@ - + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 701ff3683da..2a8ee189715 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -94,7 +94,7 @@ - + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 872fea9745b..904bd06cf4b 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -94,7 +94,7 @@ - + diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index c19ec5e903d..28978027ddb 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -174,17 +174,6 @@ void AppCommandlineArgs::_buildParser() }; _app.add_flag_function("-v,--version", versionCallback, RS_A(L"CmdVersionDesc")); - // Started explicitly as a COM server for incoming PTY flags - // /Embedding (we don't pick this, it's just how COM does it.) - auto comEmbeddingCallback = [this](std::string param) { - if ("mbedding" == param) - { - auto embeddingAction = winrt::make_self(); - embeddingAction->Action(ShortcutAction::ToggleInboundPty); - _startupActions.push_back(*embeddingAction); - } - }; - // Maximized and Fullscreen flags // -M,--maximized: Maximizes the window on launch // -F,--fullscreen: Fullscreens the window on launch diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 7b571788c15..a0d87ffc6b8 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -6,8 +6,6 @@ #include "Commandline.h" -#include - #ifdef UNIT_TESTING // fwdecl unittest classes namespace TerminalAppLocalTests diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index fab0922829f..a86f8c0b346 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -9,7 +9,6 @@ #include "Profile.h" #include -//#include #include "AppCommandlineArgs.h" diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 0125256fe93..04f64d822d9 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -2,25 +2,25 @@ #include "CTerminalHandoff.h" +// The callback function when a connection is received static NewHandoff _pfnHandoff = nullptr; - +// The registration ID of the class object for deregistration later static DWORD g_cTerminalHandoffRegistration = 0; // Routine Description: -// - Called back when COM says there is nothing left for our server to do and we can tear down. -void _releaseNotifier() noexcept -{ - CTerminalHandoff::StopListening(); -} - -HRESULT CTerminalHandoff::StartListening(NewHandoff pfnHandoff) +// - 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(NewHandoff pfnHandoff) { - // has to be because the rest of TerminalConnection is apartment threaded already - // also is it really necessary if the rest of it already is? - RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)); + RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); // We could probably hold this in a static... auto classFactory = Make>(); + RETURN_IF_NULL_ALLOC(classFactory); ComPtr unk; @@ -33,8 +33,17 @@ HRESULT CTerminalHandoff::StartListening(NewHandoff pfnHandoff) return S_OK; } -HRESULT CTerminalHandoff::StopListening() +// Routine Description: +// - Stops listening for TerminalHandoff requests by deregistering +// our class and interface with COM +// Arguments: +// - +// Return Value: +// - S_OK, E_NOT_VALID_STATE (stop called when not started), or relevant COM deregistration error +HRESULT CTerminalHandoff::s_StopListening() { + RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff == nullptr); + _pfnHandoff = nullptr; if (g_cTerminalHandoffRegistration) @@ -43,8 +52,6 @@ HRESULT CTerminalHandoff::StopListening() g_cTerminalHandoffRegistration = 0; } - CoUninitialize(); - return S_OK; } @@ -58,7 +65,7 @@ HRESULT CTerminalHandoff::StopListening() // - S_OK or Win32 error from `::DuplicateHandle` HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) { - RETURN_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &out, 0, FALSE, DUPLICATE_SAME_ACCESS)); + RETURN_IF_WIN32_BOOL_FALSE(::DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &out, 0, FALSE, DUPLICATE_SAME_ACCESS)); return S_OK; } @@ -74,11 +81,5 @@ HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) // Call registered handler from when we started listening. return _pfnHandoff(in, out, signal); - - //return S_OK; } -HRESULT CTerminalHandoff::DoNothing() -{ - return S_FALSE; -} diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index aeb37c6146b..4ee07fec621 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -14,11 +14,10 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) HANDLE out, HANDLE signal); - STDMETHODIMP DoNothing(); #pragma endregion - static HRESULT StartListening(NewHandoff pfnHandoff); - static HRESULT StopListening(); + static HRESULT s_StartListening(NewHandoff pfnHandoff); + static HRESULT s_StopListening(); }; CoCreatableClass(CTerminalHandoff); diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 5edc160eeca..8f3287026ad 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -499,11 +499,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation void ConptyConnection::StartInboundListener() { - THROW_IF_FAILED(CTerminalHandoff::StartListening(&ConptyConnection::NewHandoff)); + THROW_IF_FAILED(CTerminalHandoff::s_StartListening(&ConptyConnection::NewHandoff)); } void ConptyConnection::StopInboundListener() { - THROW_IF_FAILED(CTerminalHandoff::StopListening()); + THROW_IF_FAILED(CTerminalHandoff::s_StopListening()); } } diff --git a/src/host/dll/Host.DLL.vcxproj b/src/host/dll/Host.DLL.vcxproj index cb9d4ff5647..7595becf574 100644 --- a/src/host/dll/Host.DLL.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -4,8 +4,8 @@ {E437B604-3E98-4F40-A927-E173E818EA4B} Win32Proj host - Host.DLL - OpenConsoleDll + Host.ProxyDLL + OpenConsoleProxy DynamicLibrary @@ -20,7 +20,7 @@ - + @@ -43,7 +43,7 @@ NotUsing - OpenConsoleDll.def + OpenConsoleProxy.def true type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' diff --git a/src/host/dll/Host.DLL.vcxproj.filters b/src/host/dll/Host.DLL.vcxproj.filters index 5683f7050b1..10e369f752f 100644 --- a/src/host/dll/Host.DLL.vcxproj.filters +++ b/src/host/dll/Host.DLL.vcxproj.filters @@ -39,11 +39,6 @@ - - - Source Files - - Header Files @@ -63,4 +58,9 @@ Source Files + + + Source Files + + \ No newline at end of file diff --git a/src/host/dll/ITerminalHandoff.idl b/src/host/dll/ITerminalHandoff.idl index ca60188e749..68070af9f36 100644 --- a/src/host/dll/ITerminalHandoff.idl +++ b/src/host/dll/ITerminalHandoff.idl @@ -9,8 +9,6 @@ cpp_quote("#include \"ConsoleComGuids.h\"") uuid(__IID_ITerminalHandoff) ] interface ITerminalHandoff : IUnknown { - HRESULT DoNothing(); - HRESULT EstablishHandoff([in, system_handle(sh_pipe)] HANDLE in, [in, system_handle(sh_pipe)] HANDLE out, [in, system_handle(sh_pipe)] HANDLE signal); diff --git a/src/host/dll/OpenConsoleDll.def b/src/host/dll/OpenConsoleProxy.def similarity index 100% rename from src/host/dll/OpenConsoleDll.def rename to src/host/dll/OpenConsoleProxy.def diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 18ee1b94b84..233c37dbf47 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -4,6 +4,31 @@ #include "srvinit.h" +// 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 +{ +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 _exitEvent; @@ -14,32 +39,6 @@ void _releaseNotifier() noexcept _exitEvent.SetEvent(); } -DWORD g_cTerminalHandoffRegistration = 0; - -//template -//class DefaultOutOfProcModuleWithRegistrationFlag; -// -//template> -//class OutOfProcModuleWithRegistrationFlag : public Microsoft::WRL::Module -//{ -//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> -//{ -//}; -// -//int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) -//{ -// OutOfProcModuleWithRegistrationFlag::Create(); -//} - // Routine Description: // - Performs registrations for our COM types and waits until COM tells us we're done being a server. // Return Value: @@ -49,27 +48,13 @@ try { _exitEvent.create(); - - // has to be because the rest of TerminalConnection is apartment threaded already - // also is it really necessary if the rest of it already is? RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); - // We could probably hold this in a static... - auto classFactory = Make>(); - RETURN_IF_NULL_ALLOC(classFactory); - - ComPtr unk; - RETURN_IF_FAILED(classFactory.As(&unk)); - - RETURN_IF_FAILED(CoRegisterClassObject(__uuidof(CConsoleHandoff), unk.Get(), CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &g_cTerminalHandoffRegistration)); - - /* auto uninit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); - auto& module = Module::Create(&_releaseNotifier); - RETURN_IF_FAILED(module.RegisterObjects());*/ + auto& module = OutOfProcModuleWithRegistrationFlag::Create(&_releaseNotifier); + RETURN_IF_FAILED(module.RegisterObjects()); _exitEvent.wait(); - - //RETURN_IF_FAILED(module.UnregisterObjects()); + RETURN_IF_FAILED(module.UnregisterObjects()); return S_OK; } diff --git a/src/host/srvinit.h b/src/host/srvinit.h index 8d8e9cc53ac..5eae88c2192 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -28,11 +28,9 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, [[nodiscard]] bool ConsoleConnectionDeservesVisibleWindow(PCONSOLE_API_CONNECTINFO p); -extern "C" __declspec(dllexport) HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... - HANDLE driverInputEvent, - PCONSOLE_API_MSG connectMessage); - - +HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + const ConsoleArguments* const args, + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage); void ConsoleCheckDebug(); diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 302dc47b3c5..4f02f696555 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -18,8 +18,6 @@ #include "..\interactivity\inc\ServiceLocator.hpp" -#include "..\host\exe\CConsoleHandoff.h" - using namespace Microsoft::Console::Interactivity; // From ntstatus.h, which we cannot include without causing a bunch of other conflicts. So we just include the one code we need. @@ -187,12 +185,11 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API Globals.hInputEvent.get(), Globals.launchArgs.GetVtInHandle(), Globals.launchArgs.GetVtOutHandle(), - L"test", // TODO: this and the VT args aren't right yet. + Globals.launchArgs.GetOriginalCommandLine().data(), &msg)); - /*ConsoleArguments args; - THROW_IF_FAILED(ConsoleEstablishHandoff(Globals.pDeviceComm->_Server.get(), &args, Globals.hInputEvent.get(), pReceiveMsg)); - UnlockConsole();*/ + // TODO: anymore cleanup of stuff we're holding onto like handles? + UnlockConsole(); ExitThread(S_OK); } From 38eaeea6354c5e0d833a57dccb35df8fc982722f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 11 Sep 2020 14:48:52 -0700 Subject: [PATCH 23/80] Add propslib ways of querying and setting the default one. Fix up the out of proc com server handling a bit for the exe server delegation conhost. --- .../CascadiaPackage/Package-Dev.appxmanifest | 4 +- .../CascadiaPackage/Package-Pre.appxmanifest | 4 +- .../CascadiaPackage/Package.appxmanifest | 4 +- src/host/exe/CConsoleHandoff.cpp | 56 ------ src/host/exe/CConsoleHandoff.h | 2 - src/host/exe/exemain.cpp | 70 ++++++- src/host/srvinit.cpp | 60 +----- src/propslib/DelegationConfig.cpp | 181 +++++++++++++++++- src/propslib/DelegationConfig.hpp | 28 ++- src/server/IoDispatchers.cpp | 19 +- 10 files changed, 292 insertions(+), 136 deletions(-) diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index cd822e9ac06..11afc37d62f 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -76,7 +76,7 @@ Description="Console host built from microsoft/terminal open source repository" PublicFolder="Public"> - 1F9F2BF5-5BC3-4F17-B0E6-912413F1F451 + {1F9F2BF5-5BC3-4F17-B0E6-912413F1F451} @@ -87,7 +87,7 @@ Description="Terminal host built from microsoft/terminal open source repository" PublicFolder="Public"> - E7B98685-0CC0-45D6-8F4C-B7C863C03DE2 + {E7B98685-0CC0-45D6-8F4C-B7C863C03DE2} diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 2a8ee189715..77dfdd88f66 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -77,7 +77,7 @@ Description="Console host built from microsoft/terminal open source repository" PublicFolder="Public"> - 06EC847C-C0A5-46B8-92CB-7C92F6E35CD5 + {06EC847C-C0A5-46B8-92CB-7C92F6E35CD5} @@ -88,7 +88,7 @@ Description="Terminal host built from microsoft/terminal open source repository" PublicFolder="Public"> - 86633F1F-6454-40EC-89CE-DA4EBA977EE2 + {86633F1F-6454-40EC-89CE-DA4EBA977EE2} diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 904bd06cf4b..cdddef835fe 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -77,7 +77,7 @@ Description="Console host built from microsoft/terminal open source repository" PublicFolder="Public"> - 2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69 + {2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69} @@ -88,7 +88,7 @@ Description="Terminal host built from microsoft/terminal open source repository" PublicFolder="Public"> - E12CFF52-A866-4C77-9A90-F570A7AA2C6B + {E12CFF52-A866-4C77-9A90-F570A7AA2C6B} diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 233c37dbf47..2bbb10031f5 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -4,62 +4,6 @@ #include "srvinit.h" -// 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 -{ -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 _exitEvent; - -// Routine Description: -// - Called back when COM says there is nothing left for our server to do and we can tear down. -void _releaseNotifier() noexcept -{ - _exitEvent.SetEvent(); -} - -// Routine Description: -// - Performs registrations for our COM types and waits until COM tells us we're done being a server. -// Return Value: -// - S_OK or a suitable COM/RPC error from registration or ongoing execution. -HRESULT RunAsComServer() noexcept -try -{ - _exitEvent.create(); - - RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)); - - auto& module = OutOfProcModuleWithRegistrationFlag::Create(&_releaseNotifier); - - RETURN_IF_FAILED(module.RegisterObjects()); - _exitEvent.wait(); - RETURN_IF_FAILED(module.UnregisterObjects()); - - return S_OK; -} -CATCH_RETURN() - // Routine Description: // - Helper to duplicate a handle to ourselves so we can keep holding onto it // after the caller frees the original one. diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h index 8453aa187b6..afaf00c78d0 100644 --- a/src/host/exe/CConsoleHandoff.h +++ b/src/host/exe/CConsoleHandoff.h @@ -18,6 +18,4 @@ struct __declspec(uuid(__CLSID_CConsoleHandoff)) #pragma endregion }; -HRESULT RunAsComServer() noexcept; - CoCreatableClass(CConsoleHandoff); diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index e5f021fe450..8029da75f5e 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -17,6 +17,37 @@ TRACELOGGING_DEFINE_PROVIDER( (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. @@ -143,6 +174,13 @@ static bool ShouldUseLegacyConhost(const ConsoleArguments& args) return hr; } +// Routine Description: +// - Called back when COM says there is nothing left for our server to do and we can tear down. +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 @@ -164,6 +202,14 @@ int CALLBACK wWinMain( 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(); + auto& module = OutOfProcModuleWithRegistrationFlag::Create(&_releaseNotifier); + + // Register Trace provider by GUID TraceLoggingRegister(g_ConhostLauncherProvider); @@ -178,7 +224,29 @@ int CALLBACK wWinMain( { if (args.ShouldRunAsComServer()) { - hr = RunAsComServer(); + 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 { diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 5f1b00f4420..096b4a5673f 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -26,12 +26,6 @@ #include "..\host\dll\ITerminalHandoff_h.h" -#include -#include -#include -#include -#include - #pragma hdrstop using namespace Microsoft::Console::Interactivity; @@ -40,57 +34,6 @@ using namespace Microsoft::Console::Render; const UINT CONSOLE_EVENT_FAILURE_ID = 21790; const UINT CONSOLE_LPC_PORT_FAILURE_ID = 21791; -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Foundation::Collections; -using namespace ABI::Windows::ApplicationModel; -using namespace ABI::Windows::ApplicationModel::AppExtensions; - -HRESULT LookupCatalog() -{ - auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); - - ComPtr catalogStatics; - RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_AppExtensions_AppExtensionCatalog).Get(), &catalogStatics)); - - ComPtr catalog; - RETURN_IF_FAILED(catalogStatics->Open(HStringReference(L"com.microsoft.windows.console.host").Get(), &catalog)); - - ComPtr*>> findOperation; - RETURN_IF_FAILED(catalog->FindAllAsync(&findOperation)); - - ComPtr> extensionList; - RETURN_IF_FAILED(wil::wait_for_completion_nothrow(findOperation.Get(), &extensionList)); - - UINT extensionCount; - RETURN_IF_FAILED(extensionList->get_Size(&extensionCount)); - for (UINT index = 0; index < extensionCount; index++) - { - ComPtr extension; - RETURN_IF_FAILED(extensionList->GetAt(index, &extension)); - - ComPtr extensionPackage; - RETURN_IF_FAILED(extension->get_Package(&extensionPackage)); - - ComPtr extensionPackageId; - RETURN_IF_FAILED(extensionPackage->get_Id(&extensionPackageId)); - - HString publisherId; - RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf())); - - // PackageId.Name - HString name; - RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf())); - - // PackageId.Version - PackageVersion version; - RETURN_IF_FAILED(extensionPackageId->get_Version(&version)); - } - - return S_OK; -} - [[nodiscard]] HRESULT ConsoleServerInitialization(_In_ HANDLE Server, const ConsoleArguments* const args) try { @@ -107,7 +50,8 @@ try FontInfoBase::s_SetFontDefaultList(Globals.pFontDefaultList); - //LookupCatalog(); + std::vector consoles; + RETURN_IF_FAILED(DelegationConfig::s_GetAvailableConsoles(consoles)); // TODO: This is looked up twice in the middle hop console. IID delegationClsid; diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 2cbd570e183..1e99b63913b 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -7,19 +7,170 @@ #include "RegistrySerialization.hpp" +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::ApplicationModel; +using namespace ABI::Windows::ApplicationModel::AppExtensions; + #pragma hdrstop -[[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) +#define DELEGATION_CONSOLE_KEY_NAME L"DelegationConsole" +#define DELEGATION_TERMINAL_KEY_NAME L"DelegationTerminal" + +#define DELEGATION_CONSOLE_EXTENSION_NAME L"com.microsoft.windows.console.host" +#define DELEGATION_TERMINAL_EXTENSION_NAME L"com.microsoft.windows.terminal.host" + + +template::value>::type* = nullptr> +HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept { - return s_Get(L"DelegationConsole", iid); + vec.clear(); + + auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + + ComPtr catalogStatics; + RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_AppExtensions_AppExtensionCatalog).Get(), &catalogStatics)); + + ComPtr catalog; + RETURN_IF_FAILED(catalogStatics->Open(HStringReference(extensionName).Get(), &catalog)); + + ComPtr*>> findOperation; + RETURN_IF_FAILED(catalog->FindAllAsync(&findOperation)); + + ComPtr> extensionList; + RETURN_IF_FAILED(wil::wait_for_completion_nothrow(findOperation.Get(), &extensionList)); + + UINT extensionCount; + RETURN_IF_FAILED(extensionList->get_Size(&extensionCount)); + for (UINT index = 0; index < extensionCount; index++) + { + T extensionMetadata; + + ComPtr extension; + RETURN_IF_FAILED(extensionList->GetAt(index, &extension)); + + ComPtr extensionPackage; + RETURN_IF_FAILED(extension->get_Package(&extensionPackage)); + + ComPtr extensionPackageId; + RETURN_IF_FAILED(extensionPackage->get_Id(&extensionPackageId)); + + HString publisherId; + RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf())); + + // PackageId.Name + HString name; + RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf())); + + extensionMetadata.name = std::wstring{ name.GetRawBuffer(nullptr) }; + + // PackageId.Version + HString publisher; + RETURN_IF_FAILED(extensionPackageId->get_Publisher(publisher.GetAddressOf())); + + extensionMetadata.author = std::wstring{ publisher.GetRawBuffer(nullptr) }; + + // Fetch the custom properties XML out of the extension information + ComPtr> propertiesOperation; + RETURN_IF_FAILED(extension->GetExtensionPropertiesAsync(&propertiesOperation)); + + // Wait for async to complete and return the property set. + ComPtr properties; + RETURN_IF_FAILED(wil::wait_for_completion_nothrow(propertiesOperation.Get(), &properties)); + + // We can't do anything on a set, but it must also be convertible to this type of map per the Windows.Foundation specs for this + ComPtr> map; + RETURN_IF_FAILED(properties.As(&map)); + + // Looking it up is going to get us an inspectable + ComPtr inspectable; + RETURN_IF_FAILED(map->Lookup(HStringReference(L"Clsid").Get(), &inspectable)); + + // Unfortunately that inspectable is another set because we're dealing with XML data payload that we put in the manifest. + ComPtr anotherSet; + RETURN_IF_FAILED(inspectable.As(&anotherSet)); + + // And we can't look at sets directly, so move it to map. + ComPtr> anotherMap; + RETURN_IF_FAILED(anotherSet.As(&anotherMap)); + + // Use the magic value of #text to get the body between the XML tags. And of course it's an obtuse Inspectable again. + ComPtr anotherInspectable; + RETURN_IF_FAILED(anotherMap->Lookup(HStringReference(L"#text").Get(), &anotherInspectable)); + + // But this time that Inspectable is an IPropertyValue, which is a PROPVARIANT in a trenchcoat. + ComPtr propValue; + RETURN_IF_FAILED(anotherInspectable.As(&propValue)); + + // Check the type of the variant + PropertyType propType; + RETURN_IF_FAILED(propValue->get_Type(&propType)); + + // If we're not a string, bail because I don't know what's going on. + if (propType != PropertyType::PropertyType_String) + { + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + // Get that string out. + HString value; + RETURN_IF_FAILED(propValue->GetString(value.GetAddressOf())); + + // Holy cow. It should be a GUID. Try to parse it. + IID iid; + RETURN_IF_FAILED(IIDFromString(value.GetRawBuffer(nullptr), &iid)); + + extensionMetadata.clsid = iid; + + vec.push_back(extensionMetadata); + } + + return S_OK; +} + +[[nodiscard]] HRESULT DelegationConfig::s_GetAvailableConsoles(std::vector& consoles) noexcept +try +{ + return _lookupCatalog(DELEGATION_CONSOLE_EXTENSION_NAME, consoles); +} +CATCH_RETURN() + +[[nodiscard]] HRESULT DelegationConfig::s_GetAvailableTerminals(std::vector& terminals) noexcept +try +{ + return _lookupCatalog(DELEGATION_TERMINAL_EXTENSION_NAME, terminals); +} +CATCH_RETURN() + +[[nodiscard]] HRESULT DelegationConfig::s_SetConsole(const DelegationConsole& console) noexcept +{ + return s_Set(DELEGATION_CONSOLE_KEY_NAME, console.clsid); +} + +[[nodiscard]] HRESULT DelegationConfig::s_SetTerminal(const DelegationTerminal& terminal) noexcept +{ + return s_Set(DELEGATION_TERMINAL_KEY_NAME, terminal.clsid); +} + +[[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) noexcept +{ + return s_Get(DELEGATION_CONSOLE_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) +[[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) noexcept { - return s_Get(L"DelegationTerminal", iid); + return s_Get(DELEGATION_TERMINAL_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_Get(PCWSTR value, IID& iid) +[[nodiscard]] HRESULT DelegationConfig::s_Get(PCWSTR value, IID& iid) noexcept { wil::unique_hkey currentUserKey; wil::unique_hkey consoleKey; @@ -57,3 +208,23 @@ return S_OK; } + +[[nodiscard]] HRESULT DelegationConfig::s_Set(PCWSTR value, const CLSID clsid) noexcept +try +{ + wil::unique_hkey currentUserKey; + wil::unique_hkey consoleKey; + + RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_OpenConsoleKey(¤tUserKey, &consoleKey)); + + wil::unique_hkey startupKey; + RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_OpenKey(consoleKey.get(), L"%%Startup", &startupKey)); + + wil::unique_cotaskmem_string str; + RETURN_IF_FAILED(StringFromCLSID(clsid, &str)); + + RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(startupKey.get(), value, REG_SZ, reinterpret_cast(str.get()), gsl::narrow(wcslen(str.get() + 1) * sizeof(wchar_t)))); + + return S_OK; +} +CATCH_RETURN() diff --git a/src/propslib/DelegationConfig.hpp b/src/propslib/DelegationConfig.hpp index 25cbcdaa797..23c81da8aec 100644 --- a/src/propslib/DelegationConfig.hpp +++ b/src/propslib/DelegationConfig.hpp @@ -18,9 +18,31 @@ Author(s): class DelegationConfig { public: - [[nodiscard]] static HRESULT s_GetConsole(IID& iid); - [[nodiscard]] static HRESULT s_GetTerminal(IID& iid); + struct DelegationBase + { + CLSID clsid; + std::wstring name; + std::wstring author; + }; + + struct DelegationConsole : public DelegationBase + { + }; + + struct DelegationTerminal : public DelegationBase + { + }; + + [[nodiscard]] static HRESULT s_GetAvailableConsoles(std::vector& consoles) noexcept; + [[nodiscard]] static HRESULT s_GetAvailableTerminals(std::vector& terminals) noexcept; + + [[nodiscard]] static HRESULT s_SetConsole(const DelegationConsole& console) noexcept; + [[nodiscard]] static HRESULT s_SetTerminal(const DelegationTerminal& terminal) noexcept; + + [[nodiscard]] static HRESULT s_GetConsole(IID& iid) noexcept; + [[nodiscard]] static HRESULT s_GetTerminal(IID& iid) noexcept; private: - [[nodiscard]] static HRESULT s_Get(PCWSTR value, IID& iid); + [[nodiscard]] static HRESULT s_Get(PCWSTR value, IID& iid) noexcept; + [[nodiscard]] static HRESULT s_Set(PCWSTR value, const CLSID clsid) noexcept; }; diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 4f02f696555..d53f5e93608 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -13,12 +13,14 @@ #include "..\host\handle.h" #include "..\host\srvinit.h" #include "..\host\telemetry.hpp" +#include "..\types\inc\utils.hpp" #include "..\host\dll\IConsoleHandoff_h.h" #include "..\interactivity\inc\ServiceLocator.hpp" using namespace Microsoft::Console::Interactivity; +using namespace Microsoft::Console::Utils; // From ntstatus.h, which we cannot include without causing a bunch of other conflicts. So we just include the one code we need. // @@ -160,7 +162,6 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API } Globals& Globals = ServiceLocator::LocateGlobals(); - // TODO: only the inside windows one should probably bother trying to delegate, the out of box one could probably assume it doesn't need to. if (!Globals.launchArgs.IsHeadless() && Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) { try @@ -181,17 +182,25 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API msg.InputSize = pReceiveMsg->Descriptor.InputSize; msg.OutputSize = pReceiveMsg->Descriptor.OutputSize; + HANDLE vtIn = Globals.launchArgs.GetVtInHandle(); + HANDLE vtOut = Globals.launchArgs.GetVtOutHandle(); + + // TODO: pass sig if we have it? + HANDLE vtSig = Globals.launchArgs.GetSignalHandle(); + vtSig; + THROW_IF_FAILED(handoff->EstablishHandoff(Globals.pDeviceComm->_Server.get(), Globals.hInputEvent.get(), - Globals.launchArgs.GetVtInHandle(), - Globals.launchArgs.GetVtOutHandle(), + vtIn, + vtOut, Globals.launchArgs.GetOriginalCommandLine().data(), &msg)); - // TODO: anymore cleanup of stuff we're holding onto like handles? + // Unlock in case anything tries to spool down as we exit. UnlockConsole(); - ExitThread(S_OK); + // We've handed off responsibility. Exit process to clean up any outstanding things we have open. + ExitProcess(S_OK); } CATCH_LOG(); // Just log, don't do anything more. We'll move on to launching normally on failure. } From 3539838a3c9841f97a98fbcb84aad02681ff708f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 5 Nov 2020 12:51:56 -0800 Subject: [PATCH 24/80] It's going to be important to put the MIDL outputs in different folders as they can vary. --- src/common.build.pre.props | 2 +- src/host/dll/Host.DLL.vcxproj | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/common.build.pre.props b/src/common.build.pre.props index d89221c3dc4..46ee4f63a7b 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -71,7 +71,7 @@ - /target NT100 %(AdditionalOptions) + /target NT100 /out $(IntDir) %(AdditionalOptions) Use diff --git a/src/host/dll/Host.DLL.vcxproj b/src/host/dll/Host.DLL.vcxproj index 7595becf574..ae5fb5e6d3b 100644 --- a/src/host/dll/Host.DLL.vcxproj +++ b/src/host/dll/Host.DLL.vcxproj @@ -10,11 +10,11 @@ - - - - - + + + + + @@ -24,8 +24,8 @@ - - + + @@ -38,7 +38,7 @@ - ..;%(AdditionalIncludeDirectories) + ..;.;%(AdditionalIncludeDirectories) PROXY_CLSID=CLSID_IConsoleProxy;REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions) NotUsing From 5bef8378a6a3c5c86e3a38d96b31ae7bc2c8a341 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 13:30:45 -0800 Subject: [PATCH 25/80] Fix up the last things required to finish the merge and get it working again. --- .vscode/tasks.json | 1 + OpenConsole.sln | 70 +++++++++---------- .../CascadiaPackage/CascadiaPackage.wapproj | 2 +- .../TerminalApp/AppCommandlineArgs.cpp | 5 +- .../TerminalApp/ShortcutActionDispatch.cpp | 2 +- .../TerminalConnection/CTerminalHandoff.h | 10 ++- .../TerminalConnection.vcxproj | 3 + src/host/exe/CConsoleHandoff.cpp | 12 ---- src/host/exe/CConsoleHandoff.h | 13 ++-- src/host/exe/Host.EXE.vcxproj | 2 +- src/host/host-common.vcxitems | 2 +- src/host/proxy/Host.Proxy.vcxproj | 10 +-- src/host/proxy/Host.Proxy.vcxproj.filters | 22 ++---- 13 files changed, 74 insertions(+), 80 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 827e4c40762..c8d1cf1ad8f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -17,6 +17,7 @@ "/p:Configuration=${input:configChoice}", "/p:Platform=${input:platformChoice}", "/t:$target", + "/m", "/verbosity:minimal" ], "problemMatcher": ["$msCompile"], diff --git a/OpenConsole.sln b/OpenConsole.sln index a25f77535e5..7796252ead9 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -12,7 +12,7 @@ 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 - {E437B604-3E98-4F40-A927-E173E818EA4B} = {E437B604-3E98-4F40-A927-E173E818EA4B} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} = {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} {0CF235BD-2DA0-407E-90EE-C467E8BBC714} = {0CF235BD-2DA0-407E-90EE-C467E8BBC714} EndProjectSection EndProject @@ -106,7 +106,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Build Common", "_Build Com EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "src\server\lib\server.vcxproj", "{18D09A24-8240-42D6-8CB6-236EEE820262}" ProjectSection(ProjectDependencies) = postProject - {E437B604-3E98-4F40-A927-E173E818EA4B} = {E437B604-3E98-4F40-A927-E173E818EA4B} + {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}" @@ -323,8 +323,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfTerminalTestNetCore", "s EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wt", "src\cascadia\wt\wt.vcxproj", "{506FD703-BAA7-4F6E-9361-64F550EC8FCA}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.DLL", "src\host\dll\Host.DLL.vcxproj", "{E437B604-3E98-4F40-A927-E173E818EA4B}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.Settings.Editor", "src\cascadia\TerminalSettingsEditor\Microsoft.Terminal.Settings.Editor.vcxproj", "{CA5CAD1A-0B5E-45C3-96A8-BB496BFE4E32}" ProjectSection(ProjectDependencies) = postProject {CA5CAD1A-082C-4476-9F33-94B339494076} = {CA5CAD1A-082C-4476-9F33-94B339494076} @@ -370,7 +368,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}") = "Host.Proxy", "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 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -2548,36 +2546,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 @@ -2668,7 +2666,7 @@ Global {27B5AAEB-A548-44CF-9777-F8BAA32AF7AE} = {59840756-302F-44DF-AA47-441A9D673202} {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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj index 54d25f3b013..865774f3215 100644 --- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj +++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj @@ -70,7 +70,7 @@ - + diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 1c5dbc4cfb6..84f8d806126 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -753,9 +753,8 @@ int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { if (arg == L"-Embedding") { - auto embeddingAction = winrt::make_self(); - embeddingAction->Action(ShortcutAction::ToggleInboundPty); - _startupActions.push_back(*embeddingAction); + winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs embeddingAction(ShortcutAction::ToggleInboundPty, nullptr); + _startupActions.push_back(embeddingAction); return 0; } } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index cf4ec88ff3d..b5b053ba8a3 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -267,7 +267,7 @@ namespace winrt::TerminalApp::implementation } case ShortcutAction::ToggleInboundPty: { - _ToggleInboundPtyHandlers(*this, *eventArgs); + _ToggleInboundPtyHandlers(*this, eventArgs); break; } default: diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 4ee07fec621..ba419bba733 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -1,6 +1,14 @@ #pragma once -#include "..\host\dll\ITerminalHandoff_h.h" +#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 namespace Microsoft::WRL; diff --git a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj index 135685f3c80..62548452353 100644 --- a/src/cascadia/TerminalConnection/TerminalConnection.vcxproj +++ b/src/cascadia/TerminalConnection/TerminalConnection.vcxproj @@ -79,6 +79,9 @@ + + $(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) + $(OpenConsoleCommonOutDir)\conptylib.lib;%(AdditionalDependencies) diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 2bbb10031f5..c054f09757f 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -23,15 +23,9 @@ HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) // 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 -// - in - The input handle originally given to the inbox conhost on startup -// - out - The output handle original given to the inbox conhost on startup -// - argString - Argument string given to the original inbox conhost on startup // - msg - Portable attach message containing just enough descriptor payload to get us started in servicing it HRESULT CConsoleHandoff::EstablishHandoff(HANDLE server, HANDLE inputEvent, - HANDLE in, - HANDLE out, - wchar_t* argString, PCCONSOLE_PORTABLE_ATTACH_MSG msg) try { @@ -56,16 +50,10 @@ try // Making our own duplicate copy ensures they hang around in our lifetime. RETURN_IF_FAILED(_duplicateHandle(server, server)); RETURN_IF_FAILED(_duplicateHandle(inputEvent, inputEvent)); - /*RETURN_IF_FAILED(_duplicateHandle(in, in)); - RETURN_IF_FAILED(_duplicateHandle(out, out));*/ // Build a console arguments structure that contains all information on how the // original console was started. ConsoleArguments consoleArgs; - //(argString, in, out); - UNREFERENCED_PARAMETER(in); - UNREFERENCED_PARAMETER(out); - UNREFERENCED_PARAMETER(argString); // Now perform the handoff. RETURN_IF_FAILED(ConsoleEstablishHandoff(server, &consoleArgs, inputEvent, &apiMsg)); diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h index afaf00c78d0..66238077953 100644 --- a/src/host/exe/CConsoleHandoff.h +++ b/src/host/exe/CConsoleHandoff.h @@ -1,6 +1,14 @@ #pragma once -#include "..\dll\IConsoleHandoff_h.h" +#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; @@ -10,9 +18,6 @@ struct __declspec(uuid(__CLSID_CConsoleHandoff)) #pragma region IConsoleHandoff STDMETHODIMP EstablishHandoff(HANDLE server, HANDLE inputEvent, - HANDLE in, - HANDLE out, - wchar_t* argString, PCCONSOLE_PORTABLE_ATTACH_MSG msg); #pragma endregion diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index 691e9370f47..c9016766c13 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -82,7 +82,7 @@ - ..;%(AdditionalIncludeDirectories) + ..;$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) diff --git a/src/host/host-common.vcxitems b/src/host/host-common.vcxitems index 0361b6f82b3..190eef79209 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/proxy/Host.Proxy.vcxproj b/src/host/proxy/Host.Proxy.vcxproj index 24ffac574ed..f6db5976293 100644 --- a/src/host/proxy/Host.Proxy.vcxproj +++ b/src/host/proxy/Host.Proxy.vcxproj @@ -1,7 +1,7 @@ - {E437B604-3E98-4F40-A927-E173E818EA4B} + {71CC9D78-BA29-4D93-946F-BEF5D9A3A6EF} Win32Proj openconsoleproxy OpenConsoleProxy @@ -41,17 +41,17 @@ - PROXY_CLSID=3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F;%(PreprocessorDefinitions) + PROXY_CLSID_IS={0x3171DE52,0x6EFA,0x4AEF,{0x8A,0x9F,0xD0,0x2B,0xD6,0x7E,0x7A,0x4F}};%(PreprocessorDefinitions) - PROXY_CLSID=1833E661-CC81-4DD0-87C6-C2F74BD39EFA;%(PreprocessorDefinitions) + PROXY_CLSID_IS={0x1833E661,0xCC81,0x4DD0,{0x87,0xC6,0xC2,0xF7,0x4B,0xD3,0x9E,0xFA}};%(PreprocessorDefinitions) - PROXY_CLSID=DEC4804D-56D1-4F73-9FBE-6828E7C85C56;%(PreprocessorDefinitions) + PROXY_CLSID_IS={0xDEC4804D,0x56D1,0x4F73,{0x9F,0xBE,0x68,0x28,0xE7,0xC8,0x5C,0x56}};%(PreprocessorDefinitions) @@ -66,4 +66,4 @@ - + \ No newline at end of file diff --git a/src/host/proxy/Host.Proxy.vcxproj.filters b/src/host/proxy/Host.Proxy.vcxproj.filters index 58fd7c39204..df6bcbd10c6 100644 --- a/src/host/proxy/Host.Proxy.vcxproj.filters +++ b/src/host/proxy/Host.Proxy.vcxproj.filters @@ -15,19 +15,19 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files @@ -35,13 +35,10 @@ - + Header Files - - Header Files - - + Header Files @@ -53,9 +50,4 @@ Source Files - - - Source Files - - \ No newline at end of file From 81b4914a52940a6033087dd29becf00c784db053 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 13:37:54 -0800 Subject: [PATCH 26/80] Spell check. --- .github/actions/spelling/dictionary/apis.txt | 5 +++++ .github/actions/spelling/expect/expect.txt | 1 + src/cascadia/TerminalConnection/CTerminalHandoff.cpp | 6 +++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/actions/spelling/dictionary/apis.txt b/.github/actions/spelling/dictionary/apis.txt index e83f15dcc13..9c7f9097348 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 @@ -81,6 +82,7 @@ schandle semver serializer shobjidl +SINGLEUSE SIZENS smoothstep GETDESKWALLPAPER @@ -90,6 +92,7 @@ spsc sregex STDCPP strchr +STDMETHOD Subheader Subpage UPDATEINIFILE @@ -105,8 +108,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 96c6fe7f479..614bbac803b 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -432,6 +432,7 @@ cstring cstyle csv CSwitch +CTerminal CText ctime ctl diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 04f64d822d9..99ce21a11a5 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -4,7 +4,7 @@ // The callback function when a connection is received static NewHandoff _pfnHandoff = nullptr; -// The registration ID of the class object for deregistration later +// The registration ID of the class object for clean up later static DWORD g_cTerminalHandoffRegistration = 0; // Routine Description: @@ -34,12 +34,12 @@ HRESULT CTerminalHandoff::s_StartListening(NewHandoff pfnHandoff) } // Routine Description: -// - Stops listening for TerminalHandoff requests by deregistering +// - 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 deregistration error +// - S_OK, E_NOT_VALID_STATE (stop called when not started), or relevant COM class revoke error HRESULT CTerminalHandoff::s_StopListening() { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff == nullptr); From c4e1c8adf5a2ec172d7ad6401ff6251830a4f021 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 13:40:05 -0800 Subject: [PATCH 27/80] Add code format task to VScode tasks. Run code format task. --- .vscode/tasks.json | 15 +++++++++++++-- src/cascadia/TerminalApp/TerminalPage.cpp | 4 ++-- .../TerminalConnection/CTerminalHandoff.cpp | 3 +-- .../TerminalConnection/CTerminalHandoff.h | 6 +++--- .../TerminalConnection/ConptyConnection.cpp | 10 +++++----- .../TerminalConnection/ConptyConnection.h | 3 +-- src/host/exe/CConsoleHandoff.h | 6 +++--- src/host/exe/exemain.cpp | 1 - src/host/globals.h | 2 +- src/host/proxy/ConsoleComGuids.h | 12 ++++++------ 10 files changed, 35 insertions(+), 27 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index c8d1cf1ad8f..81884fba3f6 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -47,8 +47,7 @@ ], "problemMatcher": ["$msCompile"], "group": { - "kind": "build", - "isDefault": true + "kind": "build" } }, { @@ -58,6 +57,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/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index ecb14e4b94e..c5993a80fbc 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3022,7 +3022,7 @@ namespace winrt::TerminalApp::implementation } void TerminalPage::_OnInboundPtyChanged(const IInspectable& /*sender*/, - const IInspectable& /*eventArgs*/) + const IInspectable& /*eventArgs*/) { if (InboundPty()) { @@ -3039,7 +3039,7 @@ namespace winrt::TerminalApp::implementation // TODO: this should probably use a more reasonable profile than nullptr. _OpenNewTab(nullptr, connection); } - + // Method Description: // - Updates all tabs with their current index in _tabs. // Arguments: diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 99ce21a11a5..6ba0b5bd471 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -20,7 +20,7 @@ HRESULT CTerminalHandoff::s_StartListening(NewHandoff pfnHandoff) // We could probably hold this in a static... auto classFactory = Make>(); - + RETURN_IF_NULL_ALLOC(classFactory); ComPtr unk; @@ -82,4 +82,3 @@ HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) // Call registered handler from when we started listening. return _pfnHandoff(in, out, signal); } - diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index ba419bba733..931285a887e 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -3,11 +3,11 @@ #include "ITerminalHandoff.h" #if defined(WT_BRANDING_RELEASE) - #define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" +#define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" #elif defined(WT_BRANDING_PREVIEW) - #define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" +#define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" #else - #define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" +#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" #endif using namespace Microsoft::WRL; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 3485204bbab..96113cdcc63 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -195,17 +195,17 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation const uint64_t hIn, const uint64_t hOut) : _initialRows{ 25 }, - _initialCols{ 80}, + _initialCols{ 80 }, _commandline{ L"" }, - _startingDirectory{ L""}, + _startingDirectory{ L"" }, _startingTitle{ L"" }, - _environment{ nullptr}, + _environment{ nullptr }, _guid{}, _u8State{}, _u16Str{}, _buffer{}, _inPipe{ (HANDLE)hIn }, - _outPipe{(HANDLE)hOut} + _outPipe{ (HANDLE)hOut } { hSig; // TODO: this needs to be packed into the hpcon if (_guid == guid{}) @@ -502,7 +502,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { 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 70a687614b4..811adf69bb8 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -45,11 +45,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation static winrt::event_token NewConnection(NewConnectionHandler const& handler); static void NewConnection(winrt::event_token const& token); - + WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler); private: - HRESULT _LaunchAttachedClient() noexcept; void _indicateExitWithStatus(unsigned int status) noexcept; void _ClientTerminated() noexcept; diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h index 66238077953..aa544d7ece3 100644 --- a/src/host/exe/CConsoleHandoff.h +++ b/src/host/exe/CConsoleHandoff.h @@ -3,11 +3,11 @@ #include "IConsoleHandoff.h" #if defined(WT_BRANDING_RELEASE) - #define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" +#define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" #elif defined(WT_BRANDING_PREVIEW) - #define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" +#define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" #else - #define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" +#define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" #endif using namespace Microsoft::WRL; diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index 5a5264c136d..dcc71a56b7a 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -209,7 +209,6 @@ int CALLBACK wWinMain( _comServerExitEvent.create(); auto& module = OutOfProcModuleWithRegistrationFlag::Create(&_releaseNotifier); - // Register Trace provider by GUID TraceLoggingRegister(g_ConhostLauncherProvider); diff --git a/src/host/globals.h b/src/host/globals.h index c5ebb2a7006..4edf2bbc454 100644 --- a/src/host/globals.h +++ b/src/host/globals.h @@ -71,7 +71,7 @@ class Globals ApiRoutines api; bool handoffTarget = false; - + std::optional handoffConsoleClsid; std::optional handoffTerminalClsid; diff --git a/src/host/proxy/ConsoleComGuids.h b/src/host/proxy/ConsoleComGuids.h index 29e0bc77f88..7dd42207492 100644 --- a/src/host/proxy/ConsoleComGuids.h +++ b/src/host/proxy/ConsoleComGuids.h @@ -1,12 +1,12 @@ #pragma once #if defined(WT_BRANDING_RELEASE) - #define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" - #define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" +#define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" +#define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" #elif defined(WT_BRANDING_PREVIEW) - #define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" - #define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" +#define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" +#define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" #else - #define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" - #define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" +#define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" +#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" #endif From 1111f6b1ba647d6441b6bbd4903ba6e81993b404 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 13:40:44 -0800 Subject: [PATCH 28/80] Remove guids file. They were moved to closer locations. --- src/host/proxy/ConsoleComGuids.h | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 src/host/proxy/ConsoleComGuids.h diff --git a/src/host/proxy/ConsoleComGuids.h b/src/host/proxy/ConsoleComGuids.h deleted file mode 100644 index 7dd42207492..00000000000 --- a/src/host/proxy/ConsoleComGuids.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#if defined(WT_BRANDING_RELEASE) -#define __CLSID_CConsoleHandoff "2EACA947-7F5F-4CFA-BA87-8F7FBEEFBE69" -#define __CLSID_CTerminalHandoff "E12CFF52-A866-4C77-9A90-F570A7AA2C6B" -#elif defined(WT_BRANDING_PREVIEW) -#define __CLSID_CConsoleHandoff "06EC847C-C0A5-46B8-92CB-7C92F6E35CD5" -#define __CLSID_CTerminalHandoff "86633F1F-6454-40EC-89CE-DA4EBA977EE2" -#else -#define __CLSID_CConsoleHandoff "1F9F2BF5-5BC3-4F17-B0E6-912413F1F451" -#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" -#endif From ed3001952cee809421f556f65213682743225002 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 13:56:02 -0800 Subject: [PATCH 29/80] Some draft PR comments. --- src/cascadia/TerminalApp/Resources/en-US/Resources.resw | 8 ++++---- src/host/exe/Host.EXE.vcxproj | 2 -- src/host/proxy/IConsoleHandoff.idl | 3 +++ src/host/proxy/ITerminalHandoff.idl | 3 +++ 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index ca65d26502d..f1818f2f710 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -223,12 +223,12 @@ Warnings were found while parsing your keybindings: - • Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array. - {Locked="\"keys\"","•"} This glyph is a bullet, used in a bulleted list. + • Found a keybinding with too many strings for the "keys" array. There should only be one string value in the "keys" array. + {Locked="\"keys\"","•"} This glyph is a bullet, used in a bulleted list. - • Found a keybinding that was missing a required parameter value. This keybinding will be ignored. - {Locked="•"} This glyph is a bullet, used in a bulleted list. + • Found a keybinding that was missing a required parameter value. This keybinding will be ignored. + {Locked="•"} This glyph is a bullet, used in a bulleted list. The "globals" property is deprecated - your settings might need updating. diff --git a/src/host/exe/Host.EXE.vcxproj b/src/host/exe/Host.EXE.vcxproj index c9016766c13..260915fcc25 100644 --- a/src/host/exe/Host.EXE.vcxproj +++ b/src/host/exe/Host.EXE.vcxproj @@ -85,8 +85,6 @@ ..;$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories) - - true diff --git a/src/host/proxy/IConsoleHandoff.idl b/src/host/proxy/IConsoleHandoff.idl index 9af705ccb63..067eb0efa83 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"; diff --git a/src/host/proxy/ITerminalHandoff.idl b/src/host/proxy/ITerminalHandoff.idl index a0c5c150e2b..1a6af5b3699 100644 --- a/src/host/proxy/ITerminalHandoff.idl +++ b/src/host/proxy/ITerminalHandoff.idl @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + import "oaidl.idl"; import "ocidl.idl"; From 5ba43007d52bd65645a521f62022e52368fd68ec Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 14:55:58 -0800 Subject: [PATCH 30/80] undo common change to midls as they're used elsewhere in this proj. --- src/common.build.pre.props | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/common.build.pre.props b/src/common.build.pre.props index 09ec6e27f26..52e19f02552 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -77,9 +77,6 @@ - - /target NT100 /out $(IntDir) %(AdditionalOptions) - Use Level4 From ea58e2831f5df3dda0d4863d88fbf25bb1f1abff Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 16:11:45 -0800 Subject: [PATCH 31/80] Initial placement of UI --- .../TerminalSettingsEditor/Launch.cpp | 32 ++++++++++ src/cascadia/TerminalSettingsEditor/Launch.h | 8 +++ .../TerminalSettingsEditor/Launch.idl | 7 ++- .../TerminalSettingsEditor/Launch.xaml | 18 ++++++ .../Resources/en-US/Resources.resw | 12 ++++ src/propsheet/TerminalPropsheetPage.cpp | 61 +++++++++++++++++++ src/propsheet/console.rc | 22 +++++++ src/propsheet/dialogs.h | 2 + 8 files changed, 161 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalSettingsEditor/Launch.cpp b/src/cascadia/TerminalSettingsEditor/Launch.cpp index b2bbaedd4bf..4183fb46722 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.cpp +++ b/src/cascadia/TerminalSettingsEditor/Launch.cpp @@ -37,4 +37,36 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation const auto profile{ winrt::unbox_value(value) }; _State.Settings().GlobalSettings().DefaultProfile(profile.Guid()); } + + 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; + } + + Windows::Foundation::Collections::IObservableVector Launch::DefaultConsoles() + { + Windows::Foundation::Collections::IObservableVector vec; + return vec; + } + + IInspectable Launch::CurrentDefaultConsole() + { + return nullptr; + } + + void Launch::CurrentDefaultConsole(const IInspectable& value) + { + value; + } } diff --git a/src/cascadia/TerminalSettingsEditor/Launch.h b/src/cascadia/TerminalSettingsEditor/Launch.h index 33fb30cb63c..e4cf8d47391 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.h +++ b/src/cascadia/TerminalSettingsEditor/Launch.h @@ -28,6 +28,14 @@ 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); + + Windows::Foundation::Collections::IObservableVector DefaultConsoles(); + IInspectable CurrentDefaultConsole(); + void CurrentDefaultConsole(const IInspectable& value); + GETSET_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 e2a1382e0d3..1d8a432cd1e 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.idl +++ b/src/cascadia/TerminalSettingsEditor/Launch.idl @@ -17,10 +17,15 @@ namespace Microsoft.Terminal.Settings.Editor IInspectable CurrentDefaultProfile; + IInspectable CurrentDefaultTerminal; + IObservableVector DefaultTerminals { get; }; + + IInspectable CurrentDefaultConsole; + IObservableVector DefaultConsoles { 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 ab0b60d1862..0a5176cc1db 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -67,6 +67,24 @@ 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 967147f7023..6516f71908f 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -201,6 +201,18 @@ Profile that opens when clicking the '+' icon or by typing the new tab key binding. + + Default terminal + + + The terminal application that launches when a command-line application is run without an existing session, like from the Start Menu or Run dialog. + + + Default console (PTY) + + + The console engine and pseudoconsole version that will be used to power the default terminal application. + Redraw entire screen when display updates diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index 5d1c6c6c682..5de854f9b34 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -181,6 +181,21 @@ bool InitTerminalDialog(const HWND hDlg) noexcept CheckDlgButton(hDlg, IDD_DISABLE_SCROLLFORWARD, gpStateInfo->TerminalScrolling); + HWND hTermCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFTERM); + ComboBox_ResetContent(hTermCombo); + ComboBox_AddString(hTermCombo, TEXT("Term1")); + ComboBox_AddString(hTermCombo, TEXT("Term2")); + ComboBox_AddString(hTermCombo, TEXT("Term3")); + ComboBox_SetCurSel(hTermCombo, 0); + ComboBox_Enable(hTermCombo, TRUE); + + HWND hConCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFCON); + ComboBox_ResetContent(hConCombo); + ComboBox_AddString(hConCombo, TEXT("Con1")); + ComboBox_AddString(hConCombo, TEXT("Con2")); + ComboBox_SetCurSel(hConCombo, 0); + ComboBox_Enable(hConCombo, TRUE); + return true; } @@ -341,11 +356,57 @@ bool TerminalDlgCommand(const HWND hDlg, const WORD item, const WORD command) no break; } case IDD_DISABLE_SCROLLFORWARD: + { gpStateInfo->TerminalScrolling = IsDlgButtonChecked(hDlg, IDD_DISABLE_SCROLLFORWARD); UpdateApplyButton(hDlg); handled = true; break; } + case IDD_TERMINAL_COMBO_DEFTERM: + { + if (CBN_SELCHANGE == command) + { + HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFTERM); + wchar_t buf[50]; + DWORD comboItem = ComboBox_GetCurSel(hCombo); + if (CB_ERR != comboItem) + { + if (ComboBox_GetLBTextLen(hCombo, comboItem) < ARRAYSIZE(buf)) + { + ComboBox_GetLBText(hCombo, comboItem, buf); + MessageBox(hDlg, (LPCWSTR)buf, TEXT("Terminal Selected"), MB_OK); + } + else + { + MessageBox(hDlg, (LPCWSTR)L"Terminal item too big.", TEXT("Terminal Selection Error"), MB_OK); + } + } + } + break; + } + case IDD_TERMINAL_COMBO_DEFCON: + { + if (CBN_SELCHANGE == command) + { + HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFCON); + wchar_t buf[50]; + DWORD comboItem = ComboBox_GetCurSel(hCombo); + if (CB_ERR != comboItem) + { + if (ComboBox_GetLBTextLen(hCombo, comboItem) < ARRAYSIZE(buf)) + { + ComboBox_GetLBText(hCombo, comboItem, buf); + MessageBox(hDlg, (LPCWSTR)buf, TEXT("Console Selected"), MB_OK); + } + else + { + MessageBox(hDlg, (LPCWSTR)L"Console item too big.", TEXT("Console Selection Error"), MB_OK); + } + } + } + break; + } + } return handled; } diff --git a/src/propsheet/console.rc b/src/propsheet/console.rc index dd7bc9df01e..9d074484854 100644 --- a/src/propsheet/console.rc +++ b/src/propsheet/console.rc @@ -534,6 +534,22 @@ END #define T_SCROLL_W 100 #define T_SCROLL_H 40 +// default application group box +#define T_DEFAPP_X T_CCOLOR_X +#define T_DEFAPP_Y T_SCROLL_Y +#define T_DEFAPP_W T_CCOLOR_W +#define T_DEFAPP_H 54 + +#define T_DEFTERM_X (T_DEFAPP_X+P_1) +#define T_DEFTERM_Y (T_DEFAPP_Y+P_2) +#define T_DEFTERM_W (T_DEFAPP_W-P_4-P_4) +#define T_DEFTERM_H 25 + +#define T_DEFCON_X T_DEFTERM_X +#define T_DEFCON_Y (T_DEFTERM_Y+P_4+P_4+P_0+P_0) +#define T_DEFCON_W T_DEFTERM_W +#define T_DEFCON_H T_DEFTERM_H + #define UPDOWN_STYLES (UDS_AUTOBUDDY | UDS_SETBUDDYINT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_ALIGNRIGHT) DID_TERMINAL DIALOG 0, 0, 245, 226 CAPTION " Terminal " @@ -620,6 +636,12 @@ BEGIN GROUPBOX "Terminal Scrolling", -1, T_SCROLL_X, T_SCROLL_Y, T_SCROLL_W, T_SCROLL_H AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10 + GROUPBOX "Default Launch Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H + LTEXT "Terminal Window", -1, T_DEFTERM_X, T_DEFTERM_Y, T_DEFTERM_W, T_DEFTERM_H + COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y+P_2, T_DEFTERM_W-P_4-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Console Engine", -1, T_DEFCON_X, T_DEFCON_Y, T_DEFCON_W, T_DEFCON_H + COMBOBOX IDD_TERMINAL_COMBO_DEFCON, T_DEFCON_X+P_1, T_DEFCON_Y+P_2, T_DEFCON_W-P_4-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Find out more about experimental terminal settings", IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10 END diff --git a/src/propsheet/dialogs.h b/src/propsheet/dialogs.h index 60949a070ad..1aaeb24dd89 100644 --- a/src/propsheet/dialogs.h +++ b/src/propsheet/dialogs.h @@ -164,6 +164,8 @@ Revision History: #define IDD_TERMINAL_CURSOR_GREEN 630 #define IDD_TERMINAL_CURSOR_BLUE 631 #define IDD_HELP_TERMINAL 632 +#define IDD_TERMINAL_COMBO_DEFTERM 640 +#define IDD_TERMINAL_COMBO_DEFCON 641 #define BM_TRUETYPE_ICON 1000 From ae7779193dcc195cc8d461cbe3ff4c5e07333c87 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 2 Mar 2021 16:12:04 -0800 Subject: [PATCH 32/80] Add more flags to make build easier. --- .vscode/tasks.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 81884fba3f6..e9942e0bb6d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,8 +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", + "/m", // Parallel builds "/verbosity:minimal" ], "problemMatcher": ["$msCompile"], From 83ef4d2d3c9ad53a9e2d96659acb5ae4c112f25f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 3 Mar 2021 10:06:11 -0800 Subject: [PATCH 33/80] Fix audit mode issues with the macro, noexcept, and override. --- .../TerminalConnection/CTerminalHandoff.cpp | 10 ++++++---- .../TerminalConnection/CTerminalHandoff.h | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 6ba0b5bd471..28889c259aa 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -14,7 +14,8 @@ static DWORD g_cTerminalHandoffRegistration = 0; // - 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(NewHandoff pfnHandoff) +HRESULT CTerminalHandoff::s_StartListening(NewHandoff pfnHandoff) noexcept +try { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); @@ -32,6 +33,7 @@ HRESULT CTerminalHandoff::s_StartListening(NewHandoff pfnHandoff) return S_OK; } +CATCH_RETURN() // Routine Description: // - Stops listening for TerminalHandoff requests by revoking the registration @@ -40,7 +42,7 @@ HRESULT CTerminalHandoff::s_StartListening(NewHandoff pfnHandoff) // - // Return Value: // - S_OK, E_NOT_VALID_STATE (stop called when not started), or relevant COM class revoke error -HRESULT CTerminalHandoff::s_StopListening() +HRESULT CTerminalHandoff::s_StopListening() noexcept { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff == nullptr); @@ -63,13 +65,13 @@ HRESULT CTerminalHandoff::s_StopListening() // - out - Where to place the duplicated value // Return Value: // - S_OK or Win32 error from `::DuplicateHandle` -HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) +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; } -HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) +HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept { // Duplicate the handles from what we received. // The contract with COM specifies that any HANDLEs we receive from the caller belong diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 931285a887e..83c81be0d1d 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -20,12 +20,22 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) #pragma region ITerminalHandoff STDMETHODIMP EstablishHandoff(HANDLE in, HANDLE out, - HANDLE signal); + HANDLE signal) noexcept override; #pragma endregion - static HRESULT s_StartListening(NewHandoff pfnHandoff); - static HRESULT s_StopListening(); + static HRESULT s_StartListening(NewHandoff pfnHandoff) noexcept; + static HRESULT s_StopListening() noexcept; }; +// Disable warnings from the CoCreateableClass 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) From ed1da2b471f5f5995f14eb311a3d4355ec849118 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 3 Mar 2021 10:25:04 -0800 Subject: [PATCH 34/80] spell check will be the end of me. --- src/cascadia/TerminalConnection/CTerminalHandoff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 83c81be0d1d..3f522d74449 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -28,7 +28,7 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) static HRESULT s_StopListening() noexcept; }; -// Disable warnings from the CoCreateableClass macro as the value it provides for +// 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) From 04967e5619055e4affdc85d2567d4e398e712437 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 3 Mar 2021 10:35:44 -0800 Subject: [PATCH 35/80] Add stdcall convention to resolve x86 build/link issue in proxy. --- src/host/proxy/Host.Proxy.vcxproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/host/proxy/Host.Proxy.vcxproj b/src/host/proxy/Host.Proxy.vcxproj index f6db5976293..9d479599e4c 100644 --- a/src/host/proxy/Host.Proxy.vcxproj +++ b/src/host/proxy/Host.Proxy.vcxproj @@ -57,6 +57,7 @@ ..;%(AdditionalIncludeDirectories) + StdCall REGISTER_PROXY_DLL;%(PreprocessorDefinitions) NotUsing @@ -66,4 +67,4 @@ - \ No newline at end of file + From e17598880a95470e06781d212bbb25e301baa2fb Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 3 Mar 2021 13:29:42 -0800 Subject: [PATCH 36/80] Make propsheet work. --- OpenConsole.sln | 1 + src/internal/stubs.cpp | 2 +- src/propsheet/TerminalPropsheetPage.cpp | 80 ++++++++++++++----------- src/propsheet/console.cpp | 21 +++++++ src/propsheet/console.rc | 4 +- src/propsheet/globals.cpp | 7 +++ src/propsheet/globals.h | 7 +++ src/propsheet/propsheet.vcxproj | 3 + src/propslib/DelegationConfig.cpp | 24 +++++--- src/propslib/DelegationConfig.hpp | 4 +- 10 files changed, 107 insertions(+), 46 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 7796252ead9..1662ce0bde0 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -14,6 +14,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.EXE", "src\host\exe\Ho 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}" diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index ac312a23e71..7c8d4e6c5b0 100644 --- a/src/internal/stubs.cpp +++ b/src/internal/stubs.cpp @@ -32,6 +32,6 @@ void EdpPolicy::AuditClipboard(const std::wstring_view /*destinationName*/) noex [[nodiscard]] HRESULT DefaultApp::CheckDefaultAppPolicy(bool& isEnabled) noexcept { - isEnabled = false; + isEnabled = true; return S_OK; } \ No newline at end of file diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index 5de854f9b34..82eedbc289a 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -6,6 +6,7 @@ #include "OptionsPage.h" // For InitializeCursorSize #include "ColorControl.h" #include +#include "../propslib/DelegationConfig.hpp" // From conattrs.h const COLORREF INVALID_COLOR = 0xffffffff; @@ -87,6 +88,36 @@ void _UpdateTextAndScroll(const HWND hDlg, SendDlgItemMessage(hDlg, scrollItem, UDM_SETPOS, 0, MAKELONG(value, 0)); } +template +void _PrepDefAppCombo(const HWND hDlg, + const int dlgItem, + const std::vector& list, + const IID selected, + const bool enabled) +{ + HWND hCombo = GetDlgItem(hDlg, dlgItem); + ComboBox_ResetContent(hCombo); + + DWORD selectedIndex = 0; + for (DWORD i = 0; i < gsl::narrow(list.size()); ++i) + { + auto& item = list[i]; + ComboBox_AddString(hCombo, item.name.c_str()); + ComboBox_SetItemData(hCombo, i, &item.clsid); + if (selected == item.clsid) + { + selectedIndex = i; + } + } + + ComboBox_SetCurSel(hCombo, selectedIndex); + + if (enabled) + { + ComboBox_Enable(hCombo, TRUE); + } +} + bool InitTerminalDialog(const HWND hDlg) noexcept { // Initialize the global handle to this dialog @@ -181,20 +212,17 @@ bool InitTerminalDialog(const HWND hDlg) noexcept CheckDlgButton(hDlg, IDD_DISABLE_SCROLLFORWARD, gpStateInfo->TerminalScrolling); - HWND hTermCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFTERM); - ComboBox_ResetContent(hTermCombo); - ComboBox_AddString(hTermCombo, TEXT("Term1")); - ComboBox_AddString(hTermCombo, TEXT("Term2")); - ComboBox_AddString(hTermCombo, TEXT("Term3")); - ComboBox_SetCurSel(hTermCombo, 0); - ComboBox_Enable(hTermCombo, TRUE); - - HWND hConCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFCON); - ComboBox_ResetContent(hConCombo); - ComboBox_AddString(hConCombo, TEXT("Con1")); - ComboBox_AddString(hConCombo, TEXT("Con2")); - ComboBox_SetCurSel(hConCombo, 0); - ComboBox_Enable(hConCombo, TRUE); + _PrepDefAppCombo(hDlg, + IDD_TERMINAL_COMBO_DEFTERM, + g_availableTerminals, + g_selectedTerminal, + g_defAppEnabled); + + _PrepDefAppCombo(hDlg, + IDD_TERMINAL_COMBO_DEFCON, + g_availableConsoles, + g_selectedConsole, + g_defAppEnabled); return true; } @@ -367,19 +395,11 @@ bool TerminalDlgCommand(const HWND hDlg, const WORD item, const WORD command) no if (CBN_SELCHANGE == command) { HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFTERM); - wchar_t buf[50]; DWORD comboItem = ComboBox_GetCurSel(hCombo); if (CB_ERR != comboItem) { - if (ComboBox_GetLBTextLen(hCombo, comboItem) < ARRAYSIZE(buf)) - { - ComboBox_GetLBText(hCombo, comboItem, buf); - MessageBox(hDlg, (LPCWSTR)buf, TEXT("Terminal Selected"), MB_OK); - } - else - { - MessageBox(hDlg, (LPCWSTR)L"Terminal item too big.", TEXT("Terminal Selection Error"), MB_OK); - } + auto pClsid = reinterpret_cast(ComboBox_GetItemData(hCombo, comboItem)); + g_selectedTerminal = *pClsid; } } break; @@ -389,19 +409,11 @@ bool TerminalDlgCommand(const HWND hDlg, const WORD item, const WORD command) no if (CBN_SELCHANGE == command) { HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFCON); - wchar_t buf[50]; DWORD comboItem = ComboBox_GetCurSel(hCombo); if (CB_ERR != comboItem) { - if (ComboBox_GetLBTextLen(hCombo, comboItem) < ARRAYSIZE(buf)) - { - ComboBox_GetLBText(hCombo, comboItem, buf); - MessageBox(hDlg, (LPCWSTR)buf, TEXT("Console Selected"), MB_OK); - } - else - { - MessageBox(hDlg, (LPCWSTR)L"Console item too big.", TEXT("Console Selection Error"), MB_OK); - } + auto pClsid = reinterpret_cast(ComboBox_GetItemData(hCombo, comboItem)); + g_selectedConsole = *pClsid; } } break; diff --git a/src/propsheet/console.cpp b/src/propsheet/console.cpp index 8a32a15faa9..e7f940ad69c 100644 --- a/src/propsheet/console.cpp +++ b/src/propsheet/console.cpp @@ -19,6 +19,8 @@ Revision History: #include "precomp.h" +#include "conint.h" + #pragma hdrstop UINT gnCurrentPage; @@ -94,9 +96,16 @@ void SaveConsoleSettingsIfNeeded(const HWND hwnd) gpStateInfo->FaceName[0] = TEXT('\0'); } + if (g_defAppEnabled) + { + LOG_IF_FAILED(DelegationConfig::s_SetTerminal(g_selectedTerminal)); + LOG_IF_FAILED(DelegationConfig::s_SetConsole(g_selectedConsole)); + } + if (gpStateInfo->LinkTitle != nullptr) { SetGlobalRegistryValues(); + if (!NT_SUCCESS(ShortcutSerialization::s_SetLinkValues(gpStateInfo, g_fEastAsianSystem, g_fForceV2, @@ -611,6 +620,18 @@ INT_PTR ConsolePropertySheet(__in HWND hWnd, __in PCONSOLE_STATE_INFO pStateInfo // since we just triggered font enumeration, recreate our font handles to adapt for DPI RecreateFontHandles(hWnd); + // + // Find the available default consoles/terminals + // + + if (SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(g_defAppEnabled)) && g_defAppEnabled) + { + LOG_IF_FAILED(DelegationConfig::s_GetAvailableTerminals(g_availableTerminals)); + LOG_IF_FAILED(DelegationConfig::s_GetTerminal(g_selectedTerminal)); + LOG_IF_FAILED(DelegationConfig::s_GetAvailableConsoles(g_availableConsoles)); + LOG_IF_FAILED(DelegationConfig::s_GetTerminal(g_selectedConsole)); + } + // // Get the current page number // diff --git a/src/propsheet/console.rc b/src/propsheet/console.rc index 9d074484854..00972ac8971 100644 --- a/src/propsheet/console.rc +++ b/src/propsheet/console.rc @@ -638,9 +638,9 @@ BEGIN GROUPBOX "Default Launch Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H LTEXT "Terminal Window", -1, T_DEFTERM_X, T_DEFTERM_Y, T_DEFTERM_W, T_DEFTERM_H - COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y+P_2, T_DEFTERM_W-P_4-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y+P_2, T_DEFTERM_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "Console Engine", -1, T_DEFCON_X, T_DEFCON_Y, T_DEFCON_W, T_DEFCON_H - COMBOBOX IDD_TERMINAL_COMBO_DEFCON, T_DEFCON_X+P_1, T_DEFCON_Y+P_2, T_DEFCON_W-P_4-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDD_TERMINAL_COMBO_DEFCON, T_DEFCON_X+P_1, T_DEFCON_Y+P_2, T_DEFCON_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Find out more about experimental terminal settings", IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10 diff --git a/src/propsheet/globals.cpp b/src/propsheet/globals.cpp index 980b60a263b..89aef20cc63 100644 --- a/src/propsheet/globals.cpp +++ b/src/propsheet/globals.cpp @@ -59,3 +59,10 @@ COLORREF g_fakeCursorColor = RGB(242, 242, 242); // Default bright white HWND g_hTerminalDlg = static_cast(INVALID_HANDLE_VALUE); HWND g_hOptionsDlg = static_cast(INVALID_HANDLE_VALUE); + +bool g_defAppEnabled = false; +std::vector g_availableConsoles; +std::vector g_availableTerminals; +CLSID g_selectedConsole; +CLSID g_selectedTerminal; + diff --git a/src/propsheet/globals.h b/src/propsheet/globals.h index 5ae9bb2fa16..65d3b34fbe3 100644 --- a/src/propsheet/globals.h +++ b/src/propsheet/globals.h @@ -14,6 +14,7 @@ #pragma once #include "font.h" +#include "../propslib/DelegationConfig.hpp" extern HINSTANCE ghInstance; extern PCONSOLE_STATE_INFO gpStateInfo; @@ -54,3 +55,9 @@ extern COLORREF g_fakeCursorColor; extern HWND g_hTerminalDlg; extern HWND g_hOptionsDlg; + +extern bool g_defAppEnabled; +extern std::vector g_availableConsoles; +extern std::vector g_availableTerminals; +extern CLSID g_selectedConsole; +extern CLSID g_selectedTerminal; diff --git a/src/propsheet/propsheet.vcxproj b/src/propsheet/propsheet.vcxproj index d981afa01c1..47a137dc774 100644 --- a/src/propsheet/propsheet.vcxproj +++ b/src/propsheet/propsheet.vcxproj @@ -53,6 +53,9 @@ {345fd5a4-b32b-4f29-bd1c-b033bd2c35cc} + + {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00} + diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 8ad4698733f..dba3f2fcc49 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -33,7 +33,14 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept { vec.clear(); - auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED); + T useInbox; + useInbox.clsid = { 0 }; + useInbox.name = L"Windows Console Host"; + useInbox.author = L"Microsoft Corporation"; + + vec.push_back(useInbox); + + auto coinit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED); ComPtr catalogStatics; RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_AppExtensions_AppExtensionCatalog).Get(), &catalogStatics)); @@ -149,23 +156,25 @@ try } CATCH_RETURN() -[[nodiscard]] HRESULT DelegationConfig::s_SetConsole(const DelegationConsole& console) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_SetConsole(const IID& iid) noexcept { - return s_Set(DELEGATION_CONSOLE_KEY_NAME, console.clsid); + return s_Set(DELEGATION_CONSOLE_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_SetTerminal(const DelegationTerminal& terminal) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_SetTerminal(const IID& iid) noexcept { - return s_Set(DELEGATION_TERMINAL_KEY_NAME, terminal.clsid); + return s_Set(DELEGATION_TERMINAL_KEY_NAME, iid); } [[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) noexcept { + iid = {0}; return s_Get(DELEGATION_CONSOLE_KEY_NAME, iid); } [[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) noexcept { + iid = {0}; return s_Get(DELEGATION_TERMINAL_KEY_NAME, iid); } @@ -192,7 +201,7 @@ CATCH_RETURN() RETURN_NTSTATUS(result); } - auto buffer = std::make_unique(bytesNeeded / sizeof(wchar_t)); + auto buffer = std::make_unique(bytesNeeded / sizeof(wchar_t) + 1); DWORD bytesUsed = 0; @@ -203,6 +212,7 @@ CATCH_RETURN() reinterpret_cast(buffer.get()), &bytesUsed)); + RETURN_IF_FAILED(IIDFromString(buffer.get(), &iid)); return S_OK; @@ -222,7 +232,7 @@ try wil::unique_cotaskmem_string str; RETURN_IF_FAILED(StringFromCLSID(clsid, &str)); - RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(startupKey.get(), value, REG_SZ, reinterpret_cast(str.get()), gsl::narrow(wcslen(str.get() + 1) * sizeof(wchar_t)))); + RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(startupKey.get(), value, REG_SZ, reinterpret_cast(str.get()), gsl::narrow(wcslen(str.get()) * sizeof(wchar_t)))); return S_OK; } diff --git a/src/propslib/DelegationConfig.hpp b/src/propslib/DelegationConfig.hpp index 7136395945e..5e2562e8236 100644 --- a/src/propslib/DelegationConfig.hpp +++ b/src/propslib/DelegationConfig.hpp @@ -36,8 +36,8 @@ class DelegationConfig [[nodiscard]] static HRESULT s_GetAvailableConsoles(std::vector& consoles) noexcept; [[nodiscard]] static HRESULT s_GetAvailableTerminals(std::vector& terminals) noexcept; - [[nodiscard]] static HRESULT s_SetConsole(const DelegationConsole& console) noexcept; - [[nodiscard]] static HRESULT s_SetTerminal(const DelegationTerminal& terminal) noexcept; + [[nodiscard]] static HRESULT s_SetConsole(const IID& iid) noexcept; + [[nodiscard]] static HRESULT s_SetTerminal(const IID& iid) noexcept; [[nodiscard]] static HRESULT s_GetConsole(IID& iid) noexcept; [[nodiscard]] static HRESULT s_GetTerminal(IID& iid) noexcept; From 11401f20a1f686b8f4490dd43c49e41d09da79ed Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 3 Mar 2021 15:56:18 -0800 Subject: [PATCH 37/80] Fix dev build manifest clsids --- src/cascadia/CascadiaPackage/Package-Dev.appxmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index 366525192cf..631af36748a 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -92,7 +92,7 @@ Description="Terminal host built from microsoft/terminal open source repository" PublicFolder="Public"> - {E7B98685-0CC0-45D6-8F4C-B7C863C03DE2} + {051F34EE-C1FD-4B19-AF75-9BA54648434C} From f3c62fd6cd7e594d33cdb0550ac084f429a716f3 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 10:38:52 -0800 Subject: [PATCH 38/80] Consolidate switcher options to one option. --- src/host/srvinit.cpp | 8 +-- src/propsheet/TerminalPropsheetPage.cpp | 39 +++-------- src/propsheet/console.cpp | 10 +-- src/propsheet/console.rc | 14 +--- src/propsheet/dialogs.h | 1 - src/propsheet/globals.cpp | 7 +- src/propsheet/globals.h | 6 +- src/propslib/DelegationConfig.cpp | 91 ++++++++++++++++++++++--- src/propslib/DelegationConfig.hpp | 64 +++++++++++++++-- 9 files changed, 163 insertions(+), 77 deletions(-) diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index f0c4c49705a..80ed0db269d 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -58,11 +58,11 @@ try if (SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(isEnabled) && isEnabled)) { IID delegationClsid; - if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) + if (SUCCEEDED(DelegationConfig::s_GetDefaultConsoleId(delegationClsid))) { Globals.handoffConsoleClsid = delegationClsid; } - if (SUCCEEDED(DelegationConfig::s_GetTerminal(delegationClsid))) + if (SUCCEEDED(DelegationConfig::s_GetDefaultTerminalId(delegationClsid))) { Globals.handoffTerminalClsid = delegationClsid; } @@ -322,11 +322,11 @@ try g.handoffTarget = true; IID delegationClsid; - if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid))) + if (SUCCEEDED(DelegationConfig::s_GetDefaultConsoleId(delegationClsid))) { g.handoffConsoleClsid = delegationClsid; } - if (SUCCEEDED(DelegationConfig::s_GetTerminal(delegationClsid))) + if (SUCCEEDED(DelegationConfig::s_GetDefaultTerminalId(delegationClsid))) { g.handoffTerminalClsid = delegationClsid; } diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index 82eedbc289a..bdf82d03cb0 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -88,11 +88,10 @@ void _UpdateTextAndScroll(const HWND hDlg, SendDlgItemMessage(hDlg, scrollItem, UDM_SETPOS, 0, MAKELONG(value, 0)); } -template void _PrepDefAppCombo(const HWND hDlg, const int dlgItem, - const std::vector& list, - const IID selected, + const std::vector& list, + const DelegationConfig::DelegationPackage& selected, const bool enabled) { HWND hCombo = GetDlgItem(hDlg, dlgItem); @@ -102,9 +101,9 @@ void _PrepDefAppCombo(const HWND hDlg, for (DWORD i = 0; i < gsl::narrow(list.size()); ++i) { auto& item = list[i]; - ComboBox_AddString(hCombo, item.name.c_str()); - ComboBox_SetItemData(hCombo, i, &item.clsid); - if (selected == item.clsid) + ComboBox_AddString(hCombo, item.terminal.name.c_str()); + ComboBox_SetItemData(hCombo, i, &item); + if (selected == item) { selectedIndex = i; } @@ -214,14 +213,8 @@ bool InitTerminalDialog(const HWND hDlg) noexcept _PrepDefAppCombo(hDlg, IDD_TERMINAL_COMBO_DEFTERM, - g_availableTerminals, - g_selectedTerminal, - g_defAppEnabled); - - _PrepDefAppCombo(hDlg, - IDD_TERMINAL_COMBO_DEFCON, - g_availableConsoles, - g_selectedConsole, + g_availablePackages, + g_selectedPackage, g_defAppEnabled); return true; @@ -398,22 +391,8 @@ bool TerminalDlgCommand(const HWND hDlg, const WORD item, const WORD command) no DWORD comboItem = ComboBox_GetCurSel(hCombo); if (CB_ERR != comboItem) { - auto pClsid = reinterpret_cast(ComboBox_GetItemData(hCombo, comboItem)); - g_selectedTerminal = *pClsid; - } - } - break; - } - case IDD_TERMINAL_COMBO_DEFCON: - { - if (CBN_SELCHANGE == command) - { - HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFCON); - DWORD comboItem = ComboBox_GetCurSel(hCombo); - if (CB_ERR != comboItem) - { - auto pClsid = reinterpret_cast(ComboBox_GetItemData(hCombo, comboItem)); - g_selectedConsole = *pClsid; + auto pPackage = reinterpret_cast(ComboBox_GetItemData(hCombo, comboItem)); + g_selectedPackage = *pPackage; } } break; diff --git a/src/propsheet/console.cpp b/src/propsheet/console.cpp index e7f940ad69c..2eb0507a0f9 100644 --- a/src/propsheet/console.cpp +++ b/src/propsheet/console.cpp @@ -98,8 +98,7 @@ void SaveConsoleSettingsIfNeeded(const HWND hwnd) if (g_defAppEnabled) { - LOG_IF_FAILED(DelegationConfig::s_SetTerminal(g_selectedTerminal)); - LOG_IF_FAILED(DelegationConfig::s_SetConsole(g_selectedConsole)); + LOG_IF_FAILED(DelegationConfig::s_SetDefaultByPackage(g_selectedPackage)); } if (gpStateInfo->LinkTitle != nullptr) @@ -621,15 +620,12 @@ INT_PTR ConsolePropertySheet(__in HWND hWnd, __in PCONSOLE_STATE_INFO pStateInfo RecreateFontHandles(hWnd); // - // Find the available default consoles/terminals + // Find the available default console/terminal packages // if (SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(g_defAppEnabled)) && g_defAppEnabled) { - LOG_IF_FAILED(DelegationConfig::s_GetAvailableTerminals(g_availableTerminals)); - LOG_IF_FAILED(DelegationConfig::s_GetTerminal(g_selectedTerminal)); - LOG_IF_FAILED(DelegationConfig::s_GetAvailableConsoles(g_availableConsoles)); - LOG_IF_FAILED(DelegationConfig::s_GetTerminal(g_selectedConsole)); + LOG_IF_FAILED(DelegationConfig::s_GetAvailablePackages(g_availablePackages, g_selectedPackage)); } // diff --git a/src/propsheet/console.rc b/src/propsheet/console.rc index 00972ac8971..460b6f43712 100644 --- a/src/propsheet/console.rc +++ b/src/propsheet/console.rc @@ -538,18 +538,13 @@ END #define T_DEFAPP_X T_CCOLOR_X #define T_DEFAPP_Y T_SCROLL_Y #define T_DEFAPP_W T_CCOLOR_W -#define T_DEFAPP_H 54 +#define T_DEFAPP_H T_SCROLL_H #define T_DEFTERM_X (T_DEFAPP_X+P_1) #define T_DEFTERM_Y (T_DEFAPP_Y+P_2) #define T_DEFTERM_W (T_DEFAPP_W-P_4-P_4) #define T_DEFTERM_H 25 -#define T_DEFCON_X T_DEFTERM_X -#define T_DEFCON_Y (T_DEFTERM_Y+P_4+P_4+P_0+P_0) -#define T_DEFCON_W T_DEFTERM_W -#define T_DEFCON_H T_DEFTERM_H - #define UPDOWN_STYLES (UDS_AUTOBUDDY | UDS_SETBUDDYINT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_ALIGNRIGHT) DID_TERMINAL DIALOG 0, 0, 245, 226 CAPTION " Terminal " @@ -636,11 +631,8 @@ BEGIN GROUPBOX "Terminal Scrolling", -1, T_SCROLL_X, T_SCROLL_Y, T_SCROLL_W, T_SCROLL_H AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10 - GROUPBOX "Default Launch Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H - LTEXT "Terminal Window", -1, T_DEFTERM_X, T_DEFTERM_Y, T_DEFTERM_W, T_DEFTERM_H - COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y+P_2, T_DEFTERM_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "Console Engine", -1, T_DEFCON_X, T_DEFCON_Y, T_DEFCON_W, T_DEFCON_H - COMBOBOX IDD_TERMINAL_COMBO_DEFCON, T_DEFCON_X+P_1, T_DEFCON_Y+P_2, T_DEFCON_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + GROUPBOX "Default Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H + COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y, T_DEFTERM_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Find out more about experimental terminal settings", IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10 diff --git a/src/propsheet/dialogs.h b/src/propsheet/dialogs.h index 1aaeb24dd89..ffa52c3e605 100644 --- a/src/propsheet/dialogs.h +++ b/src/propsheet/dialogs.h @@ -165,7 +165,6 @@ Revision History: #define IDD_TERMINAL_CURSOR_BLUE 631 #define IDD_HELP_TERMINAL 632 #define IDD_TERMINAL_COMBO_DEFTERM 640 -#define IDD_TERMINAL_COMBO_DEFCON 641 #define BM_TRUETYPE_ICON 1000 diff --git a/src/propsheet/globals.cpp b/src/propsheet/globals.cpp index 89aef20cc63..e42d0bbf4f6 100644 --- a/src/propsheet/globals.cpp +++ b/src/propsheet/globals.cpp @@ -61,8 +61,5 @@ HWND g_hTerminalDlg = static_cast(INVALID_HANDLE_VALUE); HWND g_hOptionsDlg = static_cast(INVALID_HANDLE_VALUE); bool g_defAppEnabled = false; -std::vector g_availableConsoles; -std::vector g_availableTerminals; -CLSID g_selectedConsole; -CLSID g_selectedTerminal; - +std::vector g_availablePackages; +DelegationConfig::DelegationPackage g_selectedPackage; diff --git a/src/propsheet/globals.h b/src/propsheet/globals.h index 65d3b34fbe3..1ecfb407e31 100644 --- a/src/propsheet/globals.h +++ b/src/propsheet/globals.h @@ -57,7 +57,5 @@ extern HWND g_hTerminalDlg; extern HWND g_hOptionsDlg; extern bool g_defAppEnabled; -extern std::vector g_availableConsoles; -extern std::vector g_availableTerminals; -extern CLSID g_selectedConsole; -extern CLSID g_selectedTerminal; +extern std::vector g_availablePackages; +extern DelegationConfig::DelegationPackage g_selectedPackage; diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index dba3f2fcc49..4e829ee2106 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -33,7 +33,7 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept { vec.clear(); - T useInbox; + T useInbox = { 0 }; useInbox.clsid = { 0 }; useInbox.name = L"Windows Console Host"; useInbox.author = L"Microsoft Corporation"; @@ -72,18 +72,25 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept HString publisherId; RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf())); - // PackageId.Name HString name; RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf())); - extensionMetadata.name = std::wstring{ name.GetRawBuffer(nullptr) }; - // PackageId.Version HString publisher; RETURN_IF_FAILED(extensionPackageId->get_Publisher(publisher.GetAddressOf())); - extensionMetadata.author = std::wstring{ publisher.GetRawBuffer(nullptr) }; + HString pfn; + RETURN_IF_FAILED(extensionPackageId->get_FamilyName(pfn.GetAddressOf())); + extensionMetadata.pfn = std::wstring{ pfn.GetRawBuffer(nullptr) }; + + PackageVersion version; + RETURN_IF_FAILED(extensionPackageId->get_Version(&version)); + extensionMetadata.version.major = version.Major; + extensionMetadata.version.minor = version.Minor; + extensionMetadata.version.build = version.Build; + extensionMetadata.version.revision = version.Revision; + // Fetch the custom properties XML out of the extension information ComPtr> propertiesOperation; RETURN_IF_FAILED(extension->GetExtensionPropertiesAsync(&propertiesOperation)); @@ -156,23 +163,89 @@ try } CATCH_RETURN() -[[nodiscard]] HRESULT DelegationConfig::s_SetConsole(const IID& iid) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_GetAvailablePackages(std::vector& packages, DelegationPackage& defPackage) noexcept +try +{ + packages.clear(); + + std::vector consoles; + RETURN_IF_FAILED(s_GetAvailableConsoles(consoles)); + + std::vector terminals; + RETURN_IF_FAILED(s_GetAvailableTerminals(terminals)); + + // TODO: I hate this algorithm (it's bad performance), but I couldn't + // find an AppModel interface that would let me look up all the extensions + // in one package. + for (auto& term : terminals) + { + for (auto& con : consoles) + { + if (term.IsFromSamePackage(con)) + { + DelegationPackage pkg; + pkg.terminal = term; + pkg.console = con; + packages.push_back(pkg); + break; + } + } + } + + // We should find at least one package. + RETURN_HR_IF(E_FAIL, packages.empty()); + + // We also find the default here while we have the list of available ones so + // we can return the opaque structure instead of the raw IID. + IID defCon; + RETURN_IF_FAILED(s_GetDefaultConsoleId(defCon)); + IID defTerm; + RETURN_IF_FAILED(s_GetDefaultTerminalId(defTerm)); + + // The default one is the 0th one because that's supposed to be the inbox conhost one. + DelegationPackage chosenPackage = packages.at(0); + + // Search through and find a package that matches. If we failed to match because + // it's torn across multiple or something not in the catalog, we'll offer the inbox conhost one. + for (auto& pkg : packages) + { + if (pkg.console.clsid == defCon && pkg.terminal.clsid == defTerm) + { + chosenPackage = pkg; + break; + } + } + + defPackage = chosenPackage; + + return S_OK; +} +CATCH_RETURN() + +[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultConsoleById(const IID& iid) noexcept { return s_Set(DELEGATION_CONSOLE_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_SetTerminal(const IID& iid) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultTerminalById(const IID& iid) noexcept { return s_Set(DELEGATION_TERMINAL_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultByPackage(const DelegationPackage& package) noexcept +{ + RETURN_IF_FAILED(s_SetDefaultConsoleById(package.console.clsid)); + RETURN_IF_FAILED(s_SetDefaultTerminalById(package.terminal.clsid)); + return S_OK; +} + +[[nodiscard]] HRESULT DelegationConfig::s_GetDefaultConsoleId(IID& iid) noexcept { iid = {0}; return s_Get(DELEGATION_CONSOLE_KEY_NAME, iid); } -[[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) noexcept +[[nodiscard]] HRESULT DelegationConfig::s_GetDefaultTerminalId(IID& iid) noexcept { iid = {0}; return s_Get(DELEGATION_TERMINAL_KEY_NAME, iid); diff --git a/src/propslib/DelegationConfig.hpp b/src/propslib/DelegationConfig.hpp index 5e2562e8236..7522db64905 100644 --- a/src/propslib/DelegationConfig.hpp +++ b/src/propslib/DelegationConfig.hpp @@ -18,11 +18,46 @@ Author(s): class DelegationConfig { public: + struct PkgVersion + { + unsigned short major; + unsigned short minor; + unsigned short build; + unsigned short revision; + + bool operator==(const PkgVersion& other) const + { + return major == other.major && + minor == other.minor && + build == other.build && + revision == other.revision; + } + }; + struct DelegationBase { CLSID clsid; std::wstring name; std::wstring author; + std::wstring pfn; + PkgVersion version; + + bool IsFromSamePackage(const DelegationBase& other) const + { + return name == other.name && + author == other.author && + pfn == other.pfn && + version == other.version; + } + + bool operator==(const DelegationBase& other) const + { + return clsid == other.clsid && + name == other.name && + author == other.author && + pfn == other.pfn && + version == other.version; + } }; struct DelegationConsole : public DelegationBase @@ -33,16 +68,33 @@ class DelegationConfig { }; - [[nodiscard]] static HRESULT s_GetAvailableConsoles(std::vector& consoles) noexcept; - [[nodiscard]] static HRESULT s_GetAvailableTerminals(std::vector& terminals) noexcept; + struct DelegationPackage + { + DelegationConsole console; + DelegationTerminal terminal; + + bool operator==(const DelegationPackage& other) const + { + return console == other.console && + terminal == other.terminal; + } + }; + + + [[nodiscard]] static HRESULT s_GetAvailablePackages(std::vector& packages, DelegationPackage& default) noexcept; - [[nodiscard]] static HRESULT s_SetConsole(const IID& iid) noexcept; - [[nodiscard]] static HRESULT s_SetTerminal(const IID& iid) noexcept; + [[nodiscard]] static HRESULT s_SetDefaultByPackage(const DelegationPackage& pkg) noexcept; - [[nodiscard]] static HRESULT s_GetConsole(IID& iid) noexcept; - [[nodiscard]] static HRESULT s_GetTerminal(IID& iid) noexcept; + [[nodiscard]] static HRESULT s_GetDefaultConsoleId(IID& iid) noexcept; + [[nodiscard]] static HRESULT s_GetDefaultTerminalId(IID& iid) noexcept; private: + [[nodiscard]] static HRESULT s_GetAvailableConsoles(std::vector& consoles) noexcept; + [[nodiscard]] static HRESULT s_GetAvailableTerminals(std::vector& terminals) noexcept; + + [[nodiscard]] static HRESULT s_SetDefaultConsoleById(const IID& iid) noexcept; + [[nodiscard]] static HRESULT s_SetDefaultTerminalById(const IID& iid) noexcept; + [[nodiscard]] static HRESULT s_Get(PCWSTR value, IID& iid) noexcept; [[nodiscard]] static HRESULT s_Set(PCWSTR value, const CLSID clsid) noexcept; }; From c4117c8f551d802938fc5609e91628c8d8e60c98 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 10:54:51 -0800 Subject: [PATCH 39/80] Reduce 2x drop downs to 1 in Terminal. --- src/cascadia/TerminalSettingsEditor/Launch.cpp | 16 ---------------- src/cascadia/TerminalSettingsEditor/Launch.h | 4 ---- src/cascadia/TerminalSettingsEditor/Launch.idl | 3 --- src/cascadia/TerminalSettingsEditor/Launch.xaml | 9 --------- 4 files changed, 32 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/Launch.cpp b/src/cascadia/TerminalSettingsEditor/Launch.cpp index 4183fb46722..6ac4c4bfdde 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.cpp +++ b/src/cascadia/TerminalSettingsEditor/Launch.cpp @@ -53,20 +53,4 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { value; } - - Windows::Foundation::Collections::IObservableVector Launch::DefaultConsoles() - { - Windows::Foundation::Collections::IObservableVector vec; - return vec; - } - - IInspectable Launch::CurrentDefaultConsole() - { - return nullptr; - } - - void Launch::CurrentDefaultConsole(const IInspectable& value) - { - value; - } } diff --git a/src/cascadia/TerminalSettingsEditor/Launch.h b/src/cascadia/TerminalSettingsEditor/Launch.h index e4cf8d47391..7be2d662626 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.h +++ b/src/cascadia/TerminalSettingsEditor/Launch.h @@ -32,10 +32,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation IInspectable CurrentDefaultTerminal(); void CurrentDefaultTerminal(const IInspectable& value); - Windows::Foundation::Collections::IObservableVector DefaultConsoles(); - IInspectable CurrentDefaultConsole(); - void CurrentDefaultConsole(const IInspectable& value); - GETSET_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 1d8a432cd1e..62e6ba9292f 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.idl +++ b/src/cascadia/TerminalSettingsEditor/Launch.idl @@ -20,9 +20,6 @@ namespace Microsoft.Terminal.Settings.Editor IInspectable CurrentDefaultTerminal; IObservableVector DefaultTerminals { get; }; - IInspectable CurrentDefaultConsole; - IObservableVector DefaultConsoles { get; }; - IInspectable CurrentLaunchMode; IObservableVector LaunchModeList { get; }; diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml index 0a5176cc1db..ba1a1ac1447 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -76,15 +76,6 @@ the MIT License. See LICENSE in the project root for license information. --> - - - - - - From df665dce1e4b9926292fd73aaa28eec1ba8015ea Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 11:02:42 -0800 Subject: [PATCH 40/80] Use display name instead of package identity name. --- src/propslib/DelegationConfig.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 4e829ee2106..16d61f0bce4 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -66,6 +66,9 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept ComPtr extensionPackage; RETURN_IF_FAILED(extension->get_Package(&extensionPackage)); + ComPtr extensionPackage2; + RETURN_IF_FAILED(extensionPackage.As(&extensionPackage2)); + ComPtr extensionPackageId; RETURN_IF_FAILED(extensionPackage->get_Id(&extensionPackageId)); @@ -73,11 +76,11 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf())); HString name; - RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf())); + RETURN_IF_FAILED(extensionPackage2->get_DisplayName(name.GetAddressOf())); extensionMetadata.name = std::wstring{ name.GetRawBuffer(nullptr) }; HString publisher; - RETURN_IF_FAILED(extensionPackageId->get_Publisher(publisher.GetAddressOf())); + RETURN_IF_FAILED(extensionPackage2->get_PublisherDisplayName(publisher.GetAddressOf())); extensionMetadata.author = std::wstring{ publisher.GetRawBuffer(nullptr) }; HString pfn; From 205c71aeab211550e0e39f0634372151bc58b928 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 11:29:13 -0800 Subject: [PATCH 41/80] Handful of PR feedback. --- OpenConsole.sln | 1 + .../TerminalConnection/CTerminalHandoff.cpp | 2 +- .../TerminalConnection/CTerminalHandoff.h | 6 +++--- src/host/exe/CConsoleHandoff.cpp | 7 +++++-- src/host/exe/CConsoleHandoff.h | 16 ++++++++++++++++ src/host/exe/sources | 2 +- src/host/proxy/ITerminalHandoff.idl | 6 +++--- src/host/srvinit.cpp | 8 ++++---- src/host/srvinit.h | 8 ++++---- 9 files changed, 38 insertions(+), 18 deletions(-) diff --git a/OpenConsole.sln b/OpenConsole.sln index 1662ce0bde0..42674c4cb4d 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -66,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 diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 28889c259aa..fa338d22b53 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -71,7 +71,7 @@ HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept return S_OK; } -HRESULT CTerminalHandoff::EstablishHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept +HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept { // Duplicate the handles from what we received. // The contract with COM specifies that any HANDLEs we receive from the caller belong diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 3f522d74449..d3e3b6dbc2a 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -18,9 +18,9 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) CTerminalHandoff : public RuntimeClass, ITerminalHandoff> { #pragma region ITerminalHandoff - STDMETHODIMP EstablishHandoff(HANDLE in, - HANDLE out, - HANDLE signal) noexcept override; + STDMETHODIMP EstablishPtyHandoff(HANDLE in, + HANDLE out, + HANDLE signal) noexcept override; #pragma endregion diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index c054f09757f..1fd63c1b1e5 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + #include "precomp.h" #include "CConsoleHandoff.h" @@ -12,7 +15,7 @@ // - out - Where to place the duplicated value // Return Value: // - S_OK or Win32 error from `::DuplicateHandle` -HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) +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; @@ -35,7 +38,7 @@ try // 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; + CONSOLE_API_MSG apiMsg{}; apiMsg.Descriptor.Identifier.HighPart = msg->IdHighPart; apiMsg.Descriptor.Identifier.LowPart = msg->IdLowPart; apiMsg.Descriptor.Process = msg->Process; diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h index aa544d7ece3..cfd227e59d1 100644 --- a/src/host/exe/CConsoleHandoff.h +++ b/src/host/exe/CConsoleHandoff.h @@ -1,3 +1,19 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- CConsoleHandoff.hpp + +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" diff --git a/src/host/exe/sources b/src/host/exe/sources index a827864473d..2b1dc234329 100644 --- a/src/host/exe/sources +++ b/src/host/exe/sources @@ -32,7 +32,7 @@ CETCOMPAT=1 SOURCES = \ $(SOURCES) \ - ..\exemain.cpp \ + .\exemain.cpp \ ..\res.rc \ # ------------------------------------- diff --git a/src/host/proxy/ITerminalHandoff.idl b/src/host/proxy/ITerminalHandoff.idl index 1a6af5b3699..4d50c810fae 100644 --- a/src/host/proxy/ITerminalHandoff.idl +++ b/src/host/proxy/ITerminalHandoff.idl @@ -9,7 +9,7 @@ import "ocidl.idl"; uuid(FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74) ] interface ITerminalHandoff : IUnknown { - HRESULT EstablishHandoff([in, system_handle(sh_pipe)] HANDLE in, - [in, system_handle(sh_pipe)] HANDLE out, - [in, system_handle(sh_pipe)] HANDLE signal); + HRESULT EstablishPtyHandoff([in, system_handle(sh_pipe)] HANDLE in, + [in, system_handle(sh_pipe)] HANDLE out, + [in, system_handle(sh_pipe)] HANDLE signal); }; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 80ed0db269d..8de666d98c7 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -312,7 +312,7 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, return S_OK; } -HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, +[[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage) @@ -364,9 +364,9 @@ try RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff))); - RETURN_IF_FAILED(handoff->EstablishHandoff(inPipeTheirSide.get(), - outPipeTheirSide.get(), - signalPipeTheirSide.get())); + RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(), + outPipeTheirSide.get(), + signalPipeTheirSide.get())); inPipeTheirSide.release(); outPipeTheirSide.release(); diff --git a/src/host/srvinit.h b/src/host/srvinit.h index 5eae88c2192..4e479444fa5 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -28,9 +28,9 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, [[nodiscard]] bool ConsoleConnectionDeservesVisibleWindow(PCONSOLE_API_CONNECTINFO p); -HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, - HANDLE driverInputEvent, - PCONSOLE_API_MSG connectMessage); +[[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, + const ConsoleArguments* const args, + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage); void ConsoleCheckDebug(); From bdf819e78e1993bf435787e5d372d5fae9c4029f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 11:34:17 -0800 Subject: [PATCH 42/80] spell check --- .github/actions/spelling/dictionary/apis.txt | 1 + .github/actions/spelling/expect/expect.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/actions/spelling/dictionary/apis.txt b/.github/actions/spelling/dictionary/apis.txt index 9c7f9097348..ef50b061a9c 100644 --- a/.github/actions/spelling/dictionary/apis.txt +++ b/.github/actions/spelling/dictionary/apis.txt @@ -93,6 +93,7 @@ sregex STDCPP strchr STDMETHOD +Stubless Subheader Subpage UPDATEINIFILE diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 614bbac803b..0179a67aa63 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -178,7 +178,7 @@ BOTTOMLEFT BOTTOMRIGHT boutput BPBF -bpp +7bpp BPPF branchconfig BRK @@ -564,12 +564,14 @@ DECSWL DECTCEM Dedupe deduplicated +DEFAPP DEFAULTBACKGROUND DEFAULTFOREGROUND defaultsettings DEFAULTTONEAREST DEFAULTTONULL DEFAULTTOPRIMARY +DEFCON defectdefs DEFERERASE deff From cfbc4aea1a40b62158394468728d3700b883b6f8 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 11:39:57 -0800 Subject: [PATCH 43/80] code format! --- src/cascadia/TerminalConnection/CTerminalHandoff.h | 4 ++-- src/host/srvinit.cpp | 6 +++--- src/propsheet/TerminalPropsheetPage.cpp | 2 +- src/propslib/DelegationConfig.cpp | 5 ++--- src/propslib/DelegationConfig.hpp | 1 - 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index d3e3b6dbc2a..d171df16012 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -19,8 +19,8 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) { #pragma region ITerminalHandoff STDMETHODIMP EstablishPtyHandoff(HANDLE in, - HANDLE out, - HANDLE signal) noexcept override; + HANDLE out, + HANDLE signal) noexcept override; #pragma endregion diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 8de666d98c7..53cebfe1367 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -313,9 +313,9 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, } [[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... - HANDLE driverInputEvent, - PCONSOLE_API_MSG connectMessage) + const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... + HANDLE driverInputEvent, + PCONSOLE_API_MSG connectMessage) try { auto& g = ServiceLocator::LocateGlobals(); diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index bdf82d03cb0..be9087bb774 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -211,7 +211,7 @@ bool InitTerminalDialog(const HWND hDlg) noexcept CheckDlgButton(hDlg, IDD_DISABLE_SCROLLFORWARD, gpStateInfo->TerminalScrolling); - _PrepDefAppCombo(hDlg, + _PrepDefAppCombo(hDlg, IDD_TERMINAL_COMBO_DEFTERM, g_availablePackages, g_selectedPackage, diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 16d61f0bce4..4cbfe5d22c1 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -244,13 +244,13 @@ CATCH_RETURN() [[nodiscard]] HRESULT DelegationConfig::s_GetDefaultConsoleId(IID& iid) noexcept { - iid = {0}; + iid = { 0 }; return s_Get(DELEGATION_CONSOLE_KEY_NAME, iid); } [[nodiscard]] HRESULT DelegationConfig::s_GetDefaultTerminalId(IID& iid) noexcept { - iid = {0}; + iid = { 0 }; return s_Get(DELEGATION_TERMINAL_KEY_NAME, iid); } @@ -288,7 +288,6 @@ CATCH_RETURN() reinterpret_cast(buffer.get()), &bytesUsed)); - RETURN_IF_FAILED(IIDFromString(buffer.get(), &iid)); return S_OK; diff --git a/src/propslib/DelegationConfig.hpp b/src/propslib/DelegationConfig.hpp index 7522db64905..9bc4ad89bb7 100644 --- a/src/propslib/DelegationConfig.hpp +++ b/src/propslib/DelegationConfig.hpp @@ -80,7 +80,6 @@ class DelegationConfig } }; - [[nodiscard]] static HRESULT s_GetAvailablePackages(std::vector& packages, DelegationPackage& default) noexcept; [[nodiscard]] static HRESULT s_SetDefaultByPackage(const DelegationPackage& pkg) noexcept; From 18ab9ec7b3cbfca611387508c76f6a679cb7c91f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 11:47:19 -0800 Subject: [PATCH 44/80] SPELL CHECK!!!! --- .github/actions/spelling/expect/expect.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 0179a67aa63..e86e8b076d5 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -178,6 +178,7 @@ BOTTOMLEFT BOTTOMRIGHT boutput BPBF +bpp 7bpp BPPF branchconfig From 5379a5e1dd6a83d87eeccdd8013804c86bcb66d2 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 12:32:06 -0800 Subject: [PATCH 45/80] Turn off drop down for defterm atm. --- src/cascadia/TerminalSettingsEditor/Launch.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml index ba1a1ac1447..eed1b603916 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -70,6 +70,7 @@ the MIT License. See LICENSE in the project root for license information. --> From 31a2b540bd21e8bff2b77dd24b1d614d10173bf6 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 13:10:55 -0800 Subject: [PATCH 46/80] do cast for x86 --- src/host/exe/CConsoleHandoff.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 1fd63c1b1e5..452d35711e1 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -41,8 +41,8 @@ try CONSOLE_API_MSG apiMsg{}; apiMsg.Descriptor.Identifier.HighPart = msg->IdHighPart; apiMsg.Descriptor.Identifier.LowPart = msg->IdLowPart; - apiMsg.Descriptor.Process = msg->Process; - apiMsg.Descriptor.Object = msg->Object; + 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; From 4e6ed5857ca2981b590d034817fa08e59bce6422 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 13:37:42 -0800 Subject: [PATCH 47/80] pass through client process handle. --- src/cascadia/TerminalConnection/CTerminalHandoff.cpp | 5 +++-- src/cascadia/TerminalConnection/CTerminalHandoff.h | 5 +++-- src/cascadia/TerminalConnection/ConptyConnection.cpp | 8 +++++--- src/cascadia/TerminalConnection/ConptyConnection.h | 5 +++-- src/host/exe/CConsoleHandoff.cpp | 2 +- src/host/proxy/ITerminalHandoff.idl | 5 +++-- src/host/srvinit.cpp | 6 +++++- 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index fa338d22b53..255cbd953e8 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -71,7 +71,7 @@ HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept return S_OK; } -HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept +HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept { // Duplicate the handles from what we received. // The contract with COM specifies that any HANDLEs we receive from the caller belong @@ -80,7 +80,8 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign 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); + return _pfnHandoff(in, out, signal, process); } diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index d171df16012..36b6b5666d0 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -12,7 +12,7 @@ using namespace Microsoft::WRL; -typedef HRESULT (*NewHandoff)(HANDLE, HANDLE, HANDLE); +typedef HRESULT (*NewHandoff)(HANDLE, HANDLE, HANDLE, HANDLE); struct __declspec(uuid(__CLSID_CTerminalHandoff)) CTerminalHandoff : public RuntimeClass, ITerminalHandoff> @@ -20,7 +20,8 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) #pragma region ITerminalHandoff STDMETHODIMP EstablishPtyHandoff(HANDLE in, HANDLE out, - HANDLE signal) noexcept override; + HANDLE signal, + HANDLE process) noexcept override; #pragma endregion diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 96113cdcc63..2fc7e660931 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -193,7 +193,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation ConptyConnection::ConptyConnection(const uint64_t hSig, const uint64_t hIn, - const uint64_t hOut) : + const uint64_t hOut, + const uint64_t hClientProcess) : _initialRows{ 25 }, _initialCols{ 80 }, _commandline{ L"" }, @@ -212,6 +213,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { _guid = Utils::CreateGuid(); } + _piClient.hProcess = reinterpret_cast(hClientProcess); } ConptyConnection::ConptyConnection(const hstring& commandline, @@ -483,10 +485,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation 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) noexcept + HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept try { - auto conn = winrt::make((uint64_t)signal, (uint64_t)in, (uint64_t)out); + auto conn = winrt::make((uint64_t)signal, (uint64_t)in, (uint64_t)out, (uint64_t)process); _newConnectionHandlers(conn); return S_OK; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 811adf69bb8..693122872ac 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -21,7 +21,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { ConptyConnection(const uint64_t hSig, const uint64_t hIn, - const uint64_t hOut); + const uint64_t hOut, + const uint64_t hClientProcess); ConptyConnection( const hstring& cmdline, @@ -53,7 +54,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation void _indicateExitWithStatus(unsigned int status) noexcept; void _ClientTerminated() noexcept; - static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal) noexcept; + static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept; uint32_t _initialRows{}; uint32_t _initialCols{}; diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 452d35711e1..49741a4826a 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -42,7 +42,7 @@ try 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.Object = static_cast(msg->Object); apiMsg.Descriptor.Function = msg->Function; apiMsg.Descriptor.InputSize = msg->InputSize; apiMsg.Descriptor.OutputSize = msg->OutputSize; diff --git a/src/host/proxy/ITerminalHandoff.idl b/src/host/proxy/ITerminalHandoff.idl index 4d50c810fae..79c356908ba 100644 --- a/src/host/proxy/ITerminalHandoff.idl +++ b/src/host/proxy/ITerminalHandoff.idl @@ -10,6 +10,7 @@ import "ocidl.idl"; ] 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_pipe)] HANDLE out, + [in, system_handle(sh_pipe)] HANDLE signal, + [in, system_handle(sh_process)] HANDLE client); }; diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 53cebfe1367..516531d2e2c 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -360,13 +360,17 @@ try 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())); + signalPipeTheirSide.get(), + clientProcess.get())); inPipeTheirSide.release(); outPipeTheirSide.release(); From c66966cf57c7582f4cf58cb084f9004520d31356 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 13:39:10 -0800 Subject: [PATCH 48/80] Drop unused console arguments. --- src/host/exe/CConsoleHandoff.cpp | 6 +----- src/host/srvinit.cpp | 13 ++++--------- src/host/srvinit.h | 1 - 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/host/exe/CConsoleHandoff.cpp b/src/host/exe/CConsoleHandoff.cpp index 49741a4826a..20ac3c6e806 100644 --- a/src/host/exe/CConsoleHandoff.cpp +++ b/src/host/exe/CConsoleHandoff.cpp @@ -54,12 +54,8 @@ try RETURN_IF_FAILED(_duplicateHandle(server, server)); RETURN_IF_FAILED(_duplicateHandle(inputEvent, inputEvent)); - // Build a console arguments structure that contains all information on how the - // original console was started. - ConsoleArguments consoleArgs; - // Now perform the handoff. - RETURN_IF_FAILED(ConsoleEstablishHandoff(server, &consoleArgs, inputEvent, &apiMsg)); + RETURN_IF_FAILED(ConsoleEstablishHandoff(server, inputEvent, &apiMsg)); return S_OK; } diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 516531d2e2c..471d2f58825 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -313,7 +313,6 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, } [[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, // this can't stay like this because ConsoleArguments could change... HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage) try @@ -376,16 +375,12 @@ try outPipeTheirSide.release(); signalPipeTheirSide.release(); - auto originalCommandLine = args->GetOriginalCommandLine(); + const auto commandLine = fmt::format(L" --headless --signal {:#x}", (int64_t)signalPipeOurSide.release()); - auto str2 = fmt::format(L" --headless --signal {:#x}", (int64_t)signalPipeOurSide.release()); + ConsoleArguments consoleArgs(commandLine, inPipeOurSide.release(), outPipeOurSide.release()); + RETURN_IF_FAILED(consoleArgs.ParseCommandline()); - originalCommandLine = originalCommandLine.append(str2); - - ConsoleArguments args2(originalCommandLine, inPipeOurSide.release(), outPipeOurSide.release()); - RETURN_IF_FAILED(args2.ParseCommandline()); - - return ConsoleCreateIoThread(Server, &args2, driverInputEvent, connectMessage); + return ConsoleCreateIoThread(Server, &consoleArgs, driverInputEvent, connectMessage); } CATCH_RETURN() diff --git a/src/host/srvinit.h b/src/host/srvinit.h index 4e479444fa5..3b2725a390e 100644 --- a/src/host/srvinit.h +++ b/src/host/srvinit.h @@ -29,7 +29,6 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand, [[nodiscard]] bool ConsoleConnectionDeservesVisibleWindow(PCONSOLE_API_CONNECTINFO p); [[nodiscard]] HRESULT ConsoleEstablishHandoff(_In_ HANDLE Server, - const ConsoleArguments* const args, HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage); From d1603d62323be6370a53f8578e589a0a9f77e7b5 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 13:42:46 -0800 Subject: [PATCH 49/80] remove extraneous except thing... dunno how I did that. --- .github/actions/spelling/expect/expect.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index e86e8b076d5..43e27209ae0 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -179,7 +179,6 @@ BOTTOMRIGHT boutput BPBF bpp -7bpp BPPF branchconfig BRK From c6714ce2f0c042e6ada048692ac52b13eda93743 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 13:48:20 -0800 Subject: [PATCH 50/80] remove comment. I don't want to run into a trap here. --- src/cascadia/TerminalConnection/CTerminalHandoff.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 255cbd953e8..c8cea60dc7d 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -19,7 +19,6 @@ try { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); - // We could probably hold this in a static... auto classFactory = Make>(); RETURN_IF_NULL_ALLOC(classFactory); From 9d6fcbe59d5350a5c27b2d9de2dfd9f24cf910e6 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 14:15:59 -0800 Subject: [PATCH 51/80] Use localizable resource for inbox console host. --- src/propsheet/TerminalPropsheetPage.cpp | 13 ++++++++++++- src/propsheet/console.h | 1 + src/propsheet/console.rc | 3 ++- src/propslib/DelegationConfig.cpp | 5 +++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index be9087bb774..bc760494eab 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -7,6 +7,7 @@ #include "ColorControl.h" #include #include "../propslib/DelegationConfig.hpp" +#include "../types/inc/User32Utils.hpp" // From conattrs.h const COLORREF INVALID_COLOR = 0xffffffff; @@ -101,7 +102,17 @@ void _PrepDefAppCombo(const HWND hDlg, for (DWORD i = 0; i < gsl::narrow(list.size()); ++i) { auto& item = list[i]; - ComboBox_AddString(hCombo, item.terminal.name.c_str()); + + // An empty CLSID is a sentinel for the inbox console. + if (item.terminal.clsid == CLSID{ 0 }) + { + const auto name = GetStringResource(IDS_TERMINAL_DEF_INBOX); + ComboBox_AddString(hCombo, name.c_str()); + } + else + { + ComboBox_AddString(hCombo, item.terminal.name.c_str()); + } ComboBox_SetItemData(hCombo, i, &item); if (selected == item) { diff --git a/src/propsheet/console.h b/src/propsheet/console.h index db33428a373..5eb7e91a01f 100644 --- a/src/propsheet/console.h +++ b/src/propsheet/console.h @@ -58,6 +58,7 @@ Revision History: // unused 16 #define IDS_TOOLTIP_OPACITY 17 #define IDS_TOOLTIP_INTERCEPT_COPY_PASTE 18 +#define IDS_TERMINAL_DEF_INBOX 19 // clang-format on void MakeAltRasterFont( diff --git a/src/propsheet/console.rc b/src/propsheet/console.rc index 460b6f43712..5d888c17baf 100644 --- a/src/propsheet/console.rc +++ b/src/propsheet/console.rc @@ -632,7 +632,7 @@ BEGIN AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10 GROUPBOX "Default Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H - COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_1, T_DEFTERM_Y, T_DEFTERM_W-P_4, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_0, T_DEFTERM_Y, T_DEFTERM_W, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Find out more about experimental terminal settings", IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10 @@ -660,6 +660,7 @@ BEGIN IDS_TOOLTIP_EDIT_KEYS, "Enable enhanced keyboard editing on command line." IDS_TOOLTIP_OPACITY, "Adjust the transparency of the console window." IDS_TOOLTIP_INTERCEPT_COPY_PASTE, "Use Ctrl+Shift+C/V as copy/paste shortcuts, regardless of input mode" + IDS_TERMINAL_DEF_INBOX, "Windows Console Host" END diff --git a/src/propslib/DelegationConfig.cpp b/src/propslib/DelegationConfig.cpp index 4cbfe5d22c1..6a6f8ae9221 100644 --- a/src/propslib/DelegationConfig.cpp +++ b/src/propslib/DelegationConfig.cpp @@ -35,8 +35,9 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector& vec) noexcept T useInbox = { 0 }; useInbox.clsid = { 0 }; - useInbox.name = L"Windows Console Host"; - useInbox.author = L"Microsoft Corporation"; + // CLSID of 0 will be sentinel to say "inbox console" or something. + // The UI displaying this information will have to go look up appropriate strings + // to convey that message. vec.push_back(useInbox); From 66b433d3942c980fa8b404189f34ebb07b921a19 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 4 Mar 2021 14:18:09 -0800 Subject: [PATCH 52/80] Add cconsolehandoff.cpp to sources so it builds inbox. --- src/host/exe/sources | 1 + 1 file changed, 1 insertion(+) diff --git a/src/host/exe/sources b/src/host/exe/sources index 2b1dc234329..1071fdb5c1f 100644 --- a/src/host/exe/sources +++ b/src/host/exe/sources @@ -32,6 +32,7 @@ CETCOMPAT=1 SOURCES = \ $(SOURCES) \ + .\CConsoleHandoff.cpp \ .\exemain.cpp \ ..\res.rc \ From e804de35aa44c9d138923a6b20ab723d552156f5 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 5 Mar 2021 11:35:47 -0800 Subject: [PATCH 53/80] Do not show propsheet dropdown if the feature is off. --- src/propsheet/TerminalPropsheetPage.cpp | 11 +-- src/propsheet/console.cpp | 9 ++- src/propsheet/console.rc | 91 ++++++++++++++++++++++++- src/propsheet/dialogs.h | 3 +- 4 files changed, 103 insertions(+), 11 deletions(-) diff --git a/src/propsheet/TerminalPropsheetPage.cpp b/src/propsheet/TerminalPropsheetPage.cpp index bc760494eab..7de3b8b5cbb 100644 --- a/src/propsheet/TerminalPropsheetPage.cpp +++ b/src/propsheet/TerminalPropsheetPage.cpp @@ -92,8 +92,7 @@ void _UpdateTextAndScroll(const HWND hDlg, void _PrepDefAppCombo(const HWND hDlg, const int dlgItem, const std::vector& list, - const DelegationConfig::DelegationPackage& selected, - const bool enabled) + const DelegationConfig::DelegationPackage& selected) { HWND hCombo = GetDlgItem(hDlg, dlgItem); ComboBox_ResetContent(hCombo); @@ -122,10 +121,7 @@ void _PrepDefAppCombo(const HWND hDlg, ComboBox_SetCurSel(hCombo, selectedIndex); - if (enabled) - { - ComboBox_Enable(hCombo, TRUE); - } + ComboBox_Enable(hCombo, TRUE); } bool InitTerminalDialog(const HWND hDlg) noexcept @@ -225,8 +221,7 @@ bool InitTerminalDialog(const HWND hDlg) noexcept _PrepDefAppCombo(hDlg, IDD_TERMINAL_COMBO_DEFTERM, g_availablePackages, - g_selectedPackage, - g_defAppEnabled); + g_selectedPackage); return true; } diff --git a/src/propsheet/console.cpp b/src/propsheet/console.cpp index 2eb0507a0f9..bdfc929c90d 100644 --- a/src/propsheet/console.cpp +++ b/src/propsheet/console.cpp @@ -553,7 +553,14 @@ BOOL PopulatePropSheetPageArray(_Out_writes_(cPsps) PROPSHEETPAGE* pPsp, const s { pTerminalPage->dwSize = sizeof(PROPSHEETPAGE); pTerminalPage->hInstance = ghInstance; - pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL); + if (g_defAppEnabled) + { + pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL_WITH_DEFTERM); + } + else + { + pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL); + } pTerminalPage->pfnDlgProc = TerminalDlgProc; pTerminalPage->lParam = TERMINAL_PAGE_INDEX; pTerminalPage->dwFlags = PSP_DEFAULT; diff --git a/src/propsheet/console.rc b/src/propsheet/console.rc index 5d888c17baf..bf1c06e3f5b 100644 --- a/src/propsheet/console.rc +++ b/src/propsheet/console.rc @@ -631,7 +631,96 @@ BEGIN GROUPBOX "Terminal Scrolling", -1, T_SCROLL_X, T_SCROLL_Y, T_SCROLL_W, T_SCROLL_H AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10 - GROUPBOX "Default Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H + CONTROL "Find out more about experimental terminal settings", + IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10 +END + +DID_TERMINAL_WITH_DEFTERM DIALOG 0, 0, 245, 226 +CAPTION " Terminal " +STYLE WS_VISIBLE | WS_CAPTION | WS_CHILD | DS_MODALFRAME +FONT 8,"MS Shell Dlg" +BEGIN + + // GROUPBOX text, id, x, y, width, height [, style [, extended-style]] + // CONTROL text, id, class, style, x, y, width, height [, extended-style] + + GROUPBOX "Terminal Colors", -1, T_COLORS_X, T_COLORS_Y, T_COLORS_W, T_COLORS_H, WS_GROUP + + AUTOCHECKBOX "Use Separate Foreground", IDD_USE_TERMINAL_FG, T_COLORS_X+P_1, T_COLORS_CHECK_Y, T_COLORS_FG_W, 10 + + CONTROL "", IDD_TERMINAL_FGCOLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP , + T_COLORS_X+P_2, T_COLORS_RED_Y, COLOR_SIZE, COLOR_SIZE + + LTEXT "Red:", -1, T_COLORS_FG_TEXT_X, T_COLORS_RED_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_FG_RED, T_COLORS_FG_INPUT_X, T_COLORS_RED_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_FG_REDSCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Green:", -1, T_COLORS_FG_TEXT_X, T_COLORS_GREEN_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_FG_GREEN, T_COLORS_FG_INPUT_X, T_COLORS_GREEN_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_FG_GREENSCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Blue:", -1, T_COLORS_FG_TEXT_X, T_COLORS_BLUE_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_FG_BLUE, T_COLORS_FG_INPUT_X, T_COLORS_BLUE_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_FG_BLUESCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + AUTOCHECKBOX "Use Separate Background", IDD_USE_TERMINAL_BG, T_COLORS_BG_X, T_COLORS_CHECK_Y, T_COLORS_FG_W, 10 + + CONTROL "", IDD_TERMINAL_BGCOLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP , + T_COLORS_BG_X, T_COLORS_RED_Y, COLOR_SIZE, COLOR_SIZE + + LTEXT "Red:", -1, T_COLORS_BG_TEXT_X, T_COLORS_RED_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_BG_RED, T_COLORS_BG_INPUT_X, T_COLORS_RED_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_BG_REDSCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Green:", -1, T_COLORS_BG_TEXT_X, T_COLORS_GREEN_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_BG_GREEN, T_COLORS_BG_INPUT_X, T_COLORS_GREEN_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_BG_GREENSCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Blue:", -1, T_COLORS_BG_TEXT_X, T_COLORS_BLUE_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_BG_BLUE, T_COLORS_BG_INPUT_X, T_COLORS_BLUE_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_BG_BLUESCROLL, UPDOWN_CLASS, + UPDOWN_STYLES, 0, 0, 0, 0 + + + GROUPBOX "Cursor Shape", -1, T_CSTYLE_X, T_CSTYLE_Y, T_CSTYLE_W, T_CSTYLE_H + AUTORADIOBUTTON "Use Legacy Style", IDD_TERMINAL_LEGACY_CURSOR, T_CSTYLE_X+P_1, T_CSTYLE_R_1_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, WS_TABSTOP|WS_GROUP + AUTORADIOBUTTON "Underscore", IDD_TERMINAL_UNDERSCORE, T_CSTYLE_X+P_1, T_CSTYLE_R_2_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, + AUTORADIOBUTTON "Vertical Bar", IDD_TERMINAL_VERTBAR, T_CSTYLE_X+P_1, T_CSTYLE_R_3_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, + AUTORADIOBUTTON "Empty Box", IDD_TERMINAL_EMPTYBOX, T_CSTYLE_X+P_1, T_CSTYLE_R_4_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, + AUTORADIOBUTTON "Solid Box", IDD_TERMINAL_SOLIDBOX, T_CSTYLE_X+P_1, T_CSTYLE_R_5_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, + + + GROUPBOX "Cursor Colors", -1, T_CCOLOR_X, T_CCOLOR_Y, T_CCOLOR_W, T_CCOLOR_H, WS_GROUP + + AUTORADIOBUTTON "Inverse Color", IDD_TERMINAL_INVERSE_CURSOR, T_CCOLOR_X+P_1, T_CSTYLE_R_1_Y, T_CCOLOR_R_W, T_CSTYLE_R_H, WS_TABSTOP|WS_GROUP + + AUTORADIOBUTTON "Use Color", IDD_TERMINAL_CURSOR_USECOLOR, T_CCOLOR_X+P_1, T_CSTYLE_R_2_Y, T_CCOLOR_R_W, T_CSTYLE_R_H, + + CONTROL "", IDD_TERMINAL_CURSOR_COLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP, + T_CCOLOR_X+P_2, T_CSTYLE_R_3_Y, COLOR_SIZE, COLOR_SIZE + + LTEXT "Red:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_R_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_CURSOR_RED, T_CCOLOR_EDIT_X, T_CCOLOR_R_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_CURSOR_REDSCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Green:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_G_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_CURSOR_GREEN, T_CCOLOR_EDIT_X, T_CCOLOR_G_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_CURSOR_GREENSCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0 + + LTEXT "Blue:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_B_Y, T_COLORS_TEXT_W, 9 + EDITTEXT IDD_TERMINAL_CURSOR_BLUE, T_CCOLOR_EDIT_X, T_CCOLOR_B_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL + CONTROL "", IDD_TERMINAL_CURSOR_BLUESCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0 + + + GROUPBOX "Terminal Scrolling", -1, T_SCROLL_X, T_SCROLL_Y, T_SCROLL_W, T_SCROLL_H + AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10 + + GROUPBOX "Default Terminal Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_0, T_DEFTERM_Y, T_DEFTERM_W, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Find out more about experimental terminal settings", diff --git a/src/propsheet/dialogs.h b/src/propsheet/dialogs.h index ffa52c3e605..9200f9090ef 100644 --- a/src/propsheet/dialogs.h +++ b/src/propsheet/dialogs.h @@ -164,7 +164,8 @@ Revision History: #define IDD_TERMINAL_CURSOR_GREEN 630 #define IDD_TERMINAL_CURSOR_BLUE 631 #define IDD_HELP_TERMINAL 632 -#define IDD_TERMINAL_COMBO_DEFTERM 640 +#define DID_TERMINAL_WITH_DEFTERM 640 +#define IDD_TERMINAL_COMBO_DEFTERM 641 #define BM_TRUETYPE_ICON 1000 From 1cf4fb180634333b24fb1cda2797e45c3d18490d Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 5 Mar 2021 13:13:00 -0800 Subject: [PATCH 54/80] Increase the number of things that don't hand off because lots of background activities use those modes. Also exclude things that don't make sense like attachconsole or child processes inheriting. --- src/server/IoDispatchers.cpp | 78 +++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 85c8952eb63..1fac9eca14e 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -138,6 +138,77 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCloseObject(_In_ PCONSOLE_API_MSG pMessag return pMessage; } +// Routine Description: +// - Uses some information about current console state and +// the incoming process state and preferences to determine +// whether we should attempt to handoff to a registered console. +static bool _shouldAttemptHandoff(const Globals& globals, + const CONSOLE_INFORMATION& gci, + CONSOLE_API_CONNECTINFO& cac) +{ + // 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 + // that is supposed to be inheriting the existing console/window from the parent. + if (WI_IsFlagSet(gci.Flags, CONSOLE_INITIALIZED)) + { + return false; + } + + // If this is an AttachConsole message and not occuring + // because of a conclnt!ConsoleInitialize, do not handoff. + // ConsoleApp is FALSE for attach. + if (!cac.ConsoleApp) + { + return false; + } + + // If it is a PTY session, do not attempt handoff. + if (globals.launchArgs.IsHeadless()) + { + return false; + } + + // If we do not have a registered handoff, do not attempt. + if (!globals.handoffConsoleClsid) + { + return false; + } + + // If we're already a target for receiving another handoff, + // do not chain. + if (globals.handoffTarget) + { + return false; + } + + // If the client was started with CREATE_NO_WINDOW to CreateProcess, + // this function will say that it does NOT deserve a visible window. + // Return false. + if (!ConsoleConnectionDeservesVisibleWindow(&cac)) + { + return false; + } + + // If the process is giving us explicit window show information, we need + // to look at which one it is. + if (WI_IsFlagSet(cac.ConsoleInfo.GetStartupFlags(), STARTF_USESHOWWINDOW)) + { + switch (cac.ConsoleInfo.GetShowWindow()) + { + // For all hide or minimize actions, do not hand off. + case SW_HIDE: + case SW_SHOWMINIMIZED: + case SW_MINIMIZE: + case SW_SHOWMINNOACTIVE: + case SW_FORCEMINIMIZE: + return false; + } + } + + return true; +} + // Routine Description: // - Used when a client application establishes an initial connection to this console server. // - This is supposed to represent accounting for the process, making the appropriate handles, etc. @@ -165,12 +236,9 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API goto Error; } - // If we are NOT a PTY session (headless)... - // we have FOUND a CLSID for a different console to be the default startup handler... - // we are NOT already receiving an inbound console connection handoff... - // and the client app is going to end up showing a window... + // If we pass the tests... // then attempt to delegate the startup to the registered replacement. - if (!Globals.launchArgs.IsHeadless() && Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac)) + if (_shouldAttemptHandoff(Globals, gci, Cac)) { try { From d10d3875bd1ef33b6af4ac8736bb1033f38c8817 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 5 Mar 2021 13:13:57 -0800 Subject: [PATCH 55/80] Use debugfull so WinDBG stops having problems with all the default and fastlink ones. --- src/common.build.pre.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.build.pre.props b/src/common.build.pre.props index 52e19f02552..4366c9580f7 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -120,7 +120,7 @@ _DEBUG;DBG;%(PreprocessorDefinitions) - true + DebugFull From dcb7043d37c37860b50319771c8c76c110ae64a9 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 10 Mar 2021 14:21:01 -0800 Subject: [PATCH 56/80] revert whitespace changes vs main --- src/internal/stubs.cpp | 2 +- src/propsheet/console.cpp | 1 - src/propslib/propslib.vcxproj | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index 7c8d4e6c5b0..ac312a23e71 100644 --- a/src/internal/stubs.cpp +++ b/src/internal/stubs.cpp @@ -32,6 +32,6 @@ void EdpPolicy::AuditClipboard(const std::wstring_view /*destinationName*/) noex [[nodiscard]] HRESULT DefaultApp::CheckDefaultAppPolicy(bool& isEnabled) noexcept { - isEnabled = true; + isEnabled = false; return S_OK; } \ No newline at end of file diff --git a/src/propsheet/console.cpp b/src/propsheet/console.cpp index bdfc929c90d..0d1a3bad089 100644 --- a/src/propsheet/console.cpp +++ b/src/propsheet/console.cpp @@ -104,7 +104,6 @@ void SaveConsoleSettingsIfNeeded(const HWND hwnd) if (gpStateInfo->LinkTitle != nullptr) { SetGlobalRegistryValues(); - if (!NT_SUCCESS(ShortcutSerialization::s_SetLinkValues(gpStateInfo, g_fEastAsianSystem, g_fForceV2, diff --git a/src/propslib/propslib.vcxproj b/src/propslib/propslib.vcxproj index ced59ca6c9e..21ccacc258f 100644 --- a/src/propslib/propslib.vcxproj +++ b/src/propslib/propslib.vcxproj @@ -28,4 +28,4 @@ - \ No newline at end of file + From ce200154417d193d426b170e2f6239754b2ecbf3 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 13:32:04 -0800 Subject: [PATCH 57/80] suppress warning on hard cast for handle stowed in number. --- src/cascadia/TerminalConnection/ConptyConnection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 2fc7e660931..10b93f6bed9 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -213,7 +213,13 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { _guid = Utils::CreateGuid(); } - _piClient.hProcess = reinterpret_cast(hClientProcess); + + // We are knowingly doing a semi-dangerous repack + // of a HANDLE in a 64-bit number for this interface. + // Reinterpret and C-cast are really our options for + // getting the data out and both need an audit suppress. +#pragma warning(suppress: 26493) + _piClient.hProcess = (HANDLE)(hClientProcess); } ConptyConnection::ConptyConnection(const hstring& commandline, From 0a8f690206dbffc1a5e21b7c4d6653e17ef3cbd5 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 16:51:49 -0800 Subject: [PATCH 58/80] comments and formatting --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- src/cascadia/TerminalConnection/ConptyConnection.cpp | 2 +- src/internal/stubs.cpp | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 962ae9ddfd2..8c83beb30cf 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -3084,7 +3084,7 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection) { - // TODO: this should probably use a more reasonable profile than nullptr. + // TODO: GH 9458 will give us more context so we can try to choose a better profile. _OpenNewTab(nullptr, connection); } diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 10b93f6bed9..89bf9e8faaa 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -218,7 +218,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation // of a HANDLE in a 64-bit number for this interface. // Reinterpret and C-cast are really our options for // getting the data out and both need an audit suppress. -#pragma warning(suppress: 26493) +#pragma warning(suppress : 26493) _piClient.hProcess = (HANDLE)(hClientProcess); } diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index ac312a23e71..198a5366774 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 { + // False outside so OpenConsole does not even try to handoff again to another + // console if it is started solo. isEnabled = false; return S_OK; } \ No newline at end of file From f7694ce638c2cec64056cd0930e0aaaf5727876b Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 16:55:33 -0800 Subject: [PATCH 59/80] label hpcon todo --- src/cascadia/TerminalConnection/ConptyConnection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 89bf9e8faaa..36dc0fe3b34 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -208,7 +208,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _inPipe{ (HANDLE)hIn }, _outPipe{ (HANDLE)hOut } { - hSig; // TODO: this needs to be packed into the hpcon + hSig; // TODO: GH 9464 this needs to be packed into the hpcon if (_guid == guid{}) { _guid = Utils::CreateGuid(); From 86caf5b5de46ebf1fc121e43d4ff656faf54b398 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 17:00:48 -0800 Subject: [PATCH 60/80] fix extension manifest ids and display names to be distinct and sensible. --- src/cascadia/CascadiaPackage/Package-Dev.appxmanifest | 2 +- src/cascadia/CascadiaPackage/Package-Pre.appxmanifest | 8 ++++---- src/cascadia/CascadiaPackage/Package.appxmanifest | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index 631af36748a..7bd6ff6ddbf 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -77,7 +77,7 @@ diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index 89e6a4a9c91..b0129c2c841 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -77,8 +77,8 @@ @@ -88,8 +88,8 @@ diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index 52f97691978..4337a39bc23 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -77,7 +77,7 @@ @@ -88,8 +88,8 @@ From 54836aaa481dd580d26c5421b4b48003841e2247 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 17:09:29 -0800 Subject: [PATCH 61/80] newline EOF stubs for @jsoref. --- src/internal/stubs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index 198a5366774..ca0567d222e 100644 --- a/src/internal/stubs.cpp +++ b/src/internal/stubs.cpp @@ -36,4 +36,4 @@ void EdpPolicy::AuditClipboard(const std::wstring_view /*destinationName*/) noex // console if it is started solo. isEnabled = false; return S_OK; -} \ No newline at end of file +} From c0c2f438214082876dbe2db13d8b69fb1ef581ff Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 11 Mar 2021 17:43:36 -0800 Subject: [PATCH 62/80] Add some inbox and out of box divergence so inbox can only send and out of box can only receive in regards to IConsoleHandoff. Also set policy to true outside so propsheet shows choices. --- src/host/exe/exemain.cpp | 7 ++++++- src/internal/stubs.cpp | 6 +++--- src/server/IoDispatchers.cpp | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index dcc71a56b7a..6597071f554 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -8,6 +8,7 @@ #include "CConsoleHandoff.h" #include "../server/Entrypoints.h" #include "../interactivity/inc/ServiceLocator.hpp" +#include "../inc/conint.h" // Define TraceLogging provider TRACELOGGING_DEFINE_PROVIDER( @@ -221,7 +222,10 @@ int CALLBACK wWinMain( HRESULT hr = args.ParseCommandline(); if (SUCCEEDED(hr)) { - if (args.ShouldRunAsComServer()) + // 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 { @@ -248,6 +252,7 @@ int CALLBACK wWinMain( CATCH_RETURN() } else +#endif { if (ShouldUseLegacyConhost(args)) { diff --git a/src/internal/stubs.cpp b/src/internal/stubs.cpp index ca0567d222e..f9570d6dde2 100644 --- a/src/internal/stubs.cpp +++ b/src/internal/stubs.cpp @@ -32,8 +32,8 @@ void EdpPolicy::AuditClipboard(const std::wstring_view /*destinationName*/) noex [[nodiscard]] HRESULT DefaultApp::CheckDefaultAppPolicy(bool& isEnabled) noexcept { - // False outside so OpenConsole does not even try to handoff again to another - // console if it is started solo. - 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; } diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 03ca3579820..19498b8bf6f 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -146,6 +146,20 @@ static bool _shouldAttemptHandoff(const Globals& globals, const CONSOLE_INFORMATION& gci, CONSOLE_API_CONNECTINFO& cac) { +#ifdef __INSIDE_WINDOWS + const bool insideWindows = true; +#else + const bool insideWindows = false; +#endif + + // If we are outside of Windows, do not attempt to handoff + // to another target as handoff is an inbox escape mechanism + // to get to this copy! + if (!insideWindows) + { + return false; + } + // 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 From 5f9f7d8cfc636350ec64cdf4f6921a8ed5d37549 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 12:11:15 -0800 Subject: [PATCH 63/80] Address all Carlos comments except notes to localizers. --- src/cascadia/TerminalApp/AppCommandlineArgs.cpp | 2 +- src/cascadia/TerminalApp/TerminalPage.cpp | 3 +++ .../TerminalConnection/CTerminalHandoff.cpp | 7 +++++-- .../TerminalConnection/CTerminalHandoff.h | 16 ++++++++++++++++ src/cascadia/TerminalSettingsEditor/Launch.cpp | 1 + .../TerminalSettingsModel/KeyMapping.idl | 2 +- src/host/exe/CConsoleHandoff.h | 2 +- 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 5c75582a09e..75109ac4ea3 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -760,7 +760,7 @@ std::optional AppComman // - 0 if the commandline was successfully parsed int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { - for (auto& arg : args) + for (const auto& arg : args) { if (arg == L"-Embedding") { diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 8c83beb30cf..234bef5c8dc 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -762,6 +762,9 @@ 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::BuildSettings for more details. + // - existingConnection: An optional connection that is already established to a PTY + // for this tab to host and not create one. + // If not defined, the tab will create the connection. void TerminalPage::_OpenNewTab(const NewTerminalArgs& newTerminalArgs, winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection existingConnection) try { diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index c8cea60dc7d..bc9061c086d 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + #include "pch.h" #include "CTerminalHandoff.h" @@ -19,7 +22,7 @@ try { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); - auto classFactory = Make>(); + const auto classFactory = Make>(); RETURN_IF_NULL_ALLOC(classFactory); @@ -43,7 +46,7 @@ CATCH_RETURN() // - 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(E_NOT_VALID_STATE, _pfnHandoff == nullptr); + RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff); _pfnHandoff = nullptr; diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 36b6b5666d0..0c551d5cf33 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -1,3 +1,19 @@ +/*++ +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" diff --git a/src/cascadia/TerminalSettingsEditor/Launch.cpp b/src/cascadia/TerminalSettingsEditor/Launch.cpp index 6ac4c4bfdde..3b86bb3d39a 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.cpp +++ b/src/cascadia/TerminalSettingsEditor/Launch.cpp @@ -38,6 +38,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation _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; diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.idl b/src/cascadia/TerminalSettingsModel/KeyMapping.idl index 31d76f8f655..cae7c962708 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.idl +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.idl @@ -55,7 +55,7 @@ namespace Microsoft.Terminal.Settings.Model TogglePaneReadOnly, FindMatch, NewWindow, - ToggleInboundPty + ToggleInboundPty // Not currently bindable }; [default_interface] runtimeclass ActionAndArgs { diff --git a/src/host/exe/CConsoleHandoff.h b/src/host/exe/CConsoleHandoff.h index cfd227e59d1..e2d2e14d890 100644 --- a/src/host/exe/CConsoleHandoff.h +++ b/src/host/exe/CConsoleHandoff.h @@ -3,7 +3,7 @@ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: -- CConsoleHandoff.hpp +- CConsoleHandoff.h Abstract: - This module receives a console session handoff from the operating system to From 14357c71936e3811dbad6c443d5141a4e4c4251c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 13:13:26 -0800 Subject: [PATCH 64/80] fix wording --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 234bef5c8dc..00d44759c16 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -763,7 +763,7 @@ namespace winrt::TerminalApp::implementation // control which profile is created and with possible other // configurations. See TerminalSettings::BuildSettings for more details. // - existingConnection: An optional connection that is already established to a PTY - // for this tab to host and not create one. + // 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 From 051f5378ae9a141c0a872b67bc388d30e855449a Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 13:14:38 -0800 Subject: [PATCH 65/80] format --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 00d44759c16..daa1137a2df 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -763,7 +763,7 @@ namespace winrt::TerminalApp::implementation // control which profile is created and with possible other // configurations. See TerminalSettings::BuildSettings for more details. // - existingConnection: An optional connection that is already established to a PTY - // for this tab to host instead of creating one. + // 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 From b66fe3a20056d1619cab4c8ee0e3cc84df0f54a9 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 14:39:28 -0800 Subject: [PATCH 66/80] Add commentary explaining localizable strings and remove two that were unused after refactor. --- src/cascadia/TerminalApp/Resources/en-US/Resources.resw | 3 ++- .../TerminalSettingsEditor/Resources/en-US/Resources.resw | 8 ++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index e3d1eb24e81..253eaadfcd0 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -570,7 +570,8 @@ More options - Listens for inbound pty connections + Listens for inbound connections from the operating system for command-line tools that do not yet have a window + Description of how one of the command line arguments works. This is `wt.exe -Embedding`. While typically only called by the operating system as it attempts to find a suitable Terminal application that could host the window for a command-line app that is starting up, a user COULD technically call it manually. Thus the need to describe how it works. Maximize diff --git a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw index e2fee6b4a99..505d56fbc20 100644 --- a/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsEditor/Resources/en-US/Resources.resw @@ -223,15 +223,11 @@ 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. - - - Default console (PTY) - - - The console engine and pseudoconsole version that will be used to power the default terminal application. + 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 From 5a4cfe516bb41786f7eadf1d533c6f840507165e Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 14:39:51 -0800 Subject: [PATCH 67/80] Fix grammar in comment. --- src/server/IoDispatchers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index 19498b8bf6f..b1e78849293 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -152,7 +152,7 @@ static bool _shouldAttemptHandoff(const Globals& globals, const bool insideWindows = false; #endif - // If we are outside of Windows, do not attempt to handoff + // 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! if (!insideWindows) From c7625e1f520ba63fcc73c99b6c5570c2744aae84 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 15:24:48 -0800 Subject: [PATCH 68/80] Remove the whole toggle action business to listening or not listening for inbound connections. Just do the thing if we see the argument and update the argument validator to not make a tab when embedding is found. --- .../TerminalApp/AppActionHandlers.cpp | 7 ---- .../TerminalApp/AppCommandlineArgs.cpp | 30 +++++++++------- src/cascadia/TerminalApp/AppCommandlineArgs.h | 2 ++ .../TerminalApp/ShortcutActionDispatch.cpp | 5 --- .../TerminalApp/ShortcutActionDispatch.h | 1 - .../TerminalApp/ShortcutActionDispatch.idl | 1 - src/cascadia/TerminalApp/TerminalPage.cpp | 35 +------------------ src/cascadia/TerminalApp/TerminalPage.h | 5 --- .../TerminalSettingsModel/KeyMapping.idl | 3 +- 9 files changed, 22 insertions(+), 67 deletions(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 51c61e17e38..a987a234241 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -667,11 +667,4 @@ namespace winrt::TerminalApp::implementation _OpenNewWindow(false, newTerminalArgs); actionArgs.Handled(true); } - - void TerminalPage::_HandleToggleInboundPty(const IInspectable& /*sender*/, - const ActionEventArgs& args) - { - ToggleInboundPty(); - args.Handled(true); - } } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 75109ac4ea3..ae0e8ed0729 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -726,17 +726,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 && _startupActions.front().Action() != ShortcutAction::ToggleInboundPty)) + // 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); + } } } @@ -764,8 +770,8 @@ int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { if (arg == L"-Embedding") { - winrt::Microsoft::Terminal::Settings::Model::ActionAndArgs embeddingAction(ShortcutAction::ToggleInboundPty, nullptr); - _startupActions.push_back(embeddingAction); + winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + _isHandoffListener = true; return 0; } } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index c0d34a1d34f..3d2971ffb2f 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -35,6 +35,7 @@ class TerminalApp::AppCommandlineArgs final void ValidateStartupCommands(); std::vector& GetStartupActions(); + bool IsStartedAsHandoffListener() const noexcept; const std::string& GetExitMessage(); bool ShouldExitEarly() const noexcept; @@ -104,6 +105,7 @@ class TerminalApp::AppCommandlineArgs final 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/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index b5b053ba8a3..90eede9d057 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -265,11 +265,6 @@ namespace winrt::TerminalApp::implementation _NewWindowHandlers(*this, eventArgs); break; } - case ShortcutAction::ToggleInboundPty: - { - _ToggleInboundPtyHandlers(*this, eventArgs); - break; - } default: return false; } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index bbbfaf0cdd3..bdcf59e7a17 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -67,7 +67,6 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(FindMatch, TerminalApp::ShortcutActionDispatch, Microsoft::Terminal::Settings::Model::ActionEventArgs); TYPED_EVENT(TogglePaneReadOnly, TerminalApp::ShortcutActionDispatch, Microsoft::Terminal::Settings::Model::ActionEventArgs); TYPED_EVENT(NewWindow, TerminalApp::ShortcutActionDispatch, Microsoft::Terminal::Settings::Model::ActionEventArgs); - TYPED_EVENT(ToggleInboundPty, TerminalApp::ShortcutActionDispatch, Microsoft::Terminal::Settings::Model::ActionEventArgs); // clang-format on private: diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index a561e51979a..4a8b366b945 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -53,6 +53,5 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler FindMatch; event Windows.Foundation.TypedEventHandler TogglePaneReadOnly; event Windows.Foundation.TypedEventHandler NewWindow; - event Windows.Foundation.TypedEventHandler ToggleInboundPty; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index daa1137a2df..05b8d591549 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -195,8 +195,7 @@ namespace winrt::TerminalApp::implementation // Hookup our event handlers to the ShortcutActionDispatch _RegisterActionCallbacks(); - // Hook up inbound PTY event handlers - InboundPtyChanged({ this, &TerminalPage::_OnInboundPtyChanged }); + // Hook up inbound connection event handler TerminalConnection::ConptyConnection::NewConnection({ this, &TerminalPage::_OnNewConnection }); //Event Bindings (Early) @@ -1210,7 +1209,6 @@ namespace winrt::TerminalApp::implementation _actionDispatch->FindMatch({ this, &TerminalPage::_HandleFindMatch }); _actionDispatch->TogglePaneReadOnly({ this, &TerminalPage::_HandleTogglePaneReadOnly }); _actionDispatch->NewWindow({ this, &TerminalPage::_HandleNewWindow }); - _actionDispatch->ToggleInboundPty({ this, &TerminalPage::_HandleToggleInboundPty }); } // Method Description: @@ -2844,18 +2842,6 @@ namespace winrt::TerminalApp::implementation _alwaysOnTopChangedHandlers(*this, nullptr); } - // Method Description: - // - Toggles inbound pty mode. Raises InboundPtyChanged event. - // Arguments: - // - - // Return Value: - // - - void TerminalPage::ToggleInboundPty() - { - _isInboundPty = !_isInboundPty; - _inboundPtyChangedHandlers(*this, nullptr); - } - // Method Description: // - Sets the tab split button color when a new tab color is selected // Arguments: @@ -3067,24 +3053,6 @@ namespace winrt::TerminalApp::implementation return _isAlwaysOnTop; } - bool TerminalPage::InboundPty() const - { - return _isInboundPty; - } - - void TerminalPage::_OnInboundPtyChanged(const IInspectable& /*sender*/, - const IInspectable& /*eventArgs*/) - { - if (InboundPty()) - { - ConptyConnection::StartInboundListener(); - } - else - { - ConptyConnection::StopInboundListener(); - } - } - 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. @@ -3396,5 +3364,4 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, RaiseVisualBell, _raiseVisualBellHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, InboundPtyChanged, _inboundPtyChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 9f263fb0764..10d4e84d869 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -65,11 +65,9 @@ namespace winrt::TerminalApp::implementation void ToggleFocusMode(); void ToggleFullscreen(); void ToggleAlwaysOnTop(); - void ToggleInboundPty(); bool FocusMode() const; bool Fullscreen() const; bool AlwaysOnTop() const; - bool InboundPty() const; void SetStartupActions(std::vector& actions); static std::vector ConvertExecuteCommandlineToActions(const Microsoft::Terminal::Settings::Model::ExecuteCommandlineArgs& args); @@ -96,7 +94,6 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(RaiseVisualBell, _raiseVisualBellHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTaskbarProgress, _setTaskbarProgressHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(InboundPtyChanged, _inboundPtyChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); private: @@ -127,7 +124,6 @@ namespace winrt::TerminalApp::implementation bool _isInFocusMode{ false }; bool _isFullscreen{ false }; bool _isAlwaysOnTop{ false }; - bool _isInboundPty{ false }; bool _rearranging; std::optional _rearrangeFrom; @@ -280,7 +276,6 @@ namespace winrt::TerminalApp::implementation void _HidePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); void _RestorePointerCursorHandler(const IInspectable& sender, const IInspectable& eventArgs); - void _OnInboundPtyChanged(const IInspectable& sender, const IInspectable& eventArgs); void _OnNewConnection(winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection connection); #pragma region ActionHandlers diff --git a/src/cascadia/TerminalSettingsModel/KeyMapping.idl b/src/cascadia/TerminalSettingsModel/KeyMapping.idl index cae7c962708..a51a601afee 100644 --- a/src/cascadia/TerminalSettingsModel/KeyMapping.idl +++ b/src/cascadia/TerminalSettingsModel/KeyMapping.idl @@ -54,8 +54,7 @@ namespace Microsoft.Terminal.Settings.Model BreakIntoDebugger, TogglePaneReadOnly, FindMatch, - NewWindow, - ToggleInboundPty // Not currently bindable + NewWindow }; [default_interface] runtimeclass ActionAndArgs { From c8c7ac7c8051a73e18ced0092228543745244f51 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 15:49:43 -0800 Subject: [PATCH 69/80] Cleanup unused or things that shouldn't be changes anymore. --- src/cascadia/TerminalApp/AppActionHandlers.cpp | 1 + src/cascadia/TerminalApp/AppCommandlineArgs.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index a987a234241..9b441a913fe 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -667,4 +667,5 @@ namespace winrt::TerminalApp::implementation _OpenNewWindow(false, newTerminalArgs); actionArgs.Handled(true); } + } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index 3d2971ffb2f..ae6ec4dc8e9 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -35,7 +35,6 @@ class TerminalApp::AppCommandlineArgs final void ValidateStartupCommands(); std::vector& GetStartupActions(); - bool IsStartedAsHandoffListener() const noexcept; const std::string& GetExitMessage(); bool ShouldExitEarly() const noexcept; From 495f465c26625373e7eb0303e32845e195e98ff0 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 12 Mar 2021 15:51:25 -0800 Subject: [PATCH 70/80] don't need this include twice... --- src/host/srvinit.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index 128076a6c5a..ce9ca10f147 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -9,7 +9,6 @@ #include "handle.h" #include "registry.hpp" #include "renderFontDefaults.hpp" -#include "..\propslib\DelegationConfig.hpp" #include "ApiRoutines.h" From 0443e6ca81f18c24caf94898dd74150d4c8193a4 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 16 Mar 2021 12:53:29 -0700 Subject: [PATCH 71/80] Only process listener start from the initial launch parse of arguments. The arg parser is re-used for all sorts of stuff like command palette and reloading and such. We don't want to start the listener unless COM asked us to (for now) --- src/cascadia/TerminalApp/AppCommandlineArgs.cpp | 13 ++++++++++++- src/cascadia/TerminalApp/AppCommandlineArgs.h | 1 + src/cascadia/TerminalApp/AppLogic.cpp | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index ae0e8ed0729..6eb675c058d 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 @@ -770,7 +782,6 @@ int AppCommandlineArgs::ParseArgs(winrt::array_view& args) { if (arg == L"-Embedding") { - winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); _isHandoffListener = true; return 0; } diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.h b/src/cascadia/TerminalApp/AppCommandlineArgs.h index ae6ec4dc8e9..44ff6a74a69 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.h +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.h @@ -35,6 +35,7 @@ class TerminalApp::AppCommandlineArgs final void ValidateStartupCommands(); std::vector& GetStartupActions(); + bool IsHandoffListener() const noexcept; const std::string& GetExitMessage(); bool ShouldExitEarly() const noexcept; diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index c47c9a6eee0..02bddd945b2 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -831,6 +831,14 @@ namespace winrt::TerminalApp::implementation _loadedInitialSettings = true; + // 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, + // start the listener so COM has the registrations to receive requests. + if (_settingsAppArgs.IsHandoffListener()) + { + winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + } + // Register for directory change notification. _RegisterSettingsChange(); From 5bcbb903ed15791c023e960b7c646ecbf1bfcbfd Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 17 Mar 2021 15:56:47 -0700 Subject: [PATCH 72/80] Further refine where we turn on the handoff listener so it only happens on actual initialization. --- src/cascadia/TerminalApp/AppCommandlineArgs.cpp | 1 + src/cascadia/TerminalApp/AppLogic.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp index 6eb675c058d..a672aec7da1 100644 --- a/src/cascadia/TerminalApp/AppCommandlineArgs.cpp +++ b/src/cascadia/TerminalApp/AppCommandlineArgs.cpp @@ -891,6 +891,7 @@ void AppCommandlineArgs::FullResetState() _startupActions.clear(); _exitMessage = ""; _shouldExitEarly = false; + _isHandoffListener = false; _windowTarget = std::nullopt; } diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 8eb7704f2da..d81f1a88ec5 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -832,14 +832,6 @@ namespace winrt::TerminalApp::implementation _loadedInitialSettings = true; - // 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, - // start the listener so COM has the registrations to receive requests. - if (_settingsAppArgs.IsHandoffListener()) - { - winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); - } - // Register for directory change notification. _RegisterSettingsChange(); @@ -1173,6 +1165,14 @@ 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, + // start the listener so COM has the registrations to receive requests. + if (_appArgs.IsHandoffListener()) + { + winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + } } return result; From c10811fa0efbe23b69930ffcb677fa2b19b90d1f Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Wed, 17 Mar 2021 15:58:43 -0700 Subject: [PATCH 73/80] Don't make a tab just because there are no actions. There's oid AppCommandlineArgs::ValidateStartupCommands() already does that based on the startup arguments. This will let me purposefully have NO actions when we're starting an embedding server. --- src/cascadia/TerminalApp/TerminalPage.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 504ce57e179..806f34b5534 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -355,16 +355,7 @@ namespace winrt::TerminalApp::implementation if (_startupState == StartupState::NotInitialized) { _startupState = StartupState::InStartup; - if (_startupActions.Size() == 0) - { - _OpenNewTab(nullptr); - - _CompleteInitialization(); - } - else - { - ProcessStartupActions(_startupActions, true); - } + ProcessStartupActions(_startupActions, true); } } @@ -386,11 +377,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. @@ -3046,6 +3032,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. @@ -3174,7 +3161,6 @@ namespace winrt::TerminalApp::implementation } } - // Method Description: // Method Description: // - Computes the delta for scrolling the tab's viewport. // Arguments: From d91fbd74e072432dba8af4f54b1cf60a323b7d58 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 18 Mar 2021 11:42:57 -0700 Subject: [PATCH 74/80] We have to start the server AFTER the event is hooked up or it has the chance to not be handled into a new tab. --- src/cascadia/TerminalApp/AppLogic.cpp | 7 +++++-- src/cascadia/TerminalApp/TerminalPage.cpp | 23 +++++++++++++++++++++++ src/cascadia/TerminalApp/TerminalPage.h | 2 ++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index d81f1a88ec5..f2dd86f1bcf 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1168,10 +1168,13 @@ namespace winrt::TerminalApp::implementation // 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, - // start the listener so COM has the registrations to receive requests. + // 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()) { - winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + _root->SetInboundListener(); } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 806f34b5534..a37f8293292 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -356,6 +356,16 @@ namespace winrt::TerminalApp::implementation { _startupState = StartupState::InStartup; ProcessStartupActions(_startupActions, true); + + // 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) + { + winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + } } } @@ -2722,6 +2732,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(); diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 308cb444107..a68eae46565 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -69,6 +69,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; @@ -141,6 +142,7 @@ namespace winrt::TerminalApp::implementation StartupState _startupState{ StartupState::NotInitialized }; Windows::Foundation::Collections::IVector _startupActions; + bool _shouldStartInboundListener{ false }; void _ShowAboutDialog(); winrt::Windows::Foundation::IAsyncOperation _ShowCloseWarningDialog(); From 7c9289e636a10a6ffc32949d1bfc1cdf2d04907c Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 23 Mar 2021 14:17:26 -0700 Subject: [PATCH 75/80] review feedback... comment some of the startup methods. const a thing. add a state check for the callback for handoff. --- src/cascadia/TerminalApp/TerminalPage.cpp | 9 +-- .../TerminalConnection/CTerminalHandoff.cpp | 19 +++++- src/cascadia/wt/shim.cpp | 2 +- src/host/exe/exemain.cpp | 27 +++++++++ src/host/srvinit.cpp | 58 ++++++++++++++++++- 5 files changed, 105 insertions(+), 10 deletions(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index a37f8293292..5c6f115ddb9 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -813,13 +813,8 @@ namespace winrt::TerminalApp::implementation void TerminalPage::_CreateNewTabFromSettings(GUID profileGuid, TerminalSettings settings, TerminalConnection::ITerminalConnection existingConnection) { // Initialize the new tab - auto connection = existingConnection; - - if (!connection) - { - // Create a connection based on the values in our settings object. - connection = _CreateConnectionFromSettings(profileGuid, settings); - } + // Create a connection based on the values in our settings object if we weren't given one. + const auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); TerminalConnection::ITerminalConnection debugConnection{ nullptr }; if (_settings.GlobalSettings().DebugFeaturesEnabled()) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index bc9061c086d..b9684906deb 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -67,14 +67,31 @@ HRESULT CTerminalHandoff::s_StopListening() noexcept // - out - Where to place the duplicated value // Return Value: // - S_OK or Win32 error from `::DuplicateHandle` -HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept +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. diff --git a/src/cascadia/wt/shim.cpp b/src/cascadia/wt/shim.cpp index 218b68a00b5..0b00fcaf962 100644 --- a/src/cascadia/wt/shim.cpp +++ b/src/cascadia/wt/shim.cpp @@ -32,5 +32,5 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR pCmdLine, int) // Go! wil::unique_process_information pi; - return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi); + return !CreateProcessW(module.c_str(), cmdline.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi); } diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index 6597071f554..423e400982e 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -208,6 +208,33 @@ int CALLBACK wWinMain( // 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 diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index ce9ca10f147..ca8c1623c6d 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -270,8 +270,30 @@ void ConsoleCheckDebug() #endif } +// 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, // this can't stay like this because ConsoleArguments could change... + const ConsoleArguments* const args, HANDLE driverInputEvent, PCONSOLE_API_MSG connectMessage) { @@ -311,6 +333,26 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, 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) @@ -383,6 +425,20 @@ try } 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); From a6d7a98e93c61f87335e410329040f89b008e2d2 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 23 Mar 2021 14:18:45 -0700 Subject: [PATCH 76/80] code format --- src/host/srvinit.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index ca8c1623c6d..b930429e628 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -335,12 +335,12 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, // Routine Description: // - Accepts a console server session from another console server -// most commonly from the operating system in-box console to +// 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 +// - 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. @@ -350,7 +350,7 @@ HRESULT ConsoleCreateIoThread(_In_ HANDLE Server, // 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 +// 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, @@ -431,7 +431,7 @@ CATCH_RETURN() // - 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 +// 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. From 20e55876d19cf8966bed9df0df2cd9883c6643a4 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 23 Mar 2021 15:53:14 -0700 Subject: [PATCH 77/80] Remove const because it doesn't play nice with debug tap. --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index b5da88ab750..e43ca6b5afc 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -813,7 +813,7 @@ namespace winrt::TerminalApp::implementation { // Initialize the new tab // Create a connection based on the values in our settings object if we weren't given one. - const auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); + auto connection = existingConnection ? existingConnection : _CreateConnectionFromSettings(profileGuid, settings); TerminalConnection::ITerminalConnection debugConnection{ nullptr }; if (_settings.GlobalSettings().DebugFeaturesEnabled()) From 26c1f06bbf8181a3f368df3951f213203506a071 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 26 Mar 2021 13:37:24 -0700 Subject: [PATCH 78/80] Batch of PR feedback again. --- .../CascadiaPackage/Package.appxmanifest | 8 +++---- .../Resources/en-US/Resources.resw | 4 ---- src/cascadia/TerminalApp/TerminalPage.cpp | 15 ++++++++++++- .../TerminalConnection/CTerminalHandoff.cpp | 8 ++++--- .../TerminalConnection/CTerminalHandoff.h | 8 +++---- .../TerminalConnection/ConptyConnection.cpp | 21 +++++++------------ .../TerminalConnection/ConptyConnection.h | 8 +++---- src/host/exe/exemain.cpp | 2 +- src/host/srvinit.cpp | 2 +- src/server/IoDispatchers.cpp | 18 ++++++++-------- 10 files changed, 49 insertions(+), 45 deletions(-) diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index bc235dca407..b7953a3e084 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -75,7 +75,7 @@ Enabled="false" DisplayName="ms-resource:AppName" /> - + - + diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 4dc08b29ef3..68dcb0da865 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -588,10 +588,6 @@ More options - - Listens for inbound connections from the operating system for command-line tools that do not yet have a window - Description of how one of the command line arguments works. This is `wt.exe -Embedding`. While typically only called by the operating system as it attempts to find a suitable Terminal application that could host the window for a command-line app that is starting up, a user COULD technically call it manually. Thus the need to describe how it works. - Maximize diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index e43ca6b5afc..3fcd847640d 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -363,7 +363,20 @@ namespace winrt::TerminalApp::implementation // them to nowhere. if (_shouldStartInboundListener) { - winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + 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() } } } diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index b9684906deb..1da151ac4f6 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -5,8 +5,10 @@ #include "CTerminalHandoff.h" +using namespace Microsoft::WRL; + // The callback function when a connection is received -static NewHandoff _pfnHandoff = nullptr; +static NewHandoffFunction _pfnHandoff = nullptr; // The registration ID of the class object for clean up later static DWORD g_cTerminalHandoffRegistration = 0; @@ -17,7 +19,7 @@ static DWORD g_cTerminalHandoffRegistration = 0; // - 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(NewHandoff pfnHandoff) noexcept +HRESULT CTerminalHandoff::s_StartListening(NewHandoffFunction pfnHandoff) noexcept try { RETURN_HR_IF(E_NOT_VALID_STATE, _pfnHandoff != nullptr); @@ -52,7 +54,7 @@ HRESULT CTerminalHandoff::s_StopListening() noexcept if (g_cTerminalHandoffRegistration) { - RETURN_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); + LOG_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); g_cTerminalHandoffRegistration = 0; } diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.h b/src/cascadia/TerminalConnection/CTerminalHandoff.h index 0c551d5cf33..396f4a095f0 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.h +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.h @@ -26,12 +26,10 @@ Author(s): #define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C" #endif -using namespace Microsoft::WRL; - -typedef HRESULT (*NewHandoff)(HANDLE, HANDLE, HANDLE, HANDLE); +using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE); struct __declspec(uuid(__CLSID_CTerminalHandoff)) - CTerminalHandoff : public RuntimeClass, ITerminalHandoff> + CTerminalHandoff : public Microsoft::WRL::RuntimeClass, ITerminalHandoff> { #pragma region ITerminalHandoff STDMETHODIMP EstablishPtyHandoff(HANDLE in, @@ -41,7 +39,7 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff)) #pragma endregion - static HRESULT s_StartListening(NewHandoff pfnHandoff) noexcept; + static HRESULT s_StartListening(NewHandoffFunction pfnHandoff) noexcept; static HRESULT s_StopListening() noexcept; }; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.cpp b/src/cascadia/TerminalConnection/ConptyConnection.cpp index 36dc0fe3b34..f7e5b7e819a 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.cpp +++ b/src/cascadia/TerminalConnection/ConptyConnection.cpp @@ -191,10 +191,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation } CATCH_RETURN(); - ConptyConnection::ConptyConnection(const uint64_t hSig, - const uint64_t hIn, - const uint64_t hOut, - const uint64_t hClientProcess) : + ConptyConnection::ConptyConnection(const HANDLE hSig, + const HANDLE hIn, + const HANDLE hOut, + const HANDLE hClientProcess) : _initialRows{ 25 }, _initialCols{ 80 }, _commandline{ L"" }, @@ -205,8 +205,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _u8State{}, _u16Str{}, _buffer{}, - _inPipe{ (HANDLE)hIn }, - _outPipe{ (HANDLE)hOut } + _inPipe{ hIn }, + _outPipe{ hOut } { hSig; // TODO: GH 9464 this needs to be packed into the hpcon if (_guid == guid{}) @@ -214,12 +214,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _guid = Utils::CreateGuid(); } - // We are knowingly doing a semi-dangerous repack - // of a HANDLE in a 64-bit number for this interface. - // Reinterpret and C-cast are really our options for - // getting the data out and both need an audit suppress. -#pragma warning(suppress : 26493) - _piClient.hProcess = (HANDLE)(hClientProcess); + _piClient.hProcess = hClientProcess; } ConptyConnection::ConptyConnection(const hstring& commandline, @@ -494,7 +489,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept try { - auto conn = winrt::make((uint64_t)signal, (uint64_t)in, (uint64_t)out, (uint64_t)process); + auto conn = winrt::make(signal, in, out, process); _newConnectionHandlers(conn); return S_OK; diff --git a/src/cascadia/TerminalConnection/ConptyConnection.h b/src/cascadia/TerminalConnection/ConptyConnection.h index 693122872ac..3eee9fc8d02 100644 --- a/src/cascadia/TerminalConnection/ConptyConnection.h +++ b/src/cascadia/TerminalConnection/ConptyConnection.h @@ -19,10 +19,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation { struct ConptyConnection : ConptyConnectionT, ConnectionStateHolder { - ConptyConnection(const uint64_t hSig, - const uint64_t hIn, - const uint64_t hOut, - const uint64_t hClientProcess); + ConptyConnection(const HANDLE hSig, + const HANDLE hIn, + const HANDLE hOut, + const HANDLE hClientProcess); ConptyConnection( const hstring& cmdline, diff --git a/src/host/exe/exemain.cpp b/src/host/exe/exemain.cpp index 423e400982e..d955edfa8dd 100644 --- a/src/host/exe/exemain.cpp +++ b/src/host/exe/exemain.cpp @@ -177,7 +177,7 @@ static bool ShouldUseLegacyConhost(const ConsoleArguments& args) // Routine Description: // - Called back when COM says there is nothing left for our server to do and we can tear down. -void _releaseNotifier() noexcept +static void _releaseNotifier() noexcept { _comServerExitEvent.SetEvent(); } diff --git a/src/host/srvinit.cpp b/src/host/srvinit.cpp index b930429e628..ad43d06ed5c 100644 --- a/src/host/srvinit.cpp +++ b/src/host/srvinit.cpp @@ -416,7 +416,7 @@ try outPipeTheirSide.release(); signalPipeTheirSide.release(); - const auto commandLine = fmt::format(L" --headless --signal {:#x}", (int64_t)signalPipeOurSide.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()); diff --git a/src/server/IoDispatchers.cpp b/src/server/IoDispatchers.cpp index b1e78849293..58909c7d957 100644 --- a/src/server/IoDispatchers.cpp +++ b/src/server/IoDispatchers.cpp @@ -146,19 +146,18 @@ static bool _shouldAttemptHandoff(const Globals& globals, const CONSOLE_INFORMATION& gci, CONSOLE_API_CONNECTINFO& cac) { -#ifdef __INSIDE_WINDOWS - const bool insideWindows = true; -#else - const bool insideWindows = false; -#endif +#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! - if (!insideWindows) - { - return false; - } + return false; + +#else // This console is already initialized. Do not // attempt handoff to another one. @@ -223,6 +222,7 @@ static bool _shouldAttemptHandoff(const Globals& globals, } return true; +#endif } // Routine Description: From 55cbf43cc78e6835f682e0982812ddd8da7d6cb0 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 26 Mar 2021 13:43:12 -0700 Subject: [PATCH 79/80] code format --- src/cascadia/TerminalApp/TerminalPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 3fcd847640d..31703d3227b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -365,7 +365,7 @@ namespace winrt::TerminalApp::implementation { try { - winrt::Microsoft::Terminal::TerminalConnection::ConptyConnection::StartInboundListener(); + 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. From 677a1369ead4133d23bd7f14900f563e739faea8 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 26 Mar 2021 14:17:35 -0700 Subject: [PATCH 80/80] turn back to return from log. log can throw and this path isn't used right now anyway. --- src/cascadia/TerminalConnection/CTerminalHandoff.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp index 1da151ac4f6..27611190315 100644 --- a/src/cascadia/TerminalConnection/CTerminalHandoff.cpp +++ b/src/cascadia/TerminalConnection/CTerminalHandoff.cpp @@ -54,7 +54,7 @@ HRESULT CTerminalHandoff::s_StopListening() noexcept if (g_cTerminalHandoffRegistration) { - LOG_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); + RETURN_IF_FAILED(CoRevokeClassObject(g_cTerminalHandoffRegistration)); g_cTerminalHandoffRegistration = 0; }