Enable /permissive- and remaining /Zc flags

This commit is contained in:
Leonard Hecker 2021-11-25 00:28:27 +01:00
parent f2386de422
commit 1d6818829e
36 changed files with 283 additions and 374 deletions

View file

@ -69,7 +69,8 @@
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\Generated Files";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\Generated Files";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<!-- Required for JsonUtils.h. -->
<AdditionalOptions>%(AdditionalOptions) /Zc:twoPhase-</AdditionalOptions>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. --> <!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile> </ClCompile>

View file

@ -51,10 +51,10 @@
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<!-- Disable two-phase name lookup for C++/CLI & C++/CX code. -->
<AdditionalOptions>%(AdditionalOptions) /Zc:twoPhase-</AdditionalOptions>
<DisableSpecificWarnings>4453;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4453;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories) <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(IntermediateOutputPath)</AdditionalIncludeDirectories>
;$(IntermediateOutputPath)
</AdditionalIncludeDirectories>
<PreprocessorDefinitions>INLINE_TEST_METHOD_MARKUP;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>INLINE_TEST_METHOD_MARKUP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>

View file

@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. // Copyright (c) Microsoft Corporation.
// Licensed under the MIT license. // Licensed under the MIT license.
// //
// pch.h // pch.h
@ -57,6 +57,7 @@
TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider); TRACELOGGING_DECLARE_PROVIDER(g_hTerminalControlProvider);
#include <telemetry/ProjectTelemetry.h> #include <telemetry/ProjectTelemetry.h>
#include <ShlObj_core.h>
#include <WinUser.h> #include <WinUser.h>
#include "til.h" #include "til.h"

View file

@ -250,6 +250,8 @@
<ClCompile> <ClCompile>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<!-- Required for JsonUtils.h. -->
<AdditionalOptions>%(AdditionalOptions) /Zc:twoPhase-</AdditionalOptions>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. --> <!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile> </ClCompile>

View file

@ -171,7 +171,7 @@ public:
auto mismatched = (actualChars != expectedChars || actualAttrs != expectedAttrs); auto mismatched = (actualChars != expectedChars || actualAttrs != expectedAttrs);
if (mismatched) if (mismatched)
{ {
Log::Comment(NoThrowString().Format( WEX::Logging::Log::Comment(WEX::Common::NoThrowString().Format(
L"Character or attribute at index %d was mismatched", charsProcessed)); L"Character or attribute at index %d was mismatched", charsProcessed));
} }

View file

@ -60,7 +60,8 @@
<ClCompile> <ClCompile>
<AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\Generated Files";"$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\Generated Files";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..;$(OpenConsoleDir)\dep\jsoncpp\json;$(OpenConsoleDir)src\inc;$(OpenConsoleDir)src\inc\test;$(WinRT_IncludePath)\..\cppwinrt\winrt;"$(OpenConsoleDir)\src\cascadia\TerminalApp\Generated Files";"$(OpenConsoleDir)\src\cascadia\TerminalSettingsModel\Generated Files";%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
<!-- Required for JsonUtils.h. -->
<AdditionalOptions>%(AdditionalOptions) /Zc:twoPhase-</AdditionalOptions>
<!-- Manually disable unreachable code warning, because jconcpp has a ton of that. --> <!-- Manually disable unreachable code warning, because jconcpp has a ton of that. -->
<DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>4702;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile> </ClCompile>

View file

@ -116,9 +116,11 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild> <MinimalRebuild>false</MinimalRebuild>
<RuntimeTypeInfo>false</RuntimeTypeInfo> <RuntimeTypeInfo>false</RuntimeTypeInfo>
<ConformanceMode>true</ConformanceMode>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
<LanguageStandard>stdcpp17</LanguageStandard> <LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C> <LanguageStandard_C>stdc17</LanguageStandard_C>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>%(AdditionalOptions) /utf-8 /Zc:externConstexpr /Zc:lambda /Zc:throwingNew</AdditionalOptions>
<ControlFlowGuard>Guard</ControlFlowGuard> <ControlFlowGuard>Guard</ControlFlowGuard>
<FloatingPointModel>Fast</FloatingPointModel> <FloatingPointModel>Fast</FloatingPointModel>
</ClCompile> </ClCompile>

View file

@ -71,10 +71,8 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<!-- All new code should be in non-permissive mode. Big objects for C++/WinRT. --> <!-- Big objects for C++/WinRT. -->
<ConformanceMode>true</ConformanceMode> <AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
<AdditionalOptions>%(AdditionalOptions) /bigobj /Zc:twoPhase-</AdditionalOptions>
<DisableSpecificWarnings>5104;28204;%(DisableSpecificWarnings)</DisableSpecificWarnings> <DisableSpecificWarnings>5104;28204;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories> <AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>

View file

