diff --git a/.github/actions/spell-check/dictionary/apis.txt b/.github/actions/spell-check/dictionary/apis.txt index d50ce266603..1bf739dcf9b 100644 --- a/.github/actions/spell-check/dictionary/apis.txt +++ b/.github/actions/spell-check/dictionary/apis.txt @@ -2,9 +2,15 @@ ACCEPTFILES ACCESSDENIED bitfield bitfields +CLASSNOTAVAILABLE +EXPCMDFLAGS +EXPCMDSTATE href IBox +IBind ICustom +IClass +IExplorer IMap IObject IStorage @@ -12,6 +18,7 @@ LCID NCHITTEST NCLBUTTONDBLCLK NCRBUTTONDBLCLK +NOAGGREGATION NOREDIRECTIONBITMAP oaidl ocidl diff --git a/.github/actions/spell-check/dictionary/microsoft.txt b/.github/actions/spell-check/dictionary/microsoft.txt index 50831af918c..62cd27b72cd 100644 --- a/.github/actions/spell-check/dictionary/microsoft.txt +++ b/.github/actions/spell-check/dictionary/microsoft.txt @@ -3,6 +3,7 @@ mfcribbon microsoft microsoftonline osgvsowi +powerrename powershell tdbuildteamid vcruntime diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 84ddc0aba21..8334d6e8225 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -603,6 +603,7 @@ dllexport DLLGETVERSIONPROC dllimport dllinit +dllmain DLLVERSIONINFO DLOAD DLOOK @@ -2088,6 +2089,7 @@ SHIFTJIS Shl shlguid shlobj +shobjidl shlwapi SHORTPATH SHOWCURSOR diff --git a/.github/actions/spell-check/expect/web.txt b/.github/actions/spell-check/expect/web.txt index 7ec457b6949..61bdfa1f807 100644 --- a/.github/actions/spell-check/expect/web.txt +++ b/.github/actions/spell-check/expect/web.txt @@ -4,3 +4,5 @@ www ecma rapidtables WCAG +winui +appshellintegration diff --git a/.github/actions/spell-check/patterns/patterns.txt b/.github/actions/spell-check/patterns/patterns.txt index 765eef4c23c..cddd540bffe 100644 --- a/.github/actions/spell-check/patterns/patterns.txt +++ b/.github/actions/spell-check/patterns/patterns.txt @@ -1,4 +1,4 @@ -https://(?:(?:[-a-zA-Z0-9?&=]*\.|)microsoft\.com)/[-a-zA-Z0-9?&=_\/.]* +https://(?:(?:[-a-zA-Z0-9?&=]*\.|)microsoft\.com)/[-a-zA-Z0-9?&=_#\/.]* https://aka\.ms/[-a-zA-Z0-9?&=\/_]* https://www.w3.org/[-a-zA-Z0-9?&=\/_#]* https://(?:(?:www\.|)youtube\.com|youtu.be)/[-a-zA-Z0-9?&=]* diff --git a/OpenConsole.sln b/OpenConsole.sln index bb55346956c..560dc62f757 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -6,6 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Terminal", "Terminal", "{59840756-302F-44DF-AA47-441A9D673202}" EndProject Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "CascadiaPackage", "src\cascadia\CascadiaPackage\CascadiaPackage.wapproj", "{CA5CAD1A-224A-4171-B13A-F16E576FDD12}" + ProjectSection(ProjectDependencies) = postProject + {F2ED628A-DB22-446F-A081-4CC845B51A2B} = {F2ED628A-DB22-446F-A081-4CC845B51A2B} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.EXE", "src\host\exe\Host.EXE.vcxproj", "{9CBD7DFA-1754-4A9D-93D7-857A9D17CB1B}" ProjectSection(ProjectDependencies) = postProject @@ -85,6 +88,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Host.Tests.Feature", "src\h {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} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalParser.UnitTests", "src\terminal\parser\ut_parser\Parser.UnitTests.vcxproj", "{12144E07-FE63-4D33-9231-748B8D8C3792}" @@ -188,6 +192,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalApp", "src\cascadia EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalSettings", "src\cascadia\TerminalSettings\TerminalSettings.vcxproj", "{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsTerminalShellExt", "src\cascadia\ShellExtension\WindowsTerminalShellExt.vcxproj", "{F2ED628A-DB22-446F-A081-4CC845B51A2B}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalCore", "src\cascadia\UnitTests_TerminalCore\UnitTests.vcxproj", "{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}" ProjectSection(ProjectDependencies) = postProject {06EC74CB-9A12-429C-B551-8562EC954747} = {06EC74CB-9A12-429C-B551-8562EC954747} @@ -1108,6 +1114,25 @@ Global {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x64.Build.0 = Release|x64 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x86.ActiveCfg = Release|Win32 {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907}.Release|x86.Build.0 = Release|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.AuditMode|Any CPU.ActiveCfg = Release|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.AuditMode|ARM64.ActiveCfg = Release|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.AuditMode|x64.ActiveCfg = Release|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.AuditMode|x64.Build.0 = Release|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.AuditMode|x86.ActiveCfg = Release|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x64.ActiveCfg = Debug|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x64.Build.0 = Debug|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x86.ActiveCfg = Debug|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Debug|x86.Build.0 = Debug|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|Any CPU.ActiveCfg = Release|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|ARM64.Build.0 = Release|ARM64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|x64.ActiveCfg = Release|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|x64.Build.0 = Release|x64 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|x86.ActiveCfg = Release|Win32 + {F2ED628A-DB22-446F-A081-4CC845B51A2B}.Release|x86.Build.0 = Release|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 {2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x64.ActiveCfg = AuditMode|x64 @@ -1558,6 +1583,7 @@ Global {CA5CAD1A-1754-4A9D-93D7-857A9D17CB1B} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202} {CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {59840756-302F-44DF-AA47-441A9D673202} + {F2ED628A-DB22-446F-A081-4CC845B51A2B} = {59840756-302F-44DF-AA47-441A9D673202} {2C2BEEF4-9333-4D05-B12A-1905CBF112F9} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB} {16376381-CE22-42BE-B667-C6B35007008D} = {81C352DB-1818-45B7-A284-18E259F1CC87} diff --git a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj index cfff16b6435..6fbd04d0d53 100644 --- a/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj +++ b/src/cascadia/CascadiaPackage/CascadiaPackage.wapproj @@ -64,7 +64,9 @@ + + diff --git a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest index a8ccfe6c73c..da2051a1711 100644 --- a/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Dev.appxmanifest @@ -3,9 +3,13 @@ @@ -39,7 +43,7 @@ Square150x150Logo="Images\Square150x150Logo.png" Square44x44Logo="Images\Square44x44Logo.png"> @@ -58,6 +62,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest index c69242ccb1b..ba258abe77c 100644 --- a/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-Pre.appxmanifest @@ -41,7 +41,7 @@ Square150x150Logo="Images\Square150x150Logo.png" Square44x44Logo="Images\Square44x44Logo.png"> @@ -60,6 +60,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/CascadiaPackage/Package.appxmanifest b/src/cascadia/CascadiaPackage/Package.appxmanifest index ad429698b69..c7dad075204 100644 --- a/src/cascadia/CascadiaPackage/Package.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package.appxmanifest @@ -41,7 +41,7 @@ Square150x150Logo="Images\Square150x150Logo.png" Square44x44Logo="Images\Square44x44Logo.png"> @@ -60,6 +60,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/cascadia/ShellExtension/OpenTerminalHere.cpp b/src/cascadia/ShellExtension/OpenTerminalHere.cpp new file mode 100644 index 00000000000..8091754832c --- /dev/null +++ b/src/cascadia/ShellExtension/OpenTerminalHere.cpp @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "OpenTerminalHere.h" + +// TODO GH#6112: Localize these strings +static constexpr std::wstring_view VerbDisplayName{ L"Open in Windows Terminal" }; +static constexpr std::wstring_view VerbDevBuildDisplayName{ L"Open in Windows Terminal (Dev Build)" }; +static constexpr std::wstring_view VerbName{ L"WindowsTerminalOpenHere" }; + +static constexpr std::wstring_view WtExe{ L"wt.exe" }; +static constexpr std::wstring_view WtdExe{ L"wtd.exe" }; +static constexpr std::wstring_view WindowsTerminalExe{ L"WindowsTerminal.exe" }; + +static constexpr std::wstring_view LocalAppDataAppsPath{ L"%LOCALAPPDATA%\\Microsoft\\WindowsApps\\" }; + +// This code is aggressively copied from +// https://github.com/microsoft/Windows-classic-samples/blob/master/Samples/ +// Win7Samples/winui/shell/appshellintegration/ExplorerCommandVerb/ExplorerCommandVerb.cpp + +// Function Description: +// - This is a helper to determine if we're running as a part of the Dev Build +// Package or the release package. We'll need to return different text, icons, +// and use different commandlines depending on which one the user requested. +// - Uses a C++11 "magic static" to make sure this is only computed once. +// - If we can't determine if it's the dev build or not, we'll default to true +// Arguments: +// - +// Return Value: +// - true if we believe this extension is being run in the dev build package. +static bool IsDevBuild() +{ + // use C++11 magic statics to make sure we only do this once. + static bool isDevBuild = []() -> bool { + try + { + const auto package{ winrt::Windows::ApplicationModel::Package::Current() }; + const auto id = package.Id(); + const std::wstring name{ id.FullName() }; + // Does our PFN start with WindowsTerminalDev? + return name.rfind(L"WindowsTerminalDev", 0) == 0; + } + CATCH_LOG(); + return true; + }(); + + return isDevBuild; +} + +// Function Description: +// - Helper function for getting the path to the appropriate executable to use +// for this instance of the shell extension. If we're running the dev build, +// it should be a `wtd.exe`, but if we're preview or release, we want to make +// sure to get the correct `wt.exe` that corresponds to _us_. +// - If we're unpackaged, this needs to get us `WindowsTerminal.exe`, because +// the `wt*exe` alias won't have been installed for this install. +// Arguments: +// - +// Return Value: +// - the full path to the exe, one of `wt.exe`, `wtd.exe`, or `WindowsTerminal.exe`. +static std::wstring _getExePath() +{ + // use C++11 magic statics to make sure we only do this once. + static const std::wstring exePath = []() -> std::wstring { + // First, check a packaged location for the exe. If we've got a package + // family name, that means we're one of the packaged Dev build, packaged + // Release build, or packaged Preview build. + // + // If we're the preview or release build, there's no way of knowing if the + // `wt.exe` on the %PATH% is us or not. Fortunately, _our_ execution alias + // is located in "%LOCALAPPDATA%\Microsoft\WindowsApps\", _always_, so we can use that to look up the exe easier. + try + { + const auto package{ winrt::Windows::ApplicationModel::Package::Current() }; + const auto id = package.Id(); + const std::wstring pfn{ id.FamilyName() }; + if (!pfn.empty()) + { + const std::filesystem::path windowsAppsPath{ wil::ExpandEnvironmentStringsW(LocalAppDataAppsPath.data()) }; + const std::filesystem::path wtPath = windowsAppsPath / pfn / (IsDevBuild() ? WtdExe : WtExe); + return wtPath; + } + } + CATCH_LOG(); + + // If we're here, then we couldn't resolve our exe from the package. This + // means we're running unpackaged. We should just use the + // WindowsTerminal.exe that's sitting in the directory next to us. + try + { + HMODULE hModule = GetModuleHandle(nullptr); + THROW_LAST_ERROR_IF(hModule == nullptr); + std::wstring dllPathString; + THROW_IF_FAILED(wil::GetModuleFileNameW(hModule, dllPathString)); + const std::filesystem::path dllPath{ dllPathString }; + const std::filesystem::path rootDir = dllPath.parent_path(); + std::filesystem::path wtPath = rootDir / WindowsTerminalExe; + return wtPath; + } + CATCH_LOG(); + + return L"wt.exe"; + }(); + return exePath; +} + +// Method Description: +// - This method is called when the user activates the context menu item. We'll +// launch the Terminal using the current working directory. +// Arguments: +// - psiItemArray: a IShellItemArray which contains the item that's selected. +// Return Value: +// - S_OK if we successfully attempted to launch the Terminal, otherwise a +// failure from an earlier HRESULT. +HRESULT OpenTerminalHere::Invoke(IShellItemArray* psiItemArray, + IBindCtx* /*pBindContext*/) +{ + DWORD count; + psiItemArray->GetCount(&count); + + winrt::com_ptr psi; + RETURN_IF_FAILED(psiItemArray->GetItemAt(0, psi.put())); + + wil::unique_cotaskmem_string pszName; + RETURN_IF_FAILED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszName)); + + { + wil::unique_process_information _piClient; + STARTUPINFOEX siEx{ 0 }; + siEx.StartupInfo.cb = sizeof(STARTUPINFOEX); + + // Append a "\." to the given path, so that this will work in "C:\" + std::wstring cmdline = fmt::format(L"\"{}\" -d \"{}\\.\"", _getExePath(), pszName.get()); + RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW( + nullptr, + cmdline.data(), + nullptr, // lpProcessAttributes + nullptr, // lpThreadAttributes + false, // bInheritHandles + EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT, // dwCreationFlags + nullptr, // lpEnvironment + nullptr, + &siEx.StartupInfo, // lpStartupInfo + &_piClient // lpProcessInformation + )); + } + + return S_OK; +} + +HRESULT OpenTerminalHere::GetToolTip(IShellItemArray* /*psiItemArray*/, + LPWSTR* ppszInfoTip) +{ + // tooltip provided here, in this case none is provided + *ppszInfoTip = nullptr; + return E_NOTIMPL; +} + +HRESULT OpenTerminalHere::GetTitle(IShellItemArray* /*psiItemArray*/, + LPWSTR* ppszName) +{ + // Change the string we return depending on if we're running from the dev + // build package or not. + const bool isDevBuild = IsDevBuild(); + return SHStrDup(isDevBuild ? VerbDevBuildDisplayName.data() : VerbDisplayName.data(), ppszName); +} + +HRESULT OpenTerminalHere::GetState(IShellItemArray* /*psiItemArray*/, + BOOL /*fOkToBeSlow*/, + EXPCMDSTATE* pCmdState) +{ + // compute the visibility of the verb here, respect "fOkToBeSlow" if this is + // slow (does IO for example) when called with fOkToBeSlow == FALSE return + // E_PENDING and this object will be called back on a background thread with + // fOkToBeSlow == TRUE + + // We however don't need to bother with any of that, so we'll just return + // ECS_ENABLED. + + *pCmdState = ECS_ENABLED; + return S_OK; +} + +HRESULT OpenTerminalHere::GetIcon(IShellItemArray* /*psiItemArray*/, + LPWSTR* ppszIcon) +{ + // the icon ref ("dll,-") is provided here, in this case none is provided + *ppszIcon = nullptr; + // TODO GH#6111: Return the Terminal icon here + return E_NOTIMPL; +} + +HRESULT OpenTerminalHere::GetFlags(EXPCMDFLAGS* pFlags) +{ + *pFlags = ECF_DEFAULT; + return S_OK; +} + +HRESULT OpenTerminalHere::GetCanonicalName(GUID* pguidCommandName) +{ + *pguidCommandName = __uuidof(this); + return S_OK; +} + +HRESULT OpenTerminalHere::EnumSubCommands(IEnumExplorerCommand** ppEnum) +{ + *ppEnum = nullptr; + return E_NOTIMPL; +} diff --git a/src/cascadia/ShellExtension/OpenTerminalHere.h b/src/cascadia/ShellExtension/OpenTerminalHere.h new file mode 100644 index 00000000000..5be0c0d370c --- /dev/null +++ b/src/cascadia/ShellExtension/OpenTerminalHere.h @@ -0,0 +1,51 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- OpenTerminalHere.h + +Abstract: +- This is the class that implements our Explorer Context Menu item. By + implementing IExplorerCommand, we can provide an entry to the context menu to + allow the user to open the Terminal in the current working directory. +- Importantly, we need to make sure to declare the GUID of this implementation + class explicitly, so we can refer to it in our manifest, and use it to create + instances of this class when the shell asks for one. +- This is defined as a WRL type, so that we can use WRL's CoCreatableClass magic + to create the class factory and module management for us. See more details in + dllmain.cpp. + +Author(s): +- Mike Griese - May 2020 + +--*/ +#pragma once + +#include +#include "../../cascadia/inc/cppwinrt_utils.h" + +using namespace Microsoft::WRL; + +struct __declspec(uuid("9f156763-7844-4dc4-b2b1-901f640f5155")) + OpenTerminalHere : public RuntimeClass, IExplorerCommand> +{ +#pragma region IExplorerCommand + HRESULT Invoke(IShellItemArray* psiItemArray, + IBindCtx* pBindContext); + HRESULT GetToolTip(IShellItemArray* psiItemArray, + LPWSTR* ppszInfoTip); + HRESULT GetTitle(IShellItemArray* psiItemArray, + LPWSTR* ppszName); + HRESULT GetState(IShellItemArray* psiItemArray, + BOOL fOkToBeSlow, + EXPCMDSTATE* pCmdState); + HRESULT GetIcon(IShellItemArray* psiItemArray, + LPWSTR* ppszIcon); + HRESULT GetFlags(EXPCMDFLAGS* pFlags); + HRESULT GetCanonicalName(GUID* pguidCommandName); + HRESULT EnumSubCommands(IEnumExplorerCommand** ppEnum); +#pragma endregion +}; + +CoCreatableClass(OpenTerminalHere); diff --git a/src/cascadia/ShellExtension/PlaceholderType.cpp b/src/cascadia/ShellExtension/PlaceholderType.cpp new file mode 100644 index 00000000000..dc45a6a1e47 --- /dev/null +++ b/src/cascadia/ShellExtension/PlaceholderType.cpp @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "PlaceholderType.h" +#include "PlaceholderType.g.cpp" + +namespace winrt::Microsoft::Terminal::ShellExtension::implementation +{ +} diff --git a/src/cascadia/ShellExtension/PlaceholderType.h b/src/cascadia/ShellExtension/PlaceholderType.h new file mode 100644 index 00000000000..d56395c9257 --- /dev/null +++ b/src/cascadia/ShellExtension/PlaceholderType.h @@ -0,0 +1,37 @@ +/*++ +Copyright (c) Microsoft Corporation +Licensed under the MIT license. + +Module Name: +- PlaceholderType.h + +Abstract: +- This class is just here to make our .wapproj play nicely with this project. If + we don't define any winrt types, then we won't generate a .winmd, and the + .wapproj will become _very_ mad at this project. So we'll use this placeholder + class just to trick cppwinrt into generating a winmd for us. If we ever _do_ + add a real winrt type to this project, this can be removed. + +Author(s): +- Mike Griese - May 2020 + +--*/ +#pragma once + +#include +#include "PlaceholderType.g.h" +#include "../../cascadia/inc/cppwinrt_utils.h" + +namespace winrt::Microsoft::Terminal::ShellExtension::implementation +{ + struct PlaceholderType : PlaceholderTypeT + { + PlaceholderType() = default; + GETSET_PROPERTY(int32_t, Placeholder, 42); + }; +} + +namespace winrt::Microsoft::Terminal::ShellExtension::factory_implementation +{ + BASIC_FACTORY(PlaceholderType); +} diff --git a/src/cascadia/ShellExtension/PlaceholderType.idl b/src/cascadia/ShellExtension/PlaceholderType.idl new file mode 100644 index 00000000000..0dbe7adfacc --- /dev/null +++ b/src/cascadia/ShellExtension/PlaceholderType.idl @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +// This class is just here to make our .wapproj play nicely with this project. +// If we don't define any winrt types, then we won't generate a .winmd, and the +// .wapproj will become _very_ mad at this project. So we'll use this +// placeholder class just to trick cppwinrt into generating a winmd for us. If +// we ever _do_ add a real winrt type to this project, this can be removed. + +namespace Microsoft.Terminal.ShellExtension +{ + [default_interface] runtimeclass PlaceholderType { + PlaceholderType(); + Int32 Placeholder + { + get; + set; + }; + }; + +} diff --git a/src/cascadia/ShellExtension/WindowsTerminalShellExt.def b/src/cascadia/ShellExtension/WindowsTerminalShellExt.def new file mode 100644 index 00000000000..d0e5f0b59d3 --- /dev/null +++ b/src/cascadia/ShellExtension/WindowsTerminalShellExt.def @@ -0,0 +1,4 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE +DllGetClassObject PRIVATE diff --git a/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj b/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj new file mode 100644 index 00000000000..12565176959 --- /dev/null +++ b/src/cascadia/ShellExtension/WindowsTerminalShellExt.vcxproj @@ -0,0 +1,68 @@ + + + + {f2ed628a-db22-446f-a081-4cc845b51a2b} + WindowsTerminalShellExt + Microsoft.Terminal.ShellExtension + + + DynamicLibrary + Console + + true + + true + + + + + + + + + + PlaceholderType.idl + + + + + Create + + + PlaceholderType.idl + + + + + + + + + + + + + + + + + + {18D09A24-8240-42D6-8CB6-236EEE820263} + + + {CA5CAD1A-039A-4929-BA2A-8BEB2E4106FE} + false + + + + + + diff --git a/src/cascadia/ShellExtension/dllmain.cpp b/src/cascadia/ShellExtension/dllmain.cpp new file mode 100644 index 00000000000..d7c93e96f31 --- /dev/null +++ b/src/cascadia/ShellExtension/dllmain.cpp @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" +#include "OpenTerminalHere.h" + +// For reference, see: +// * https://docs.microsoft.com/en-us/cpp/cppcx/wrl/how-to-create-a-classic-com-component-using-wrl?view=vs-2019 +// * https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/move-to-winrt-from-wrl#porting-a-wrl-module-microsoftwrlmodule +// +// We don't need to implement DllGetActivationFactory or DllCanUnloadNow +// manually, since the generated module.g.cpp will handle it for us, and will +// handle our WRL types appropriately. +// +// We DO need to implement DllGetClassObject, because that's what explorer.exe +// will call to attempt to create a class factory for our shell extension. The +// CoCreatableClass macro in OpenTerminalHere.h will create the factory for us, +// so that the GetClassObject call will work like magic. + +STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, _COM_Outptr_ void** ppv) +{ + return Microsoft::WRL::Module::GetModule().GetClassObject(rclsid, riid, ppv); +} + +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/cascadia/ShellExtension/packages.config b/src/cascadia/ShellExtension/packages.config new file mode 100644 index 00000000000..8db4233e6a9 --- /dev/null +++ b/src/cascadia/ShellExtension/packages.config @@ -0,0 +1,4 @@ + + + + diff --git a/src/cascadia/ShellExtension/pch.cpp b/src/cascadia/ShellExtension/pch.cpp new file mode 100644 index 00000000000..3c27d44d570 --- /dev/null +++ b/src/cascadia/ShellExtension/pch.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#include "pch.h" diff --git a/src/cascadia/ShellExtension/pch.h b/src/cascadia/ShellExtension/pch.h new file mode 100644 index 00000000000..5962c68100a --- /dev/null +++ b/src/cascadia/ShellExtension/pch.h @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// pch.h +// Header for platform projection include files +// + +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#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 diff --git a/src/host/ft_host/Host.FeatureTests.vcxproj b/src/host/ft_host/Host.FeatureTests.vcxproj index b31c4ef4490..e62dc672862 100644 --- a/src/host/ft_host/Host.FeatureTests.vcxproj +++ b/src/host/ft_host/Host.FeatureTests.vcxproj @@ -44,7 +44,7 @@ {18d09a24-8240-42d6-8cb6-236eee820263} - + {58a03bb2-df5a-4b66-91a0-7ef3ba01269a} @@ -59,9 +59,4 @@ - - - $(OutDir)\conpty.lib;%(AdditionalDependencies) - - - \ No newline at end of file +