mirror of
https://github.com/microsoft/terminal.git
synced 2026-05-21 14:27:22 +00:00
Merge branch 'main' into dev/migrie/oop/3/feanor-and-the-unchaining-of-melkor
This commit is contained in:
19
.github/actions/spelling/expect/expect.txt
vendored
19
.github/actions/spelling/expect/expect.txt
vendored
@@ -193,7 +193,6 @@ chh
|
||||
chk
|
||||
CHT
|
||||
Cic
|
||||
CLA
|
||||
Clcompile
|
||||
CLE
|
||||
cleartype
|
||||
@@ -480,7 +479,6 @@ defterm
|
||||
DELAYLOAD
|
||||
DELETEONRELEASE
|
||||
Delt
|
||||
demoable
|
||||
depersist
|
||||
deprioritized
|
||||
deserializers
|
||||
@@ -537,7 +535,6 @@ DSSCL
|
||||
DSwap
|
||||
DTest
|
||||
DTTERM
|
||||
DUMMYUNIONNAME
|
||||
dup'ed
|
||||
dvi
|
||||
dwl
|
||||
@@ -590,7 +587,6 @@ ETW
|
||||
EUDC
|
||||
EVENTID
|
||||
eventing
|
||||
everytime
|
||||
evflags
|
||||
evt
|
||||
execd
|
||||
@@ -802,7 +798,6 @@ HIBYTE
|
||||
hicon
|
||||
HIDEWINDOW
|
||||
hinst
|
||||
Hirots
|
||||
HISTORYBUFS
|
||||
HISTORYNODUP
|
||||
HISTORYSIZE
|
||||
@@ -903,7 +898,6 @@ INSERTMODE
|
||||
INTERACTIVITYBASE
|
||||
INTERCEPTCOPYPASTE
|
||||
INTERNALNAME
|
||||
inthread
|
||||
intsafe
|
||||
INVALIDARG
|
||||
INVALIDATERECT
|
||||
@@ -1260,14 +1254,12 @@ ntm
|
||||
nto
|
||||
ntrtl
|
||||
ntstatus
|
||||
ntsubauth
|
||||
NTSYSCALLAPI
|
||||
nttree
|
||||
nturtl
|
||||
ntuser
|
||||
NTVDM
|
||||
ntverp
|
||||
NTWIN
|
||||
nugetversions
|
||||
nullability
|
||||
nullness
|
||||
@@ -1306,8 +1298,6 @@ opencode
|
||||
opencon
|
||||
openconsole
|
||||
openconsoleproxy
|
||||
OPENIF
|
||||
OPENLINK
|
||||
openps
|
||||
openvt
|
||||
ORIGINALFILENAME
|
||||
@@ -1360,9 +1350,7 @@ pcg
|
||||
pch
|
||||
PCIDLIST
|
||||
PCIS
|
||||
PCLIENT
|
||||
PCLONG
|
||||
PCOBJECT
|
||||
pcon
|
||||
PCONSOLE
|
||||
PCONSOLEENDTASK
|
||||
@@ -1374,7 +1362,6 @@ pcshell
|
||||
PCSHORT
|
||||
PCSR
|
||||
PCSTR
|
||||
PCUNICODE
|
||||
PCWCH
|
||||
PCWCHAR
|
||||
PCWSTR
|
||||
@@ -1423,7 +1410,6 @@ PLOGICAL
|
||||
pnm
|
||||
PNMLINK
|
||||
pntm
|
||||
PNTSTATUS
|
||||
POBJECT
|
||||
Podcast
|
||||
POINTSLIST
|
||||
@@ -1442,7 +1428,6 @@ ppf
|
||||
ppguid
|
||||
ppidl
|
||||
PPROC
|
||||
PPROCESS
|
||||
ppropvar
|
||||
ppsi
|
||||
ppsl
|
||||
@@ -1506,7 +1491,6 @@ ptrs
|
||||
ptsz
|
||||
PTYIn
|
||||
PUCHAR
|
||||
PUNICODE
|
||||
pwch
|
||||
PWDDMCONSOLECONTEXT
|
||||
pws
|
||||
@@ -1568,7 +1552,6 @@ REGISTEROS
|
||||
REGISTERVDM
|
||||
regkey
|
||||
REGSTR
|
||||
reingest
|
||||
RELBINPATH
|
||||
remoting
|
||||
renamer
|
||||
@@ -1863,6 +1846,7 @@ TDP
|
||||
TEAMPROJECT
|
||||
tearoff
|
||||
Teb
|
||||
Techo
|
||||
tellp
|
||||
teraflop
|
||||
terminalcore
|
||||
@@ -2005,7 +1989,6 @@ unittesting
|
||||
unittests
|
||||
unk
|
||||
unknwn
|
||||
unmark
|
||||
UNORM
|
||||
unparseable
|
||||
unregistering
|
||||
|
||||
27
.github/workflows/winget.yml
vendored
Normal file
27
.github/workflows/winget.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Publish to Winget
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
REGEX: 'Microsoft\.WindowsTerminal(?:Preview)?_Win10_([\d.]+)_8wekyb3d8bbwe\.msixbundle$'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: windows-latest # Action can only run on Windows
|
||||
steps:
|
||||
- name: Extract version from release asset
|
||||
id: extract-version
|
||||
run: |
|
||||
$version = '${{ toJSON(github.event.release.assets.*.name) }}' | ConvertFrom-Json | Select-String -Pattern $env:REGEX | ForEach-Object { $_.Matches.Groups[1].Value }
|
||||
Write-Output "version=$version" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Publish ${{ github.event.release.prerelease && 'Preview' || 'Stable' }}
|
||||
uses: vedantmgoyal2009/winget-releaser@v2
|
||||
with:
|
||||
identifier: Microsoft.WindowsTerminal${{ github.event.release.prerelease && '.Preview' || '' }}
|
||||
version: ${{ steps.extract-version.outputs.version }}
|
||||
installers-regex: ${{ env.REGEX }}
|
||||
token: ${{ secrets.WINGET_TOKEN }}
|
||||
fork-user: DHowett
|
||||
@@ -133,7 +133,12 @@ namespace winrt::TerminalApp::implementation
|
||||
// cause you to chase down the rabbit hole of "why is App not
|
||||
// registered?" when it definitely is.
|
||||
|
||||
_isElevated = ::Microsoft::Console::Utils::IsElevated();
|
||||
// The TerminalPage has to be constructed during our construction, to
|
||||
// make sure that there's a terminal page for callers of
|
||||
// SetTitleBarContent
|
||||
|
||||
_isElevated = ::Microsoft::Console::Utils::IsRunningElevated();
|
||||
_canDragDrop = ::Microsoft::Console::Utils::CanUwpDragDrop();
|
||||
|
||||
_reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
|
||||
if (auto self{ weakSelf.get() })
|
||||
@@ -164,10 +169,14 @@ namespace winrt::TerminalApp::implementation
|
||||
// - <none> - reports internal state
|
||||
// Return Value:
|
||||
// - True if elevated, false otherwise.
|
||||
bool AppLogic::IsElevated() const noexcept
|
||||
bool AppLogic::IsRunningElevated() const noexcept
|
||||
{
|
||||
return _isElevated;
|
||||
}
|
||||
bool AppLogic::CanDragDrop() const noexcept
|
||||
{
|
||||
return _canDragDrop;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called by UWP context invoker to let us know that we may have to change some of our behaviors
|
||||
|
||||
@@ -49,7 +49,8 @@ namespace winrt::TerminalApp::implementation
|
||||
void Create();
|
||||
bool IsUwp() const noexcept;
|
||||
void RunAsUwp();
|
||||
bool IsElevated() const noexcept;
|
||||
bool IsRunningElevated() const noexcept;
|
||||
bool CanDragDrop() const noexcept;
|
||||
void ReloadSettings();
|
||||
|
||||
bool HasSettingsStartupActions() const noexcept;
|
||||
@@ -77,6 +78,7 @@ namespace winrt::TerminalApp::implementation
|
||||
private:
|
||||
bool _isUwp{ false };
|
||||
bool _isElevated{ false };
|
||||
bool _canDragDrop{ false };
|
||||
|
||||
Microsoft::Terminal::Settings::Model::CascadiaSettings _settings{ nullptr };
|
||||
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace TerminalApp
|
||||
|
||||
Boolean IsUwp();
|
||||
void RunAsUwp();
|
||||
Boolean IsElevated();
|
||||
Boolean IsRunningElevated();
|
||||
Boolean CanDragDrop();
|
||||
|
||||
Boolean HasSettingsStartupActions();
|
||||
|
||||
|
||||
@@ -128,27 +128,26 @@ namespace winrt::TerminalApp::implementation
|
||||
_systemRowsToScroll = _ReadSystemRowsToScroll();
|
||||
}
|
||||
|
||||
bool TerminalPage::IsElevated() const noexcept
|
||||
bool TerminalPage::IsRunningElevated() const noexcept
|
||||
{
|
||||
// use C++11 magic statics to make sure we only do this once.
|
||||
// This won't change over the lifetime of the application
|
||||
|
||||
static const auto isElevated = []() {
|
||||
// *** THIS IS A SINGLETON ***
|
||||
auto result = false;
|
||||
|
||||
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
||||
// because that _won't_ be an instance of TerminalApp::App in the
|
||||
// LocalTests
|
||||
try
|
||||
{
|
||||
result = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
|
||||
}
|
||||
CATCH_LOG();
|
||||
return result;
|
||||
}();
|
||||
|
||||
return isElevated;
|
||||
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
||||
// because that _won't_ be an instance of TerminalApp::App in the
|
||||
// LocalTests
|
||||
try
|
||||
{
|
||||
return Application::Current().as<TerminalApp::App>().Logic().IsRunningElevated();
|
||||
}
|
||||
CATCH_LOG();
|
||||
return false;
|
||||
}
|
||||
bool TerminalPage::CanDragDrop() const noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return Application::Current().as<TerminalApp::App>().Logic().CanDragDrop();
|
||||
}
|
||||
CATCH_LOG();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TerminalPage::Create()
|
||||
@@ -161,11 +160,11 @@ namespace winrt::TerminalApp::implementation
|
||||
_tabView = _tabRow.TabView();
|
||||
_rearranging = false;
|
||||
|
||||
const auto isElevated = IsElevated();
|
||||
const auto canDragDrop = CanDragDrop();
|
||||
|
||||
_tabRow.PointerMoved({ get_weak(), &TerminalPage::_RestorePointerCursorHandler });
|
||||
_tabView.CanReorderTabs(!isElevated);
|
||||
_tabView.CanDragTabs(!isElevated);
|
||||
_tabView.CanReorderTabs(canDragDrop);
|
||||
_tabView.CanDragTabs(canDragDrop);
|
||||
_tabView.TabDragStarting({ get_weak(), &TerminalPage::_TabDragStarted });
|
||||
_tabView.TabDragCompleted({ get_weak(), &TerminalPage::_TabDragCompleted });
|
||||
|
||||
@@ -284,7 +283,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// Setup mouse vanish attributes
|
||||
SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &_shouldMouseVanish, false);
|
||||
|
||||
_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());
|
||||
_tabRow.ShowElevationShield(IsRunningElevated() && _settings.GlobalSettings().ShowAdminShield());
|
||||
|
||||
// Store cursor, so we can restore it, e.g., after mouse vanishing
|
||||
// (we'll need to adapt this logic once we make cursor context aware)
|
||||
@@ -311,7 +310,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// GH#12267: Don't forget about defterm handoff here. If we're being
|
||||
// created for embedding, then _yea_, we don't need to handoff to an
|
||||
// elevated window.
|
||||
if (!_startupActions || IsElevated() || _shouldStartInboundListener || _startupActions.Size() == 0)
|
||||
if (!_startupActions || IsRunningElevated() || _shouldStartInboundListener || _startupActions.Size() == 0)
|
||||
{
|
||||
// there aren't startup actions, or we're elevated. In that case, go for it.
|
||||
return false;
|
||||
@@ -1103,7 +1102,7 @@ namespace winrt::TerminalApp::implementation
|
||||
WI_IsFlagSet(lAltState, CoreVirtualKeyStates::Down) &&
|
||||
WI_IsFlagSet(rAltState, CoreVirtualKeyStates::Down);
|
||||
|
||||
const auto dispatchToElevatedWindow = ctrlPressed && !IsElevated();
|
||||
const auto dispatchToElevatedWindow = ctrlPressed && !IsRunningElevated();
|
||||
|
||||
if ((shiftPressed || dispatchToElevatedWindow) && !debugTap)
|
||||
{
|
||||
@@ -2869,7 +2868,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// want to create an animation.
|
||||
WUX::Media::Animation::Timeline::AllowDependentAnimations(!_settings.GlobalSettings().DisableAnimations());
|
||||
|
||||
_tabRow.ShowElevationShield(IsElevated() && _settings.GlobalSettings().ShowAdminShield());
|
||||
_tabRow.ShowElevationShield(IsRunningElevated() && _settings.GlobalSettings().ShowAdminShield());
|
||||
|
||||
Media::SolidColorBrush transparent{ Windows::UI::Colors::Transparent() };
|
||||
_tabView.Background(transparent);
|
||||
@@ -3956,7 +3955,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
// Try to handle auto-elevation
|
||||
const auto requestedElevation = controlSettings.DefaultSettings().Elevate();
|
||||
const auto currentlyElevated = IsElevated();
|
||||
const auto currentlyElevated = IsRunningElevated();
|
||||
|
||||
// We aren't elevated, but we want to be.
|
||||
if (requestedElevation && !currentlyElevated)
|
||||
|
||||
@@ -126,7 +126,8 @@ namespace winrt::TerminalApp::implementation
|
||||
|
||||
TerminalApp::WindowProperties WindowProperties() const noexcept { return _WindowProperties; };
|
||||
|
||||
bool IsElevated() const noexcept;
|
||||
bool CanDragDrop() const noexcept;
|
||||
bool IsRunningElevated() const noexcept;
|
||||
|
||||
void OpenSettingsUI();
|
||||
void WindowActivated(const bool activated);
|
||||
|
||||
@@ -202,35 +202,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return isUwp;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Called around the codebase to discover if Terminal is running elevated
|
||||
// Arguments:
|
||||
// - <none> - reports internal state
|
||||
// Return Value:
|
||||
// - True if elevated, false otherwise.
|
||||
bool TerminalWindow::IsElevated() const noexcept
|
||||
{
|
||||
// use C++11 magic statics to make sure we only do this once.
|
||||
// This won't change over the lifetime of the application
|
||||
|
||||
static const auto isElevated = []() {
|
||||
// *** THIS IS A SINGLETON ***
|
||||
auto result = false;
|
||||
|
||||
// GH#2455 - Make sure to try/catch calls to Application::Current,
|
||||
// because that _won't_ be an instance of TerminalApp::App in the
|
||||
// LocalTests
|
||||
try
|
||||
{
|
||||
result = ::winrt::Windows::UI::Xaml::Application::Current().as<::winrt::TerminalApp::App>().Logic().IsElevated();
|
||||
}
|
||||
CATCH_LOG();
|
||||
return result;
|
||||
}();
|
||||
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Build the UI for the terminal app. Before this method is called, it
|
||||
// should not be assumed that the TerminalApp is usable. The Settings
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace winrt::TerminalApp::implementation
|
||||
void Create();
|
||||
|
||||
bool IsUwp() const noexcept;
|
||||
bool IsElevated() const noexcept;
|
||||
|
||||
void Quit();
|
||||
|
||||
|
||||
@@ -51,8 +51,6 @@ namespace TerminalApp
|
||||
// registered?" when it definitely is.
|
||||
void Create();
|
||||
|
||||
Boolean IsElevated();
|
||||
|
||||
Boolean HasCommandlineArguments();
|
||||
|
||||
Int32 SetStartupCommandline(String[] commands);
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// from state.json. We'll then load the Local props from
|
||||
// `elevated-state.json`
|
||||
// - If we're unelevated, then load _everything_ from state.json.
|
||||
if (::Microsoft::Console::Utils::IsElevated())
|
||||
if (::Microsoft::Console::Utils::IsRunningElevated())
|
||||
{
|
||||
// Only load shared properties if we're elevated
|
||||
FromJson(root, FileSource::Shared);
|
||||
@@ -225,7 +225,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
//
|
||||
// After that's done, we'll write our Local properties into
|
||||
// elevated-state.json.
|
||||
if (::Microsoft::Console::Utils::IsElevated())
|
||||
if (::Microsoft::Console::Utils::IsRunningElevated())
|
||||
{
|
||||
std::string errs;
|
||||
std::unique_ptr<Json::CharReader> reader{ Json::CharReaderBuilder{}.newCharReader() };
|
||||
@@ -353,7 +353,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// permissions, so we don't potentially read malicious data.
|
||||
std::optional<std::string> ApplicationState::_readLocalContents() const
|
||||
{
|
||||
return ::Microsoft::Console::Utils::IsElevated() ?
|
||||
return ::Microsoft::Console::Utils::IsRunningElevated() ?
|
||||
ReadUTF8FileIfExists(_elevatedPath, true) :
|
||||
ReadUTF8FileIfExists(_sharedPath, false);
|
||||
}
|
||||
@@ -374,7 +374,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
// will atomically write to `user-state.json`
|
||||
void ApplicationState::_writeLocalContents(const std::string_view content) const
|
||||
{
|
||||
if (::Microsoft::Console::Utils::IsElevated())
|
||||
if (::Microsoft::Console::Utils::IsRunningElevated())
|
||||
{
|
||||
// DON'T use WriteUTF8FileAtomic, which will write to a temporary file
|
||||
// then rename that file to the final filename. That actually lets us
|
||||
|
||||
@@ -50,6 +50,7 @@ private:
|
||||
std::vector<winrt::Microsoft::Terminal::Settings::Model::GlobalSummonArgs> _hotkeys;
|
||||
|
||||
std::unique_ptr<NotificationIcon> _notificationIcon;
|
||||
|
||||
bool _quitting{ false };
|
||||
|
||||
void _windowStartedHandler(const std::shared_ptr<WindowThread>& sender);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<AdditionalOptions>%(AdditionalOptions) /defaultlib:ucrtd.lib</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and '$(Configuration)'=='Release'">
|
||||
<ItemDefinitionGroup Condition="'$(EnableHybridCRT)'=='true' and ('$(Configuration)'=='Release' or '$(Configuration)'=='AuditMode')">
|
||||
<ClCompile>
|
||||
<!-- We use MultiThreaded, rather than MultiThreadedDLL, to avoid DLL dependencies on VCRUNTIME140.dll and MSVCP140.dll. -->
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
|
||||
@@ -81,12 +81,26 @@
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<!--
|
||||
We don't need to use HybridCRT for Fuzzing, so just skip it entirely.
|
||||
Fuzzing requires the address sanitizer runtime library plus the fuzzing
|
||||
harness. They're probably not compatible.
|
||||
|
||||
Audit, however, *does* require linking components built in Release mode...
|
||||
-->
|
||||
<ConfigurationSupportsHybridCRT Condition="'$(Configuration)'=='Fuzzing'">false</ConfigurationSupportsHybridCRT>
|
||||
<ConfigurationSupportsHybridCRT Condition="'$(ConfigurationSupportsHybridCRT)'==''">true</ConfigurationSupportsHybridCRT>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- For ALL build types-->
|
||||
<PropertyGroup Label="Configuration">
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
<EnableHybridCRT Condition="'$(EnableHybridCRT)'=='' and '$(ConfigurationSupportsHybridCRT)'=='true'">true</EnableHybridCRT>
|
||||
<UseCrtSDKReferenceStaticWarning Condition="'$(EnableHybridCRT)'=='true'">false</UseCrtSDKReferenceStaticWarning>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
|
||||
@@ -20,7 +20,7 @@ bool INPUT_READ_HANDLE_DATA::IsInputPending() const
|
||||
|
||||
bool INPUT_READ_HANDLE_DATA::IsMultilineInput() const
|
||||
{
|
||||
FAIL_FAST_IF(!_isInputPending); // we shouldn't have multiline input without a pending input.
|
||||
assert(_isInputPending); // we shouldn't have multiline input without a pending input.
|
||||
return _isMultilineInput;
|
||||
}
|
||||
|
||||
|
||||
@@ -1019,27 +1019,43 @@ void COOKED_READ_DATA::SavePendingInput(const size_t index, const bool multiline
|
||||
}
|
||||
|
||||
Tracing::s_TraceCookedRead(_clientProcess, _backupLimit, base::saturated_cast<ULONG>(idx));
|
||||
ProcessAliases(LineCount);
|
||||
|
||||
// Don't be fooled by ProcessAliases only taking one argument. It rewrites multiple
|
||||
// class members on return, including `_bytesRead`, requiring us to reconstruct `input`.
|
||||
ProcessAliases(LineCount);
|
||||
input = { _backupLimit, _bytesRead / sizeof(wchar_t) };
|
||||
|
||||
// The exact reasons for this are unclear to me (the one writing this comment), but this code used to
|
||||
// split the contents of a multiline alias (for instance `doskey test=echo foo$Techo bar$Techo baz`)
|
||||
// into multiple separate read outputs, ensuring that the client receives them line by line.
|
||||
//
|
||||
// This code first truncates the `input` to only contain the first line, so that Consume() below only
|
||||
// writes that line into the user buffer. We'll later store the remainder in SaveMultilinePendingInput().
|
||||
if (LineCount > 1)
|
||||
{
|
||||
input = input.substr(0, idx + 1);
|
||||
// ProcessAliases() is supposed to end each line with \r\n. If it doesn't we might as well fail-fast.
|
||||
const auto firstLineEnd = input.find(UNICODE_LINEFEED) + 1;
|
||||
input = input.substr(0, std::min(input.size(), firstLineEnd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto inputSizeBefore = input.size();
|
||||
GetInputBuffer()->Consume(isUnicode, input, writer);
|
||||
|
||||
if (!input.empty())
|
||||
if (LineCount > 1)
|
||||
{
|
||||
if (LineCount > 1)
|
||||
{
|
||||
GetInputReadHandleData()->SaveMultilinePendingInput(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetInputReadHandleData()->SavePendingInput(input);
|
||||
}
|
||||
// This is a continuation of the above identical if condition.
|
||||
// We've truncated the `input` slice and now we need to restore it.
|
||||
const auto inputSizeAfter = input.size();
|
||||
const auto amountConsumed = inputSizeBefore - inputSizeAfter;
|
||||
input = { _backupLimit, _bytesRead / sizeof(wchar_t) };
|
||||
input = input.substr(std::min(input.size(), amountConsumed));
|
||||
GetInputReadHandleData()->SaveMultilinePendingInput(input);
|
||||
}
|
||||
else if (!input.empty())
|
||||
{
|
||||
GetInputReadHandleData()->SavePendingInput(input);
|
||||
}
|
||||
|
||||
numBytes = _userBufferSize - writer.size();
|
||||
|
||||
@@ -288,28 +288,36 @@ try
|
||||
{
|
||||
bytesRead = 0;
|
||||
|
||||
auto pending = readHandleState.GetPendingInput();
|
||||
const auto pending = readHandleState.GetPendingInput();
|
||||
auto input = pending;
|
||||
|
||||
// This is basically the continuation of COOKED_READ_DATA::_handlePostCharInputLoop.
|
||||
if (readHandleState.IsMultilineInput())
|
||||
{
|
||||
const auto idx = pending.find(UNICODE_LINEFEED);
|
||||
if (idx != decltype(pending)::npos)
|
||||
{
|
||||
// +1 to include the newline.
|
||||
pending = pending.substr(0, idx + 1);
|
||||
}
|
||||
const auto firstLineEnd = input.find(UNICODE_LINEFEED) + 1;
|
||||
input = input.substr(0, std::min(input.size(), firstLineEnd));
|
||||
}
|
||||
|
||||
const auto inputSizeBefore = input.size();
|
||||
std::span writer{ buffer };
|
||||
inputBuffer.Consume(unicode, pending, writer);
|
||||
inputBuffer.Consume(unicode, input, writer);
|
||||
|
||||
if (pending.empty())
|
||||
// Since we truncated `input` to only include the first line,
|
||||
// we need to restore `input` here to the entirety of the remaining input.
|
||||
if (readHandleState.IsMultilineInput())
|
||||
{
|
||||
const auto inputSizeAfter = input.size();
|
||||
const auto amountConsumed = inputSizeBefore - inputSizeAfter;
|
||||
input = pending.substr(std::min(pending.size(), amountConsumed));
|
||||
}
|
||||
|
||||
if (input.empty())
|
||||
{
|
||||
readHandleState.CompletePending();
|
||||
}
|
||||
else
|
||||
{
|
||||
readHandleState.UpdatePending(pending);
|
||||
readHandleState.UpdatePending(input);
|
||||
}
|
||||
|
||||
bytesRead = buffer.size() - writer.size();
|
||||
|
||||
@@ -96,7 +96,8 @@ namespace Microsoft::Console::Utils
|
||||
|
||||
GUID CreateV5Uuid(const GUID& namespaceGuid, const std::span<const std::byte> name);
|
||||
|
||||
bool IsElevated();
|
||||
bool CanUwpDragDrop();
|
||||
bool IsRunningElevated();
|
||||
|
||||
// This function is only ever used by the ConPTY connection in
|
||||
// TerminalConnection. However, that library does not have a good system of
|
||||
|
||||
@@ -653,9 +653,18 @@ GUID Utils::CreateV5Uuid(const GUID& namespaceGuid, const std::span<const std::b
|
||||
return EndianSwap(newGuid);
|
||||
}
|
||||
|
||||
bool Utils::IsElevated()
|
||||
// * Elevated users cannot use the modern drag drop experience. This is
|
||||
// specifically normal users running the Terminal as admin
|
||||
// * The Default Administrator, who does not have a split token, CAN drag drop
|
||||
// perfectly fine. So in that case, we want to return false.
|
||||
// * This has to be kept separate from IsRunningElevated, which is exclusively
|
||||
// used for "is this instance running as admin".
|
||||
bool Utils::CanUwpDragDrop()
|
||||
{
|
||||
static auto isElevated = []() {
|
||||
// There's a lot of wacky double negatives here so that the logic is
|
||||
// basically the same as IsRunningElevated, but the end result semantically
|
||||
// makes sense as "CanDragDrop".
|
||||
static auto isDragDropBroken = []() {
|
||||
try
|
||||
{
|
||||
wil::unique_handle processToken{ GetCurrentProcessToken() };
|
||||
@@ -670,8 +679,30 @@ bool Utils::IsElevated()
|
||||
//
|
||||
// See GH#7754, GH#11096
|
||||
return false;
|
||||
// drag drop is _not_ broken -> they _can_ drag drop
|
||||
}
|
||||
|
||||
// If they are running admin, they cannot drag drop.
|
||||
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
// This failed? That's very peculiar indeed. Let's err on the side
|
||||
// of "drag drop is broken", just in case.
|
||||
return true;
|
||||
}
|
||||
}();
|
||||
|
||||
return !isDragDropBroken;
|
||||
}
|
||||
|
||||
// See CanUwpDragDrop, GH#13928 for why this is different.
|
||||
bool Utils::IsRunningElevated()
|
||||
{
|
||||
static auto isElevated = []() {
|
||||
try
|
||||
{
|
||||
return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
|
||||
}
|
||||
catch (...)
|
||||
|
||||
Reference in New Issue
Block a user