@ -1001,7 +1001,7 @@ using Microsoft::Console::VirtualTerminal::StateMachine;
// - STATUS_SUCCESS if OK. // - STATUS_SUCCESS if OK.
// - CONSOLE_STATUS_WAIT if we couldn't finish now and need to be called back later (see ppWaiter). // - CONSOLE_STATUS_WAIT if we couldn't finish now and need to be called back later (see ppWaiter).
// - Or a suitable NTSTATUS format error code for memory/string/math failures. // - Or a suitable NTSTATUS format error code for memory/string/math failures.
[[nodiscard]] NTSTATUS DoWriteConsole(_In_reads_bytes_(*pcbBuffer) PWCHAR pwchBuffer, [[nodiscard]] NTSTATUS DoWriteConsole(_In_reads_bytes_(*pcbBuffer) PCWCHAR pwchBuffer,
_Inout_ size_t* const pcbBuffer, _Inout_ size_t* const pcbBuffer,
SCREEN_INFORMATION& screenInfo, SCREEN_INFORMATION& screenInfo,
bool requiresVtQuirk, bool requiresVtQuirk,

View file

@ -90,7 +90,7 @@ Note:
// NOTE: console lock must be held when calling this routine // NOTE: console lock must be held when calling this routine
// String has been translated to unicode at this point. // String has been translated to unicode at this point.
[[nodiscard]] NTSTATUS DoWriteConsole(_In_reads_bytes_(*pcbBuffer) PWCHAR pwchBuffer, [[nodiscard]] NTSTATUS DoWriteConsole(_In_reads_bytes_(*pcbBuffer) PCWCHAR pwchBuffer,
_Inout_ size_t* const pcbBuffer, _Inout_ size_t* const pcbBuffer,
SCREEN_INFORMATION& screenInfo, SCREEN_INFORMATION& screenInfo,
bool requiresVtQuirk, bool requiresVtQuirk,

View file

@ -1216,7 +1216,7 @@ std::wstring Alias::s_MatchAndCopyAlias(const std::wstring& sourceText,
// - LineCount - aliases can contain multiple commands. $T is the command separator // - LineCount - aliases can contain multiple commands. $T is the command separator
// Return Value: // Return Value:
// - None. It will just maintain the source as the target if we can't match an alias. // - None. It will just maintain the source as the target if we can't match an alias.
void Alias::s_MatchAndCopyAliasLegacy(_In_reads_bytes_(cbSource) PWCHAR pwchSource, void Alias::s_MatchAndCopyAliasLegacy(_In_reads_bytes_(cbSource) PCWCH pwchSource,
_In_ size_t cbSource, _In_ size_t cbSource,
_Out_writes_bytes_(cbTargetWritten) PWCHAR pwchTarget, _Out_writes_bytes_(cbTargetWritten) PWCHAR pwchTarget,
_In_ const size_t cbTargetSize, _In_ const size_t cbTargetSize,

View file

@ -16,7 +16,7 @@ class Alias
public: public:
static void s_ClearCmdExeAliases(); static void s_ClearCmdExeAliases();
static void s_MatchAndCopyAliasLegacy(_In_reads_bytes_(cbSource) PWCHAR pwchSource, static void s_MatchAndCopyAliasLegacy(_In_reads_bytes_(cbSource) PCWCH pwchSource,
_In_ size_t cbSource, _In_ size_t cbSource,
_Out_writes_bytes_(cbTargetWritten) PWCHAR pwchTarget, _Out_writes_bytes_(cbTargetWritten) PWCHAR pwchTarget,
_In_ const size_t cbTargetSize, _In_ const size_t cbTargetSize,

View file

@ -104,7 +104,7 @@ void FileTests::TestUtf8WriteFileInvalid()
DWORD dwWritten; DWORD dwWritten;
DWORD dwExpectedWritten; DWORD dwExpectedWritten;
char* str; const char* str;
DWORD cbStr; DWORD cbStr;
// \x80 is an invalid UTF-8 continuation // \x80 is an invalid UTF-8 continuation

View file

@ -12,8 +12,6 @@
// - Ensures the SxS initialization for the process. // - Ensures the SxS initialization for the process.
void InitSideBySide(_Out_writes_(ScratchBufferSize) PWSTR ScratchBuffer, __range(MAX_PATH, MAX_PATH) DWORD ScratchBufferSize) void InitSideBySide(_Out_writes_(ScratchBufferSize) PWSTR ScratchBuffer, __range(MAX_PATH, MAX_PATH) DWORD ScratchBufferSize)
{ {
ACTCTXW actctx = { 0 };
// Account for the fact that sidebyside stuff happens in CreateProcess // Account for the fact that sidebyside stuff happens in CreateProcess
// but conhost is run with RtlCreateUserProcess. // but conhost is run with RtlCreateUserProcess.
@ -30,38 +28,35 @@ void InitSideBySide(_Out_writes_(ScratchBufferSize) PWSTR ScratchBuffer, __range
// make references to DLLs in the system that are in the SxS cache (ex. a 3rd party IME is loaded and asks for // make references to DLLs in the system that are in the SxS cache (ex. a 3rd party IME is loaded and asks for
// comctl32.dll. The load will fail if SxS wasn't initialized.) This was bug# WIN7:681280. // comctl32.dll. The load will fail if SxS wasn't initialized.) This was bug# WIN7:681280.
// We look at the first few chars without being careful about a terminal nul, so init them.
ScratchBuffer[0] = 0;
ScratchBuffer[1] = 0;
ScratchBuffer[2] = 0;
ScratchBuffer[3] = 0;
ScratchBuffer[4] = 0;
ScratchBuffer[5] = 0;
ScratchBuffer[6] = 0;
// GetModuleFileNameW truncates its result to fit in the buffer, so to detect if we fit, we have to do this.
ScratchBuffer[ScratchBufferSize - 2] = 0;
DWORD const dwModuleFileNameLength = GetModuleFileNameW(nullptr, ScratchBuffer, ScratchBufferSize); DWORD const dwModuleFileNameLength = GetModuleFileNameW(nullptr, ScratchBuffer, ScratchBufferSize);
if (dwModuleFileNameLength == 0) if (dwModuleFileNameLength == 0)
{ {
RIPMSG1(RIP_ERROR, "GetModuleFileNameW failed %d.\n", GetLastError()); RIPMSG1(RIP_ERROR, "GetModuleFileNameW failed %d.\n", GetLastError());
goto Exit; return;
} }
if (ScratchBuffer[ScratchBufferSize - 2] != 0) // GetModuleFileNameW truncates its result to fit in the buffer
// and returns the given buffer size in such cases.
if (dwModuleFileNameLength == ScratchBufferSize)
{ {
RIPMSG1(RIP_ERROR, "GetModuleFileNameW requires more than ScratchBufferSize(%d) - 1.\n", ScratchBufferSize); RIPMSG1(RIP_ERROR, "GetModuleFileNameW requires more than ScratchBufferSize(%d) - 1.\n", ScratchBufferSize);
goto Exit; return;
} }
// We get an NT path from the Win32 api. Fix it to be Win32. // We get an NT path from the Win32 api. Fix it to be Win32.
// We can test for NT paths by checking whether the string starts with "\??\C:\", or any
// alternative letter other than C. We specifically don't test for the drive letter below.
UINT NtToWin32PathOffset = 0; UINT NtToWin32PathOffset = 0;
if (ScratchBuffer[0] == '\\' && ScratchBuffer[1] == '?' && ScratchBuffer[2] == '?' && ScratchBuffer[3] == '\\' static constexpr wchar_t ntPathSpec1[]{ L'\\', L'?', L'?', L'\\' };
//&& ScratchBuffer[4] == a drive letter static constexpr wchar_t ntPathSpec2[]{ L':', L'\\' };
&& ScratchBuffer[5] == ':' && ScratchBuffer[6] == '\\') if (
dwModuleFileNameLength >= 7 &&
memcmp(&ScratchBuffer[0], &ntPathSpec1[0], sizeof(ntPathSpec1)) == 0 &&
memcmp(&ScratchBuffer[5], &ntPathSpec2[0], sizeof(ntPathSpec2)) == 0)
{ {
NtToWin32PathOffset = 4; NtToWin32PathOffset = 4;
} }
ACTCTXW actctx{};
actctx.cbSize = sizeof(actctx); actctx.cbSize = sizeof(actctx);
actctx.dwFlags = (ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT); actctx.dwFlags = (ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT);
actctx.lpResourceName = MAKEINTRESOURCE(IDR_SYSTEM_MANIFEST); actctx.lpResourceName = MAKEINTRESOURCE(IDR_SYSTEM_MANIFEST);
@ -83,11 +78,7 @@ void InitSideBySide(_Out_writes_(ScratchBufferSize) PWSTR ScratchBuffer, __range
{ {
RIPMSG1(RIP_WARNING, "InitSideBySide failed create an activation context. Error: %d\r\n", error); RIPMSG1(RIP_WARNING, "InitSideBySide failed create an activation context. Error: %d\r\n", error);
} }
goto Exit;
} }
Exit:
ScratchBuffer[0] = 0;
} }
// Routine Description: // Routine Description:

View file

@ -58,7 +58,7 @@ Tracing::~Tracing()
// Return Value: // Return Value:
// - An object for the caller to hold until the API call is complete. // - An object for the caller to hold until the API call is complete.
// Then destroy it to signal that the call is over so the stop trace can be written. // Then destroy it to signal that the call is over so the stop trace can be written.
Tracing Tracing::s_TraceApiCall(const NTSTATUS& result, PCSTR traceName) Tracing Tracing::s_TraceApiCall(const NTSTATUS result, PCSTR traceName)
{ {
// clang-format off // clang-format off
TraceLoggingWrite( TraceLoggingWrite(

View file

@ -40,7 +40,7 @@ class Tracing
public: public:
~Tracing(); ~Tracing();
static Tracing s_TraceApiCall(const NTSTATUS& result, PCSTR traceName); static Tracing s_TraceApiCall(const NTSTATUS result, PCSTR traceName);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_GETLARGESTWINDOWSIZE_MSG* const a); static void s_TraceApi(const NTSTATUS status, const CONSOLE_GETLARGESTWINDOWSIZE_MSG* const a);
static void s_TraceApi(const NTSTATUS status, const CONSOLE_SCREENBUFFERINFO_MSG* const a, const bool fSet); static void s_TraceApi(const NTSTATUS status, const CONSOLE_SCREENBUFFERINFO_MSG* const a, const bool fSet);

View file

@ -153,7 +153,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyTrailingCRLF) TEST_METHOD(TestMatchAndCopyTrailingCRLF)
{ {
PWSTR pwszSource = L"SourceWithoutCRLF\r\n"; const auto pwszSource = L"SourceWithoutCRLF\r\n";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 60; const size_t cchTarget = 60;
@ -193,7 +193,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyInvalidExeName) TEST_METHOD(TestMatchAndCopyInvalidExeName)
{ {
PWSTR pwszSource = L"Source"; const auto pwszSource = L"Source";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 12; const size_t cchTarget = 12;
@ -225,7 +225,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyExeNotFound) TEST_METHOD(TestMatchAndCopyExeNotFound)
{ {
PWSTR pwszSource = L"Source"; const auto pwszSource = L"Source";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 12; const size_t cchTarget = 12;
@ -257,7 +257,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyAliasNotFound) TEST_METHOD(TestMatchAndCopyAliasNotFound)
{ {
PWSTR pwszSource = L"Source"; const auto pwszSource = L"Source";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 12; const size_t cchTarget = 12;
@ -294,7 +294,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyTargetTooSmall) TEST_METHOD(TestMatchAndCopyTargetTooSmall)
{ {
PWSTR pwszSource = L"Source"; const auto pwszSource = L"Source";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 12; const size_t cchTarget = 12;
@ -330,7 +330,7 @@ class AliasTests
TEST_METHOD(TestMatchAndCopyLeadingSpaces) TEST_METHOD(TestMatchAndCopyLeadingSpaces)
{ {
PWSTR pwszSource = L" Source"; const auto pwszSource = L" Source";
const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t); const size_t cbSource = wcslen(pwszSource) * sizeof(wchar_t);
const size_t cchTarget = 12; const size_t cchTarget = 12;

View file

@ -118,7 +118,7 @@ class InputRecordConversionTests
dbcsChars, dbcsChars,
INPUT_RECORD_COUNT * 2, INPUT_RECORD_COUNT * 2,
nullptr, nullptr,
false); FALSE);
VERIFY_ARE_EQUAL(writtenBytes, static_cast<int>(INPUT_RECORD_COUNT * 2)); VERIFY_ARE_EQUAL(writtenBytes, static_cast<int>(INPUT_RECORD_COUNT * 2));
for (size_t i = 0; i < INPUT_RECORD_COUNT * 2; ++i) for (size_t i = 0; i < INPUT_RECORD_COUNT * 2; ++i)
{ {

View file

@ -2572,7 +2572,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsWriteCharsLegacy()
if (writeSingly) if (writeSingly)
{ {
wchar_t* str = L"X"; auto str = L"X";
size_t seqCb = 2; size_t seqCb = 2;
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr));
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr));
@ -2581,7 +2581,7 @@ void ScreenBufferTests::BackspaceDefaultAttrsWriteCharsLegacy()
} }
else else
{ {
wchar_t* str = L"XX\x08"; const auto str = L"XX\x08";
size_t seqCb = 6; size_t seqCb = 6;
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, writeCharsLegacyMode, nullptr));
} }

View file

@ -22,6 +22,61 @@ using namespace WEX::Logging;
using namespace WEX::TestExecution; using namespace WEX::TestExecution;
using Microsoft::Console::Interactivity::ServiceLocator; using Microsoft::Console::Interactivity::ServiceLocator;
template<typename T>
T GetIterator()
{
}
template<typename T>
T GetIteratorAt(COORD at)
{
}
template<typename T>
T GetIteratorWithAdvance()
{
}
template<>
TextBufferCellIterator GetIteratorAt<TextBufferCellIterator>(COORD at)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& outputBuffer = gci.GetActiveOutputBuffer();
return outputBuffer.GetCellDataAt(at);
}
template<>
TextBufferCellIterator GetIterator<TextBufferCellIterator>()
{
return GetIteratorAt<TextBufferCellIterator>({ 0 });
}
template<>
TextBufferCellIterator GetIteratorWithAdvance<TextBufferCellIterator>()
{
return GetIteratorAt<TextBufferCellIterator>({ 5, 5 });
}
template<>
TextBufferTextIterator GetIteratorAt<TextBufferTextIterator>(COORD at)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& outputBuffer = gci.GetActiveOutputBuffer();
return outputBuffer.GetTextDataAt(at);
}
template<>
TextBufferTextIterator GetIterator<TextBufferTextIterator>()
{
return GetIteratorAt<TextBufferTextIterator>({ 0 });
}
template<>
TextBufferTextIterator GetIteratorWithAdvance<TextBufferTextIterator>()
{
return GetIteratorAt<TextBufferTextIterator>({ 5, 5 });
}
class TextBufferIteratorTests class TextBufferIteratorTests
{ {
CommonState* m_state; CommonState* m_state;
@ -268,61 +323,6 @@ class TextBufferIteratorTests
TEST_METHOD(ConstructedLimits); TEST_METHOD(ConstructedLimits);
}; };
template<typename T>
T GetIterator()
{
}
template<typename T>
T GetIteratorAt(COORD at)
{
}
template<typename T>
T GetIteratorWithAdvance()
{
}
template<>
TextBufferCellIterator GetIteratorAt<TextBufferCellIterator>(COORD at)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& outputBuffer = gci.GetActiveOutputBuffer();
return outputBuffer.GetCellDataAt(at);
}
template<>
TextBufferCellIterator GetIterator<TextBufferCellIterator>()
{
return GetIteratorAt<TextBufferCellIterator>({ 0 });
}
template<>
TextBufferCellIterator GetIteratorWithAdvance<TextBufferCellIterator>()
{
return GetIteratorAt<TextBufferCellIterator>({ 5, 5 });
}
template<>
TextBufferTextIterator GetIteratorAt<TextBufferTextIterator>(COORD at)
{
const auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
const auto& outputBuffer = gci.GetActiveOutputBuffer();
return outputBuffer.GetTextDataAt(at);
}
template<>
TextBufferTextIterator GetIterator<TextBufferTextIterator>()
{
return GetIteratorAt<TextBufferTextIterator>({ 0 });
}
template<>
TextBufferTextIterator GetIteratorWithAdvance<TextBufferTextIterator>()
{
return GetIteratorAt<TextBufferTextIterator>({ 5, 5 });
}
void TextBufferIteratorTests::BoolOperatorText() void TextBufferIteratorTests::BoolOperatorText()
{ {
BoolOperatorTestHelper<TextBufferTextIterator>(); BoolOperatorTestHelper<TextBufferTextIterator>();

View file

@ -81,7 +81,7 @@ class TextBufferTests
TEST_METHOD(TestDoubleBytePadFlag); TEST_METHOD(TestDoubleBytePadFlag);
void DoBoundaryTest(PWCHAR const pwszInputString, void DoBoundaryTest(PCWCHAR const pwszInputString,
short const cLength, short const cLength,
short const cMax, short const cMax,
short const cLeft, short const cLeft,
@ -300,7 +300,7 @@ void TextBufferTests::TestDoubleBytePadFlag()
VERIFY_IS_FALSE(Row.WasDoubleBytePadded()); VERIFY_IS_FALSE(Row.WasDoubleBytePadded());
} }
void TextBufferTests::DoBoundaryTest(PWCHAR const pwszInputString, void TextBufferTests::DoBoundaryTest(PCWCHAR const pwszInputString,
short const cLength, short const cLength,
short const cMax, short const cMax,
short const cLeft, short const cLeft,
@ -336,7 +336,7 @@ void TextBufferTests::TestBoundaryMeasuresRegularString()
SHORT csBufferWidth = GetBufferWidth(); SHORT csBufferWidth = GetBufferWidth();
// length 44, left 0, right 44 // length 44, left 0, right 44
const PWCHAR pwszLazyDog = L"The quick brown fox jumps over the lazy dog."; const auto pwszLazyDog = L"The quick brown fox jumps over the lazy dog.";
DoBoundaryTest(pwszLazyDog, 44, csBufferWidth, 0, 44); DoBoundaryTest(pwszLazyDog, 44, csBufferWidth, 0, 44);
} }
@ -345,7 +345,7 @@ void TextBufferTests::TestBoundaryMeasuresFloatingString()
SHORT csBufferWidth = GetBufferWidth(); SHORT csBufferWidth = GetBufferWidth();
// length 5 spaces + 4 chars + 5 spaces = 14, left 5, right 9 // length 5 spaces + 4 chars + 5 spaces = 14, left 5, right 9
const PWCHAR pwszOffsets = L" C:\\> "; const auto pwszOffsets = L" C:\\> ";
DoBoundaryTest(pwszOffsets, 14, csBufferWidth, 5, 9); DoBoundaryTest(pwszOffsets, 14, csBufferWidth, 5, 9);
} }
@ -648,7 +648,7 @@ void TextBufferTests::TestMixedRgbAndLegacyForeground()
// FG = rgb(64;128;255), BG = rgb(default) // FG = rgb(64;128;255), BG = rgb(default)
Log::Comment(L"Case 1 \"\\E[m\\E[38;2;64;128;255mX\\E[49mX\\E[m\""); Log::Comment(L"Case 1 \"\\E[m\\E[38;2;64;128;255mX\\E[49mX\\E[m\"");
wchar_t* sequence = L"\x1b[m\x1b[38;2;64;128;255mX\x1b[49mX\x1b[m"; const auto sequence = L"\x1b[m\x1b[38;2;64;128;255mX\x1b[49mX\x1b[m";
stateMachine.ProcessString(sequence); stateMachine.ProcessString(sequence);
const short x = cursor.GetPosition().X; const short x = cursor.GetPosition().X;
@ -675,7 +675,7 @@ void TextBufferTests::TestMixedRgbAndLegacyForeground()
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(fgColor, bgColor)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(fgColor, bgColor));
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(fgColor, bgColor)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(fgColor, bgColor));
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -693,7 +693,7 @@ void TextBufferTests::TestMixedRgbAndLegacyBackground()
// FG = rgb(default), BG = rgb(64;128;255) // FG = rgb(default), BG = rgb(64;128;255)
Log::Comment(L"Case 2 \"\\E[m\\E[48;2;64;128;255mX\\E[39mX\\E[m\""); Log::Comment(L"Case 2 \"\\E[m\\E[48;2;64;128;255mX\\E[39mX\\E[m\"");
wchar_t* sequence = L"\x1b[m\x1b[48;2;64;128;255mX\x1b[39mX\x1b[m"; const auto sequence = L"\x1b[m\x1b[48;2;64;128;255mX\x1b[39mX\x1b[m";
stateMachine.ProcessString(sequence); stateMachine.ProcessString(sequence);
const auto x = cursor.GetPosition().X; const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y; const auto y = cursor.GetPosition().Y;
@ -719,7 +719,7 @@ void TextBufferTests::TestMixedRgbAndLegacyBackground()
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(fgColor, bgColor)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(fgColor, bgColor));
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(fgColor, bgColor)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(fgColor, bgColor));
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -735,7 +735,7 @@ void TextBufferTests::TestMixedRgbAndLegacyUnderline()
// '\E[m\E[48;2;64;128;255mX\E[4mX\E[m' // '\E[m\E[48;2;64;128;255mX\E[4mX\E[m'
// Make sure that the second X has RGB attributes AND underline // Make sure that the second X has RGB attributes AND underline
Log::Comment(L"Case 3 \"\\E[m\\E[48;2;64;128;255mX\\E[4mX\\E[m\""); Log::Comment(L"Case 3 \"\\E[m\\E[48;2;64;128;255mX\\E[4mX\\E[m\"");
wchar_t* sequence = L"\x1b[m\x1b[48;2;64;128;255mX\x1b[4mX\x1b[m"; const auto sequence = L"\x1b[m\x1b[48;2;64;128;255mX\x1b[4mX\x1b[m";
stateMachine.ProcessString(sequence); stateMachine.ProcessString(sequence);
const auto x = cursor.GetPosition().X; const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y; const auto y = cursor.GetPosition().Y;
@ -764,7 +764,7 @@ void TextBufferTests::TestMixedRgbAndLegacyUnderline()
VERIFY_ARE_EQUAL(attrA.IsUnderlined(), false); VERIFY_ARE_EQUAL(attrA.IsUnderlined(), false);
VERIFY_ARE_EQUAL(attrB.IsUnderlined(), true); VERIFY_ARE_EQUAL(attrB.IsUnderlined(), true);
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -783,7 +783,7 @@ void TextBufferTests::TestMixedRgbAndLegacyBrightness()
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
VERIFY_ARE_NOT_EQUAL(dark_green, bright_green); VERIFY_ARE_NOT_EQUAL(dark_green, bright_green);
wchar_t* sequence = L"\x1b[m\x1b[32mX\x1b[1mX"; const auto sequence = L"\x1b[m\x1b[32mX\x1b[1mX";
stateMachine.ProcessString(sequence); stateMachine.ProcessString(sequence);
const auto x = cursor.GetPosition().X; const auto x = cursor.GetPosition().X;
const auto y = cursor.GetPosition().Y; const auto y = cursor.GetPosition().Y;
@ -806,7 +806,7 @@ void TextBufferTests::TestMixedRgbAndLegacyBrightness()
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA).first, dark_green); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA).first, dark_green);
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB).first, bright_green); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB).first, bright_green);
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -1384,7 +1384,7 @@ void TextBufferTests::TestRgbThenBold()
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(foreground, background)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrA), std::make_pair(foreground, background));
VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(foreground, background)); VERIFY_ARE_EQUAL(gci.LookupAttributeColors(attrB), std::make_pair(foreground, background));
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -1408,7 +1408,7 @@ void TextBufferTests::TestResetClearsBoldness()
const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN); const auto dark_green = gci.GetColorTableEntry(TextColor::DARK_GREEN);
const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN); const auto bright_green = gci.GetColorTableEntry(TextColor::BRIGHT_GREEN);
wchar_t* sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD"; const auto sequence = L"\x1b[32mA\x1b[1mB\x1b[0mC\x1b[32mD";
Log::Comment(NoThrowString().Format(sequence)); Log::Comment(NoThrowString().Format(sequence));
stateMachine.ProcessString(sequence); stateMachine.ProcessString(sequence);
@ -1443,7 +1443,7 @@ void TextBufferTests::TestResetClearsBoldness()
VERIFY_IS_FALSE(attrC.IsBold()); VERIFY_IS_FALSE(attrC.IsBold());
VERIFY_IS_FALSE(attrD.IsBold()); VERIFY_IS_FALSE(attrD.IsBold());
wchar_t* reset = L"\x1b[0m"; const auto reset = L"\x1b[0m";
stateMachine.ProcessString(reset); stateMachine.ProcessString(reset);
} }
@ -1552,7 +1552,7 @@ void TextBufferTests::TestBackspaceStringsAPI()
Log::Comment(NoThrowString().Format( Log::Comment(NoThrowString().Format(
L"Using WriteCharsLegacy, write \\b \\b as a single string.")); L"Using WriteCharsLegacy, write \\b \\b as a single string."));
{ {
wchar_t* str = L"\b \b"; const auto str = L"\b \b";
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr));
VERIFY_ARE_EQUAL(cursor.GetPosition().X, x0); VERIFY_ARE_EQUAL(cursor.GetPosition().X, x0);
@ -1583,19 +1583,19 @@ void TextBufferTests::TestBackspaceStringsAPI()
Log::Comment(NoThrowString().Format( Log::Comment(NoThrowString().Format(
L"Using WriteCharsLegacy, write \\b \\b as separate strings.")); L"Using WriteCharsLegacy, write \\b \\b as separate strings."));
{ {
wchar_t* str = L"a"; const auto str = L"a";
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr));
} }
{ {
wchar_t* str = L"\b"; const auto str = L"\b";
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr));
} }
{ {
wchar_t* str = L" "; const auto str = L" ";
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr));
} }
{ {
wchar_t* str = L"\b"; const auto str = L"\b";
VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr)); VERIFY_SUCCESS_NTSTATUS(WriteCharsLegacy(si, str, str, str, &seqCb, nullptr, cursor.GetPosition().X, 0, nullptr));
} }

View file

@ -22,7 +22,7 @@
// Return Value: // Return Value:
// - THROW: Throws if space cannot be allocated to copy the given string // - THROW: Throws if space cannot be allocated to copy the given string
WriteData::WriteData(SCREEN_INFORMATION& siContext, WriteData::WriteData(SCREEN_INFORMATION& siContext,
_In_reads_bytes_(cbContext) wchar_t* const pwchContext, _In_reads_bytes_(cbContext) PCWCHAR pwchContext,
const size_t cbContext, const size_t cbContext,
const UINT uiOutputCodepage, const UINT uiOutputCodepage,
const bool requiresVtQuirk) : const bool requiresVtQuirk) :

View file

@ -25,7 +25,7 @@ class WriteData : public IWaitRoutine
{ {
public: public:
WriteData(SCREEN_INFORMATION& siContext, WriteData(SCREEN_INFORMATION& siContext,
_In_reads_bytes_(cbContext) wchar_t* const pwchContext, _In_reads_bytes_(cbContext) PCWCHAR pwchContext,
const size_t cbContext, const size_t cbContext,
const UINT uiOutputCodepage, const UINT uiOutputCodepage,
const bool requiresVtQuirk); const bool requiresVtQuirk);

View file

@ -97,7 +97,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
public: public:
template<typename... Args> template<typename... Args>
constexpr explicit presorted_static_map(const Args&... args) noexcept : constexpr explicit presorted_static_map(const Args&... args) noexcept :
static_map{ args... } {}; static_map<K, V, Compare, N, details::presorted_input_t>{ args... } {};
}; };
// this is a deduction guide that ensures two things: // this is a deduction guide that ensures two things:

View file

@ -169,7 +169,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
// and 5x or more for long strings (128 characters or more). // and 5x or more for long strings (128 characters or more).
// See: https://github.com/microsoft/STL/issues/2289 // See: https://github.com/microsoft/STL/issues/2289
template<typename T, typename Traits> template<typename T, typename Traits>
bool equals(const std::basic_string_view<T, Traits>& str1, const std::basic_string_view<T, Traits>& str2) noexcept bool equals(const std::basic_string_view<T, Traits>& lhs, const std::basic_string_view<T, Traits>& rhs) noexcept
{ {
return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0; return lhs.size() == rhs.size() && __builtin_memcmp(lhs.data(), rhs.data(), lhs.size() * sizeof(T)) == 0;
} }

View file

@ -315,7 +315,7 @@ class UiaTextRangeTests
short yPos; short yPos;
}; };
static constexpr wchar_t* toString(TextUnit unit) noexcept static constexpr const wchar_t* toString(TextUnit unit) noexcept
{ {
// if a format is not supported, it goes to the next largest text unit // if a format is not supported, it goes to the next largest text unit
switch (unit) switch (unit)
@ -1368,17 +1368,17 @@ class UiaTextRangeTests
Log::Comment(NoThrowString().Format(L"Forward by %s", toString(textUnit))); Log::Comment(NoThrowString().Format(L"Forward by %s", toString(textUnit)));
// Create an UTR at EndExclusive // Create an UTR at EndExclusive
const auto utrEnd{ atDocumentEnd ? documentEndExclusive : endExclusive }; const auto utrEnd{ atDocumentEnd ? documentEndExclusive : static_cast<COORD>(endExclusive) };
if (degenerate) if (degenerate)
{ {
// UTR: (exclusive, exclusive) range // UTR: (exclusive, exclusive) range
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive }; const auto utrStart{ atDocumentEnd ? documentEndExclusive : static_cast<COORD>(endExclusive) };
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd)); THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
} }
else else
{ {
// UTR: (inclusive, exclusive) range // UTR: (inclusive, exclusive) range
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive }; const auto utrStart{ atDocumentEnd ? documentEndInclusive : static_cast<COORD>(endInclusive) };
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd)); THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
} }
THROW_IF_FAILED(utr->Move(textUnit, 1, &moveAmt)); THROW_IF_FAILED(utr->Move(textUnit, 1, &moveAmt));
@ -1414,13 +1414,13 @@ class UiaTextRangeTests
if (degenerate) if (degenerate)
{ {
// UTR: (exclusive, exclusive) range // UTR: (exclusive, exclusive) range
const auto utrStart{ atDocumentEnd ? documentEndExclusive : endExclusive }; const auto utrStart{ atDocumentEnd ? documentEndExclusive : static_cast<COORD>(endExclusive) };
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd)); THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
} }
else else
{ {
// UTR: (inclusive, exclusive) range // UTR: (inclusive, exclusive) range
const auto utrStart{ atDocumentEnd ? documentEndInclusive : endInclusive }; const auto utrStart{ atDocumentEnd ? documentEndInclusive : static_cast<COORD>(endInclusive) };
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd)); THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider, utrStart, utrEnd));
} }
@ -1447,14 +1447,14 @@ class UiaTextRangeTests
else if (textUnit <= TextUnit::TextUnit_Line) else if (textUnit <= TextUnit::TextUnit_Line)
{ {
VERIFY_ARE_EQUAL(-1, moveAmt); VERIFY_ARE_EQUAL(-1, moveAmt);
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? lastLineStart : secondToLastLinePos, til::point{ utr->_start }); VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? lastLineStart : static_cast<COORD>(secondToLastLinePos), utr->_start);
VERIFY_ARE_EQUAL(lastLineStart, til::point{ utr->_end }); VERIFY_ARE_EQUAL(lastLineStart, utr->_end);
} }
else // textUnit <= TextUnit::TextUnit_Document: else // textUnit <= TextUnit::TextUnit_Document:
{ {
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? -1 : 0, moveAmt); VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? -1 : 0, moveAmt);
VERIFY_ARE_EQUAL(origin, til::point{ utr->_start }); VERIFY_ARE_EQUAL(origin, til::point{ utr->_start });
VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? origin : documentEndExclusive, til::point{ utr->_end }); VERIFY_ARE_EQUAL(degenerate || !atDocumentEnd ? static_cast<COORD>(origin) : documentEndExclusive, utr->_end);
} }
} }

View file

@ -18,14 +18,7 @@ static CONSOLE_STATE_INFO g_csi;
using namespace Microsoft::WRL; using namespace Microsoft::WRL;
// This class exposes console property sheets for use when launching the filesystem shortcut properties dialog. // This class exposes console property sheets for use when launching the filesystem shortcut properties dialog.
// clang-format off class __declspec(uuid("D2942F8E-478E-41D3-870A-35A16238F4EE")) ConsolePropertySheetHandler final : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IShellExtInit, IShellPropSheetExt, IPersist, FtmBase>
[uuid(D2942F8E-478E-41D3-870A-35A16238F4EE)]
class ConsolePropertySheetHandler WrlFinal : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
IShellExtInit,
IShellPropSheetExt,
IPersist,
FtmBase>
// clang-format on
{ {
public: public:
HRESULT RuntimeClassInitialize() HRESULT RuntimeClassInitialize()
@ -34,7 +27,7 @@ public:
} }
// IPersist // IPersist
STDMETHODIMP GetClassID(_Out_ CLSID * clsid) override STDMETHODIMP GetClassID(_Out_ CLSID* clsid) override
{ {
*clsid = __uuidof(this); *clsid = __uuidof(this);
return S_OK; return S_OK;
@ -43,7 +36,7 @@ public:
// IShellExtInit // IShellExtInit
// Shell QI's for IShellExtInit and calls Initialize first. If we return a succeeding HRESULT, the shell will QI for // Shell QI's for IShellExtInit and calls Initialize first. If we return a succeeding HRESULT, the shell will QI for
// IShellPropSheetExt and call AddPages. A failing HRESULT causes the shell to skip us. // IShellPropSheetExt and call AddPages. A failing HRESULT causes the shell to skip us.
STDMETHODIMP Initialize(_In_ PCIDLIST_ABSOLUTE /*pidlFolder*/, _In_ IDataObject * pdtobj, _In_ HKEY /*hkeyProgID*/) STDMETHODIMP Initialize(_In_ PCIDLIST_ABSOLUTE /*pidlFolder*/, _In_ IDataObject* pdtobj, _In_ HKEY /*hkeyProgID*/)
{ {
WCHAR szLinkFileName[MAX_PATH]; WCHAR szLinkFileName[MAX_PATH];
HRESULT hr = _ShouldAddPropertySheet(pdtobj, szLinkFileName, ARRAYSIZE(szLinkFileName)); HRESULT hr = _ShouldAddPropertySheet(pdtobj, szLinkFileName, ARRAYSIZE(szLinkFileName));
@ -139,7 +132,7 @@ private:
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// CODE FROM THE SHELL DEPOT'S `idllib.h` // CODE FROM THE SHELL DEPOT'S `idllib.h`
// get a link target item without resolving it. // get a link target item without resolving it.
HRESULT GetTargetIdList(_In_ IShellItem * psiLink, _COM_Outptr_ PIDLIST_ABSOLUTE * ppidl) HRESULT GetTargetIdList(_In_ IShellItem* psiLink, _COM_Outptr_ PIDLIST_ABSOLUTE* ppidl)
{ {
*ppidl = nullptr; *ppidl = nullptr;
@ -156,7 +149,7 @@ private:
} }
return hr; return hr;
} }
HRESULT GetTargetItem(_In_ IShellItem * psiLink, _In_ REFIID riid, _COM_Outptr_ void** ppv) HRESULT GetTargetItem(_In_ IShellItem* psiLink, _In_ REFIID riid, _COM_Outptr_ void** ppv)
{ {
*ppv = nullptr; *ppv = nullptr;
@ -171,7 +164,7 @@ private:
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
HRESULT _GetShellItemLinkTargetExpanded(_In_ IShellItem * pShellItem, HRESULT _GetShellItemLinkTargetExpanded(_In_ IShellItem* pShellItem,
_Out_writes_(cchFilePathExtended) PWSTR pszFilePathExtended, _Out_writes_(cchFilePathExtended) PWSTR pszFilePathExtended,
const size_t cchFilePathExtended) const size_t cchFilePathExtended)
{ {
@ -190,7 +183,7 @@ private:
return hr; return hr;
} }
HRESULT _ShouldAddPropertySheet(_In_ IDataObject * pdtobj, HRESULT _ShouldAddPropertySheet(_In_ IDataObject* pdtobj,
_Out_writes_(cchLinkFileName) PWSTR pszLinkFileName, _Out_writes_(cchLinkFileName) PWSTR pszLinkFileName,
const size_t cchLinkFileName) const size_t cchLinkFileName)
{ {

View file

@ -359,7 +359,9 @@ namespace Microsoft::Console::Render
bool is_inline() const noexcept bool is_inline() const noexcept
{ {
return (__builtin_bit_cast(uintptr_t, allocated) & 1) != 0; // VSO-1430353: __builtin_bitcast crashes the compiler under /permissive-.
#pragma warning(suppress : 26490) // Don't use reinterpret_cast (type.1).
return (reinterpret_cast<uintptr_t>(allocated) & 1) != 0;
} }
const T* data() const noexcept const T* data() const noexcept

View file

@ -144,11 +144,10 @@ PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Mess
ULONG const LayerNumber = (Message->msgHeader.ApiNumber >> 24) - 1; ULONG const LayerNumber = (Message->msgHeader.ApiNumber >> 24) - 1;
ULONG const ApiNumber = Message->msgHeader.ApiNumber & 0xffffff; ULONG const ApiNumber = Message->msgHeader.ApiNumber & 0xffffff;
NTSTATUS Status; if ((LayerNumber >= std::size(ConsoleApiLayerTable)) || (ApiNumber >= ConsoleApiLayerTable[LayerNumber].Count))
if ((LayerNumber >= RTL_NUMBER_OF(ConsoleApiLayerTable)) || (ApiNumber >= ConsoleApiLayerTable[LayerNumber].Count))
{ {
Status = STATUS_ILLEGAL_FUNCTION; Message->SetReplyStatus(STATUS_ILLEGAL_FUNCTION);
goto Complete; return Message;
} }
CONSOLE_API_DESCRIPTOR const* Descriptor = &ConsoleApiLayerTable[LayerNumber].Descriptor[ApiNumber]; CONSOLE_API_DESCRIPTOR const* Descriptor = &ConsoleApiLayerTable[LayerNumber].Descriptor[ApiNumber];
@ -159,8 +158,8 @@ PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Mess
(Message->msgHeader.ApiDescriptorSize > Message->Descriptor.InputSize - sizeof(CONSOLE_MSG_HEADER)) || (Message->msgHeader.ApiDescriptorSize > Message->Descriptor.InputSize - sizeof(CONSOLE_MSG_HEADER)) ||
(Message->msgHeader.ApiDescriptorSize < Descriptor->RequiredSize)) (Message->msgHeader.ApiDescriptorSize < Descriptor->RequiredSize))
{ {
Status = STATUS_ILLEGAL_FUNCTION; Message->SetReplyStatus(STATUS_ILLEGAL_FUNCTION);
goto Complete; return Message;
} }
BOOL ReplyPending = FALSE; BOOL ReplyPending = FALSE;
@ -173,6 +172,7 @@ PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Mess
// hard dependencies on NTSTATUS codes that aren't readily expressible as an HRESULT. There's currently only one // hard dependencies on NTSTATUS codes that aren't readily expressible as an HRESULT. There's currently only one
// such known code -- STATUS_BUFFER_TOO_SMALL. There's a conlibk dependency on this being returned from the console // such known code -- STATUS_BUFFER_TOO_SMALL. There's a conlibk dependency on this being returned from the console
// alias API. // alias API.
NTSTATUS Status = S_OK;
{ {
const auto trace = Tracing::s_TraceApiCall(Status, Descriptor->TraceName); const auto trace = Tracing::s_TraceApiCall(Status, Descriptor->TraceName);
Status = (*Descriptor->Routine)(Message, &ReplyPending); Status = (*Descriptor->Routine)(Message, &ReplyPending);
@ -184,14 +184,9 @@ PCONSOLE_API_MSG ApiSorter::ConsoleDispatchRequest(_Inout_ PCONSOLE_API_MSG Mess
if (!ReplyPending) if (!ReplyPending)
{ {
goto Complete; Message->SetReplyStatus(Status);
return Message;
} }
return nullptr; return nullptr;
Complete:
Message->SetReplyStatus(Status);
return Message;
} }

View file

@ -92,7 +92,9 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; UnlockConsole();
pMessage->SetReplyStatus(Status);
return pMessage;
} }
auto deviceComm{ ServiceLocator::LocateGlobals().pDeviceComm }; auto deviceComm{ ServiceLocator::LocateGlobals().pDeviceComm };
@ -110,16 +112,6 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCreateObject(_In_ PCONSOLE_API_MSG pMessa
UnlockConsole(); UnlockConsole();
return nullptr; return nullptr;
Error:
FAIL_FAST_IF(NT_SUCCESS(Status));
UnlockConsole();
pMessage->SetReplyStatus(Status);
return pMessage;
} }
// Routine Description: // Routine Description:
@ -256,17 +248,32 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
Telemetry::Instance().LogApiCall(Telemetry::ApiCall::AttachConsole); Telemetry::Instance().LogApiCall(Telemetry::ApiCall::AttachConsole);
ConsoleProcessHandle* ProcessData = nullptr; ConsoleProcessHandle* ProcessData = nullptr;
NTSTATUS Status;
LockConsole(); LockConsole();
const auto cleanup = wil::scope_exit([&]() noexcept {
UnlockConsole();
if (!NT_SUCCESS(Status))
{
pReceiveMsg->SetReplyStatus(Status);
if (ProcessData != nullptr)
{
CommandHistory::s_Free(ProcessData);
gci.ProcessHandleList.FreeProcessData(ProcessData);
}
}
});
DWORD const dwProcessId = (DWORD)pReceiveMsg->Descriptor.Process; DWORD const dwProcessId = (DWORD)pReceiveMsg->Descriptor.Process;
DWORD const dwThreadId = (DWORD)pReceiveMsg->Descriptor.Object; DWORD const dwThreadId = (DWORD)pReceiveMsg->Descriptor.Object;
CONSOLE_API_CONNECTINFO Cac; CONSOLE_API_CONNECTINFO Cac;
NTSTATUS Status = ConsoleInitializeConnectInfo(pReceiveMsg, &Cac); Status = ConsoleInitializeConnectInfo(pReceiveMsg, &Cac);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; return pReceiveMsg;
} }
// If we pass the tests... // If we pass the tests...
@ -354,7 +361,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; return pReceiveMsg;
} }
ProcessData->fRootProcess = WI_IsFlagClear(gci.Flags, CONSOLE_INITIALIZED); ProcessData->fRootProcess = WI_IsFlagClear(gci.Flags, CONSOLE_INITIALIZED);
@ -376,7 +383,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
Status = ConsoleAllocateConsole(&Cac); Status = ConsoleAllocateConsole(&Cac);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; return pReceiveMsg;
} }
WI_SetFlag(gci.Flags, CONSOLE_INITIALIZED); WI_SetFlag(gci.Flags, CONSOLE_INITIALIZED);
@ -389,7 +396,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
catch (...) catch (...)
{ {
LOG_CAUGHT_EXCEPTION(); LOG_CAUGHT_EXCEPTION();
goto Error; return pReceiveMsg;
} }
gci.ProcessHandleList.ModifyConsoleProcessFocus(WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS)); gci.ProcessHandleList.ModifyConsoleProcessFocus(WI_IsFlagSet(gci.Flags, CONSOLE_HAS_FOCUS));
@ -403,7 +410,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; return pReceiveMsg;
} }
auto& screenInfo = gci.GetActiveOutputBuffer().GetMainBuffer(); auto& screenInfo = gci.GetActiveOutputBuffer().GetMainBuffer();
@ -414,7 +421,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
goto Error; return pReceiveMsg;
} }
// Complete the request. // Complete the request.
@ -434,24 +441,7 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
Tracing::s_TraceConsoleAttachDetach(ProcessData, true); Tracing::s_TraceConsoleAttachDetach(ProcessData, true);
UnlockConsole();
return nullptr; return nullptr;
Error:
FAIL_FAST_IF(NT_SUCCESS(Status));
if (ProcessData != nullptr)
{
CommandHistory::s_Free((HANDLE)ProcessData);
gci.ProcessHandleList.FreeProcessData(ProcessData);
}
UnlockConsole();
pReceiveMsg->SetReplyStatus(Status);
return pReceiveMsg;
} }
// Routine Description: // Routine Description:

View file

@ -25,7 +25,7 @@ using namespace Microsoft::Console::VirtualTerminal;
// For magic reasons, this has to live outside the class. Something wonderful about TAEF macros makes it // For magic reasons, this has to live outside the class. Something wonderful about TAEF macros makes it
// invisible to the linker when inside the class. // invisible to the linker when inside the class.
static wchar_t* s_pwszInputExpected; static const wchar_t* s_pwszInputExpected;
static wchar_t s_pwszExpectedBuffer[BYTE_MAX]; // big enough for anything static wchar_t s_pwszExpectedBuffer[BYTE_MAX]; // big enough for anything
@ -46,7 +46,7 @@ static COORD s_rgTestCoords[] = {
// Note: We're going to be changing the value of the third char (the space) of // Note: We're going to be changing the value of the third char (the space) of
// these strings as we test things with this array, to alter the expected button value. // these strings as we test things with this array, to alter the expected button value.
// The default value is the button=WM_LBUTTONDOWN case, which is element[3]=' ' // The default value is the button=WM_LBUTTONDOWN case, which is element[3]=' '
static wchar_t* s_rgDefaultTestOutput[] = { static const wchar_t* s_rgDefaultTestOutput[] = {
L"\x1b[M !!", L"\x1b[M !!",
L"\x1b[M !\"", L"\x1b[M !\"",
L"\x1b[M \"\"", L"\x1b[M \"\"",
@ -64,7 +64,7 @@ static wchar_t* s_rgDefaultTestOutput[] = {
// these strings as we test things with this array, to alter the expected button value. // these strings as we test things with this array, to alter the expected button value.
// The default value is the button=WM_LBUTTONDOWN case, which is element[3]='0' // The default value is the button=WM_LBUTTONDOWN case, which is element[3]='0'
// We're also going to change the last element, for button-down (M) vs button-up (m) // We're also going to change the last element, for button-down (M) vs button-up (m)
static wchar_t* s_rgSgrTestOutput[] = { static const wchar_t* s_rgSgrTestOutput[] = {
L"\x1b[<%d;1;1M", L"\x1b[<%d;1;1M",
L"\x1b[<%d;1;2M", L"\x1b[<%d;1;2M",
L"\x1b[<%d;2;2M", L"\x1b[<%d;2;2M",
@ -113,7 +113,7 @@ public:
// Routine Description: // Routine Description:
// Constructs a string from s_rgDefaultTestOutput with the third char // Constructs a string from s_rgDefaultTestOutput with the third char
// correctly filled in to match uiButton. // correctly filled in to match uiButton.
wchar_t* BuildDefaultTestOutput(wchar_t* pwchTestOutput, unsigned int uiButton, short sModifierKeystate, short sScrollDelta) wchar_t* BuildDefaultTestOutput(const wchar_t* pwchTestOutput, unsigned int uiButton, short sModifierKeystate, short sScrollDelta)
{ {
Log::Comment(NoThrowString().Format(L"Input Test Output:\'%s\'", pwchTestOutput)); Log::Comment(NoThrowString().Format(L"Input Test Output:\'%s\'", pwchTestOutput));
// Copy the expected output into the buffer // Copy the expected output into the buffer
@ -136,7 +136,7 @@ public:
// Routine Description: // Routine Description:
// Constructs a string from s_rgSgrTestOutput with the third and last chars // Constructs a string from s_rgSgrTestOutput with the third and last chars
// correctly filled in to match uiButton. // correctly filled in to match uiButton.
wchar_t* BuildSGRTestOutput(wchar_t* pwchTestOutput, unsigned int uiButton, short sModifierKeystate, short sScrollDelta) wchar_t* BuildSGRTestOutput(const wchar_t* pwchTestOutput, unsigned int uiButton, short sModifierKeystate, short sScrollDelta)
{ {
ClearTestBuffer(); ClearTestBuffer();

View file

@ -112,7 +112,7 @@ std::string GenerateWhiteSpaceToken()
std::string GenerateTextToken() std::string GenerateTextToken()
{ {
const LPSTR tokens[] = { const LPCSTR tokens[] = {
"The cow jumped over the moon.", "The cow jumped over the moon.",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?", "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?",
@ -134,14 +134,14 @@ std::string GenerateTextToken()
std::string GenerateInvalidToken() std::string GenerateInvalidToken()
{ {
const LPSTR tokens[]{ ":", "'", "\"", "\\" }; const LPCSTR tokens[]{ ":", "'", "\"", "\\" };
return std::string(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens))); return std::string(CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)));
} }
std::string GenerateFuzzedToken( std::string GenerateFuzzedToken(
__in_ecount(cmap) const _fuzz_type_entry<std::string>* map, __in_ecount(cmap) const _fuzz_type_entry<std::string>* map,
__in DWORD cmap, __in DWORD cmap,
__in_ecount(ctokens) const LPSTR* tokens, __in_ecount(ctokens) const LPCSTR* tokens,
__in DWORD ctokens) __in DWORD ctokens)
{ {
std::string csis[] = { CSI, C1CSI }; std::string csis[] = { CSI, C1CSI };
@ -165,7 +165,7 @@ std::string GenerateFuzzedToken(
std::string GenerateFuzzedOscToken( std::string GenerateFuzzedOscToken(
__in_ecount(cmap) const _fuzz_type_entry<std::string>* map, __in_ecount(cmap) const _fuzz_type_entry<std::string>* map,
__in DWORD cmap, __in DWORD cmap,
__in_ecount(ctokens) const LPSTR* tokens, __in_ecount(ctokens) const LPCSTR* tokens,
__in DWORD ctokens) __in DWORD ctokens)
{ {
std::string s(OSC); std::string s(OSC);
@ -227,7 +227,7 @@ std::string GenerateSGRToken()
49, 49,
}; };
const LPSTR tokens[] = { "m" }; const LPCSTR tokens[] = { "m" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 40, [&](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::SelectOne(psValid, ARRAYSIZE(psValid))); return s; } }, { 40, [&](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::SelectOne(psValid, ARRAYSIZE(psValid))); return s; } },
{ 10, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } }, { 10, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } },
@ -242,7 +242,7 @@ std::string GenerateSGRToken()
// For example, moving the cursor to the next line, previous line, up, down, etc. // For example, moving the cursor to the next line, previous line, up, down, etc.
std::string GenerateCUXToken() std::string GenerateCUXToken()
{ {
const LPSTR tokens[] = { "A", "B", "C", "D", "E", "F", "G" }; const LPCSTR tokens[] = { "A", "B", "C", "D", "E", "F", "G" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<USHORT>()); return s; } }, { 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<USHORT>()); return s; } },
{ 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } } { 25, [](std::string) { std::string s; AppendFormat(s, "%d", CFuzzChance::GetRandom<BYTE>()); return s; } }
@ -255,7 +255,7 @@ std::string GenerateCUXToken()
// Differs from other cursor functions since these are ESC sequences and not CSI sequences. // Differs from other cursor functions since these are ESC sequences and not CSI sequences.
std::string GenerateCUXToken2() std::string GenerateCUXToken2()
{ {
const LPSTR tokens[] = { "7", "8" }; const LPCSTR tokens[] = { "7", "8" };
std::string cux(ESC); std::string cux(ESC);
cux += GenerateTokenLowProbability(); cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)); cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
@ -266,7 +266,7 @@ std::string GenerateCUXToken2()
// Cursor positioning with two arguments // Cursor positioning with two arguments
std::string GenerateCUXToken3() std::string GenerateCUXToken3()
{ {
const LPSTR tokens[]{ "H" }; const LPCSTR tokens[]{ "H" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 60, [](std::string) { std::string s; AppendFormat(s, "%d;%d", CFuzzChance::GetRandom<BYTE>(), CFuzzChance::GetRandom<BYTE>()); return s; } }, // 60% give us two numbers in the valid range { 60, [](std::string) { std::string s; AppendFormat(s, "%d;%d", CFuzzChance::GetRandom<BYTE>(), CFuzzChance::GetRandom<BYTE>()); return s; } }, // 60% give us two numbers in the valid range
{ 10, [](std::string) { return std::string(";"); } }, // 10% give us just a ; { 10, [](std::string) { return std::string(";"); } }, // 10% give us just a ;
@ -281,7 +281,7 @@ std::string GenerateCUXToken3()
// Hard Reset (has no args) // Hard Reset (has no args)
std::string GenerateHardResetToken() std::string GenerateHardResetToken()
{ {
const LPSTR tokens[] = { "c" }; const LPCSTR tokens[] = { "c" };
std::string cux(ESC); std::string cux(ESC);
cux += GenerateTokenLowProbability(); cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)); cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
@ -292,7 +292,7 @@ std::string GenerateHardResetToken()
// Soft Reset (has no args) // Soft Reset (has no args)
std::string GenerateSoftResetToken() std::string GenerateSoftResetToken()
{ {
const LPSTR tokens[] = { "p" }; const LPCSTR tokens[] = { "p" };
std::string cux(CSI); std::string cux(CSI);
cux += GenerateTokenLowProbability(); cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)); cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
@ -304,7 +304,7 @@ std::string GenerateSoftResetToken()
// enabling mouse mode, changing to the alt buffer, blinking the cursor, etc. // enabling mouse mode, changing to the alt buffer, blinking the cursor, etc.
std::string GeneratePrivateModeParamToken() std::string GeneratePrivateModeParamToken()
{ {
const LPSTR tokens[] = { "h", "l" }; const LPCSTR tokens[] = { "h", "l" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 12, [](std::string) { std::string s; AppendFormat(s, "?%02d", CFuzzChance::GetRandom<BYTE>()); return s; } }, { 12, [](std::string) { std::string s; AppendFormat(s, "?%02d", CFuzzChance::GetRandom<BYTE>()); return s; } },
{ 8, [](std::string) { return std::string("?1"); } }, { 8, [](std::string) { return std::string("?1"); } },
@ -327,7 +327,7 @@ std::string GeneratePrivateModeParamToken()
// Erase sequences, valid numerical values are 0-2. If no numeric value is specified, 0 is assumed. // Erase sequences, valid numerical values are 0-2. If no numeric value is specified, 0 is assumed.
std::string GenerateEraseToken() std::string GenerateEraseToken()
{ {
const LPSTR tokens[] = { "J", "K" }; const LPCSTR tokens[] = { "J", "K" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 9, [](std::string) { return std::string(""); } }, { 9, [](std::string) { return std::string(""); } },
{ 25, [](std::string) { return std::string("0"); } }, { 25, [](std::string) { return std::string("0"); } },
@ -343,7 +343,7 @@ std::string GenerateEraseToken()
// Device Attributes // Device Attributes
std::string GenerateDeviceAttributesToken() std::string GenerateDeviceAttributesToken()
{ {
const LPSTR tokens[] = { "c" }; const LPCSTR tokens[] = { "c" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 70, [](std::string) { return std::string(""); } }, // 70% leave it blank (valid) { 70, [](std::string) { return std::string(""); } }, // 70% leave it blank (valid)
{ 29, [](std::string) { return std::string("0"); } }, // 29% put in a 0 (valid) { 29, [](std::string) { return std::string("0"); } }, // 29% put in a 0 (valid)
@ -356,7 +356,7 @@ std::string GenerateDeviceAttributesToken()
// Device Attributes // Device Attributes
std::string GenerateDeviceStatusReportToken() std::string GenerateDeviceStatusReportToken()
{ {
const LPSTR tokens[] = { "n" }; const LPCSTR tokens[] = { "n" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 50, [](std::string) { return std::string("6"); } }, // 50% of the time, give us the one we were looking for (6, cursor report) { 50, [](std::string) { return std::string("6"); } }, // 50% of the time, give us the one we were looking for (6, cursor report)
{ 49, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 49% of the time, put in a random value { 49, [](std::string) { std::string s; AppendFormat(s, "%02d", CFuzzChance::GetRandom<BYTE>()); return s; } } // 49% of the time, put in a random value
@ -369,7 +369,7 @@ std::string GenerateDeviceStatusReportToken()
// Scroll sequences, valid numeric values include 0-16384. // Scroll sequences, valid numeric values include 0-16384.
std::string GenerateScrollToken() std::string GenerateScrollToken()
{ {
const LPSTR tokens[] = { "S", "T" }; const LPCSTR tokens[] = { "S", "T" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<ULONG>()); return s; } }, { 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<ULONG>()); return s; } },
{ 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<USHORT>()); return s; } }, { 5, [](std::string) { std::string s; AppendFormat(s, "%08d", CFuzzChance::GetRandom<USHORT>()); return s; } },
@ -383,7 +383,7 @@ std::string GenerateScrollToken()
// Resize sequences, valid numeric values include 0-16384. // Resize sequences, valid numeric values include 0-16384.
std::string GenerateResizeToken() std::string GenerateResizeToken()
{ {
const LPSTR tokens[] = { "t" }; const LPCSTR tokens[] = { "t" };
// 5% - generate a random window manipulation with 1 params // 5% - generate a random window manipulation with 1 params
// 5% - generate a random window manipulation with 2 params // 5% - generate a random window manipulation with 2 params
// 5% - generate a random window manipulation with no params // 5% - generate a random window manipulation with no params
@ -406,7 +406,7 @@ std::string GenerateResizeToken()
// and BEL terminated. // and BEL terminated.
std::string GenerateOscTitleToken() std::string GenerateOscTitleToken()
{ {
const LPSTR tokens[] = { "\x7" }; const LPCSTR tokens[] = { "\x7" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 100, { 100,
[](std::string) { [](std::string) {
@ -435,7 +435,7 @@ std::string GenerateOscTitleToken()
// and BEL terminated. // and BEL terminated.
std::string GenerateOscColorTableToken() std::string GenerateOscColorTableToken()
{ {
const LPSTR tokens[] = { "\x7", "\x1b\\" }; const LPCSTR tokens[] = { "\x7", "\x1b\\" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 100, { 100,
[](std::string) { [](std::string) {
@ -515,7 +515,7 @@ std::string GenerateOscColorTableToken()
// VT52 sequences without parameters. // VT52 sequences without parameters.
std::string GenerateVt52Token() std::string GenerateVt52Token()
{ {
const LPSTR tokens[] = { "A", "B", "C", "D", "F", "G", "H", "I", "J", "K", "Z", "<" }; const LPCSTR tokens[] = { "A", "B", "C", "D", "F", "G", "H", "I", "J", "K", "Z", "<" };
std::string cux(ESC); std::string cux(ESC);
cux += GenerateTokenLowProbability(); cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)); cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
@ -525,7 +525,7 @@ std::string GenerateVt52Token()
// VT52 direct cursor address sequence with parameters. // VT52 direct cursor address sequence with parameters.
std::string GenerateVt52CursorAddressToken() std::string GenerateVt52CursorAddressToken()
{ {
const LPSTR tokens[] = { "Y" }; const LPCSTR tokens[] = { "Y" };
std::string cux(ESC); std::string cux(ESC);
cux += GenerateTokenLowProbability(); cux += GenerateTokenLowProbability();
cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens)); cux += CFuzzChance::SelectOne(tokens, ARRAYSIZE(tokens));
@ -540,7 +540,7 @@ std::string GenerateVt52CursorAddressToken()
// followed by a ";", followed by a string, and BEL terminated. // followed by a ";", followed by a string, and BEL terminated.
std::string GenerateOscHyperlinkToken() std::string GenerateOscHyperlinkToken()
{ {
const LPSTR tokens[] = { "\x7" }; const LPCSTR tokens[] = { "\x7" };
const _fuzz_type_entry<std::string> map[] = { const _fuzz_type_entry<std::string> map[] = {
{ 100, { 100,
[](std::string) { [](std::string) {

View file

@ -898,7 +898,7 @@ namespace fuzz
_Type operator->() const throw() _Type operator->() const throw()
{ {
return (this->m_fFuzzed) ? this->m_t : m_tInit; return (this->m_fFuzzed) ? this->m_t : CFuzzType<_Type, _Args...>::m_tInit;
} }
// This operator makes it possible to invoke the fuzzing map // This operator makes it possible to invoke the fuzzing map
@ -909,7 +909,7 @@ namespace fuzz
// the logic of the fuzz map). // the logic of the fuzz map).
__inline void operator()() throw() __inline void operator()() throw()
{ {
GetValueFromMap(); CFuzzType<_Type, _Args...>::GetValueFromMap();
} }
}; };
@ -960,7 +960,7 @@ namespace fuzz
__inline virtual _Type** operator&() throw() __inline virtual _Type** operator&() throw()
{ {
m_ftEffectiveTraits |= TRAIT_TRANSFER_ALLOCATION; m_ftEffectiveTraits |= TRAIT_TRANSFER_ALLOCATION;
return (this->m_fFuzzed) ? &(this->m_t) : &m_tInit; return (this->m_fFuzzed) ? &(this->m_t) : &CFuzzType<_Type, _Args...>::m_tInit;
} }
private: private:
@ -1087,7 +1087,7 @@ namespace fuzz
int iLow = iHigh - (r.range.iHigh - r.range.iLow); int iLow = iHigh - (r.range.iHigh - r.range.iLow);
if (iLow <= wRandom && wRandom < iHigh) if (iLow <= wRandom && wRandom < iHigh)
{ {
this->m_t |= CallFuzzMapFunction(r.fte.pfnFuzz, this->m_tInit, m_tArgs); this->m_t |= CallFuzzMapFunction(r.fte.pfnFuzz, this->m_tInit, CFuzzType<_Type, _Args...>::m_tArgs);
} }
} }
} }

View file

@ -38,12 +38,12 @@ namespace fuzz
{ {
if (rcch > 1) if (rcch > 1)
{ {
const LPWSTR rgFormatStringChars[] = { L"%n", L"%s", L"%d" }; const PCWSTR rgFormatStringChars[] = { L"%n", L"%s", L"%d" };
size_t cbDestSize = 2 * sizeof(WCHAR); size_t cbDestSize = 2 * sizeof(WCHAR);
memcpy_s( memcpy_s(
&(pwsz[CFuzzChance::GetRandom<size_t>(rcch - 1)]), // -1 because we are writing 2 chars &(pwsz[CFuzzChance::GetRandom<size_t>(rcch - 1)]), // -1 because we are writing 2 chars
cbDestSize, cbDestSize,
CFuzzChance::SelectOne<const LPWSTR>(rgFormatStringChars, ARRAYSIZE(rgFormatStringChars)), CFuzzChance::SelectOne<const PCWSTR>(rgFormatStringChars, ARRAYSIZE(rgFormatStringChars)),
cbDestSize); cbDestSize);
} }
@ -56,12 +56,12 @@ namespace fuzz
{ {
if (rcch > 1) if (rcch > 1)
{ {
const LPSTR rgFormatStringChars[] = { "%n", "%s", "%d" }; const LPCSTR rgFormatStringChars[] = { "%n", "%s", "%d" };
size_t cbDestSize = 2 * sizeof(CHAR); size_t cbDestSize = 2 * sizeof(CHAR);
memcpy_s( memcpy_s(
&(psz[CFuzzChance::GetRandom<size_t>(rcch - 1)]), &(psz[CFuzzChance::GetRandom<size_t>(rcch - 1)]),
cbDestSize, cbDestSize,
CFuzzChance::SelectOne<const LPSTR>(rgFormatStringChars, ARRAYSIZE(rgFormatStringChars)), CFuzzChance::SelectOne<const LPCSTR>(rgFormatStringChars, ARRAYSIZE(rgFormatStringChars)),
cbDestSize); cbDestSize);
} }
@ -238,12 +238,40 @@ namespace fuzz
return _strrev(psz); return _strrev(psz);
} }
template<class _Alloc = CFuzzCRTAllocator>
class CFuzzLogic;
// Flips a random byte value within the buffer.
template<typename _Type>
static _Type* _fz_flipByte(__inout_ecount(rcelms) _Type* p, __inout size_t& rcelms)
{
if (rcelms > 0)
{
return reinterpret_cast<_Type*>(CFuzzLogic<>::FuzzArrayElement(
reinterpret_cast<BYTE*>(p), (rcelms) * sizeof(_Type)));
}
return p;
}
// Flips a random entry value within the buffer
template<typename _Type>
static _Type* _fz_flipEntry(__inout_ecount(rcelms) _Type* p, __inout size_t& rcelms)
{
if (rcelms > 0)
{
return CFuzzLogic<>::FuzzArrayElement(p, rcelms);
}
return p;
}
// Contains fuzzing logic based upon a variety of default scenarios. The // Contains fuzzing logic based upon a variety of default scenarios. The
// idea is to capture and make available a comprehensive fuzzing library // idea is to capture and make available a comprehensive fuzzing library
// that does not require external modules or complex setup. This should // that does not require external modules or complex setup. This should
// make fuzzing easier to implement and test, as well as more explicit // make fuzzing easier to implement and test, as well as more explicit
// with regard to what fuzzing manipulations are possible. // with regard to what fuzzing manipulations are possible.
template<class _Alloc = CFuzzCRTAllocator> template<class _Alloc>
class CFuzzLogic class CFuzzLogic
{ {
public: public:
@ -429,31 +457,6 @@ namespace fuzz
} }
}; };
// Flips a random byte value within the buffer.
template<typename _Type>
static _Type* _fz_flipByte(__inout_ecount(rcelms) _Type* p, __inout size_t& rcelms)
{
if (rcelms > 0)
{
return reinterpret_cast<_Type*>(CFuzzLogic<>::FuzzArrayElement(
reinterpret_cast<BYTE*>(p), (rcelms) * sizeof(_Type)));
}
return p;
}
// Flips a random entry value within the buffer
template<typename _Type>
static _Type* _fz_flipEntry(__inout_ecount(rcelms) _Type* p, __inout size_t& rcelms)
{
if (rcelms > 0)
{
return CFuzzLogic<>::FuzzArrayElement(p, rcelms);
}
return p;
}
static char* _fz_sz_tokenizeSpaces(__in char* psz) static char* _fz_sz_tokenizeSpaces(__in char* psz)
{ {
const _fuzz_type_entry<DWORD> repeatMap[] = { const _fuzz_type_entry<DWORD> repeatMap[] = {

View file

@ -121,6 +121,16 @@ namespace Microsoft::Console::Types
[[nodiscard]] static SomeViewports Subtract(const Viewport& original, const Viewport& removeMe) noexcept; [[nodiscard]] static SomeViewports Subtract(const Viewport& original, const Viewport& removeMe) noexcept;
constexpr bool operator==(const Viewport& other) const noexcept
{
return _sr == other._sr;
}
constexpr bool operator!=(const Viewport& other) const noexcept
{
return _sr != other._sr;
}
private: private:
Viewport(const SMALL_RECT sr) noexcept; Viewport(const SMALL_RECT sr) noexcept;
@ -142,15 +152,3 @@ inline COORD operator-(const COORD& c) noexcept
{ {
return { -c.X, -c.Y }; return { -c.X, -c.Y };
} }
inline bool operator==(const Microsoft::Console::Types::Viewport& a,
const Microsoft::Console::Types::Viewport& b) noexcept
{
return a.ToInclusive() == b.ToInclusive();
}
inline bool operator!=(const Microsoft::Console::Types::Viewport& a,
const Microsoft::Console::Types::Viewport& b) noexcept
{
return !(a == b);
}

View file

@ -22,44 +22,48 @@ class ConPtyTests
TEST_METHOD(DiesOnClose); TEST_METHOD(DiesOnClose);
}; };
HRESULT _CreatePseudoConsole(const COORD size, static HRESULT _CreatePseudoConsole(const COORD size,
const HANDLE hInput, const HANDLE hInput,
const HANDLE hOutput, const HANDLE hOutput,
const DWORD dwFlags, const DWORD dwFlags,
_Inout_ PseudoConsole* pPty) _Inout_ PseudoConsole* pPty)
{ {
return _CreatePseudoConsole(INVALID_HANDLE_VALUE, size, hInput, hOutput, dwFlags, pPty); return _CreatePseudoConsole(INVALID_HANDLE_VALUE, size, hInput, hOutput, dwFlags, pPty);
} }
HRESULT AttachPseudoConsole(HPCON hPC, LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList) static HRESULT AttachPseudoConsole(HPCON hPC, std::wstring& command, PROCESS_INFORMATION* ppi)
{ {
BOOL fSuccess = UpdateProcThreadAttribute(lpAttributeList, SIZE_T size = 0;
0, InitializeProcThreadAttributeList(nullptr, 1, 0, &size);
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, RETURN_LAST_ERROR_IF(size == 0);
hPC,
sizeof(HANDLE),
nullptr,
nullptr);
return fSuccess ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}
void _CreateChildProcess(std::wstring& command, STARTUPINFOEXW* psiEx, PROCESS_INFORMATION* ppi) const auto buffer = std::make_unique<std::byte[]>(gsl::narrow_cast<size_t>(size));
{
std::unique_ptr<wchar_t[]> mutableCommandline = std::make_unique<wchar_t[]>(command.length() + 1); STARTUPINFOEXW siEx{};
VERIFY_IS_NOT_NULL(mutableCommandline); siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
VERIFY_SUCCEEDED(StringCchCopyW(mutableCommandline.get(), command.length() + 1, command.c_str())); siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(buffer.get());
VERIFY_IS_TRUE(CreateProcessW(
RETURN_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, &size));
auto deleteAttrList = wil::scope_exit([&] {
DeleteProcThreadAttributeList(siEx.lpAttributeList);
});
RETURN_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(siEx.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, hPC, sizeof(HANDLE), nullptr, nullptr));
RETURN_IF_WIN32_BOOL_FALSE(CreateProcessW(
nullptr, nullptr,
mutableCommandline.get(), command.data(),
nullptr, // lpProcessAttributes nullptr, // lpProcessAttributes
nullptr, // lpThreadAttributes nullptr, // lpThreadAttributes
true, // bInheritHandles true, // bInheritHandles
EXTENDED_STARTUPINFO_PRESENT, // dwCreationFlags EXTENDED_STARTUPINFO_PRESENT, // dwCreationFlags
nullptr, // lpEnvironment nullptr, // lpEnvironment
nullptr, // lpCurrentDirectory nullptr, // lpCurrentDirectory
&psiEx->StartupInfo, // lpStartupInfo &siEx.StartupInfo, // lpStartupInfo
ppi // lpProcessInformation ppi // lpProcessInformation
)); ));
return S_OK;
} }
void ConPtyTests::CreateConPtyNoPipes() void ConPtyTests::CreateConPtyNoPipes()
@ -200,27 +204,9 @@ void ConPtyTests::SurvivesOnBreakInput()
VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
STARTUPINFOEXW siEx;
siEx = { 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
size_t size;
VERIFY_IS_FALSE(InitializeProcThreadAttributeList(NULL, 1, 0, (PSIZE_T)&size));
BYTE* attrList = new BYTE[size];
auto freeAttrList = wil::scope_exit([&] {
delete[] attrList;
});
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList);
VERIFY_IS_TRUE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, (PSIZE_T)&size));
auto deleteAttrList = wil::scope_exit([&] {
DeleteProcThreadAttributeList(siEx.lpAttributeList);
});
VERIFY_SUCCEEDED(
AttachPseudoConsole(reinterpret_cast<HPCON>(&pty), siEx.lpAttributeList));
wil::unique_process_information piClient; wil::unique_process_information piClient;
std::wstring realCommand = L"cmd.exe"; std::wstring realCommand = L"cmd.exe";
_CreateChildProcess(realCommand, &siEx, piClient.addressof()); VERIFY_SUCCEEDED(AttachPseudoConsole(&pty, realCommand, piClient.addressof()));
VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
@ -263,27 +249,9 @@ void ConPtyTests::SurvivesOnBreakOutput()
VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
STARTUPINFOEXW siEx;
siEx = { 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
size_t size;
VERIFY_IS_FALSE(InitializeProcThreadAttributeList(NULL, 1, 0, (PSIZE_T)&size));
BYTE* attrList = new BYTE[size];
auto freeAttrList = wil::scope_exit([&] {
delete[] attrList;
});
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList);
VERIFY_IS_TRUE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, (PSIZE_T)&size));
auto deleteAttrList = wil::scope_exit([&] {
DeleteProcThreadAttributeList(siEx.lpAttributeList);
});
VERIFY_SUCCEEDED(
AttachPseudoConsole(reinterpret_cast<HPCON>(&pty), siEx.lpAttributeList));
wil::unique_process_information piClient; wil::unique_process_information piClient;
std::wstring realCommand = L"cmd.exe"; std::wstring realCommand = L"cmd.exe";
_CreateChildProcess(realCommand, &siEx, piClient.addressof()); VERIFY_SUCCEEDED(AttachPseudoConsole(&pty, realCommand, piClient.addressof()));
VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
@ -326,27 +294,9 @@ void ConPtyTests::DiesOnBreakBoth()
VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
STARTUPINFOEXW siEx;
siEx = { 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
size_t size;
VERIFY_IS_FALSE(InitializeProcThreadAttributeList(NULL, 1, 0, (PSIZE_T)&size));
BYTE* attrList = new BYTE[size];
auto freeAttrList = wil::scope_exit([&] {
delete[] attrList;
});
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList);
VERIFY_IS_TRUE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, (PSIZE_T)&size));
auto deleteAttrList = wil::scope_exit([&] {
DeleteProcThreadAttributeList(siEx.lpAttributeList);
});
VERIFY_SUCCEEDED(
AttachPseudoConsole(reinterpret_cast<HPCON>(&pty), siEx.lpAttributeList));
wil::unique_process_information piClient; wil::unique_process_information piClient;
std::wstring realCommand = L"cmd.exe"; std::wstring realCommand = L"cmd.exe";
_CreateChildProcess(realCommand, &siEx, piClient.addressof()); VERIFY_SUCCEEDED(AttachPseudoConsole(&pty, realCommand, piClient.addressof()));
VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
@ -415,27 +365,9 @@ void ConPtyTests::DiesOnClose()
VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(pty.hConPtyProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);
STARTUPINFOEXW siEx;
siEx = { 0 };
siEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);
size_t size;
VERIFY_IS_FALSE(InitializeProcThreadAttributeList(NULL, 1, 0, (PSIZE_T)&size));
BYTE* attrList = new BYTE[size];
auto freeAttrList = wil::scope_exit([&] {
delete[] attrList;
});
siEx.lpAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(attrList);
VERIFY_IS_TRUE(InitializeProcThreadAttributeList(siEx.lpAttributeList, 1, 0, (PSIZE_T)&size));
auto deleteAttrList = wil::scope_exit([&] {
DeleteProcThreadAttributeList(siEx.lpAttributeList);
});
VERIFY_SUCCEEDED(
AttachPseudoConsole(reinterpret_cast<HPCON>(&pty), siEx.lpAttributeList));
wil::unique_process_information piClient; wil::unique_process_information piClient;
std::wstring realCommand = testCommandline; std::wstring realCommand(reinterpret_cast<const wchar_t*>(testCommandline.GetBuffer()), testCommandline.GetLength());
_CreateChildProcess(realCommand, &siEx, piClient.addressof()); VERIFY_SUCCEEDED(AttachPseudoConsole(&pty, realCommand, piClient.addressof()));
VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit)); VERIFY_IS_TRUE(GetExitCodeProcess(piClient.hProcess, &dwExit));
VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE); VERIFY_ARE_EQUAL(dwExit, (DWORD)STILL_ACTIVE);