Files
terminal/src/interactivity/win32/SystemConfigurationProvider.cpp
2022-07-26 10:29:48 -05:00

222 lines
8.6 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "precomp.h"
#include "SystemConfigurationProvider.hpp"
#include "icon.hpp"
#include "../inc/ServiceLocator.hpp"
using namespace Microsoft::Console::Interactivity::Win32;
UINT SystemConfigurationProvider::GetCaretBlinkTime()
{
return ::GetCaretBlinkTime();
}
bool SystemConfigurationProvider::IsCaretBlinkingEnabled()
{
return GetSystemMetrics(SM_CARETBLINKINGENABLED) ? true : false;
}
int SystemConfigurationProvider::GetNumberOfMouseButtons()
{
return GetSystemMetrics(SM_CMOUSEBUTTONS);
}
ULONG SystemConfigurationProvider::GetCursorWidth()
{
ULONG width;
if (SystemParametersInfoW(SPI_GETCARETWIDTH, 0, &width, FALSE))
{
return width;
}
else
{
LOG_LAST_ERROR();
return s_DefaultCursorWidth;
}
}
ULONG SystemConfigurationProvider::GetNumberOfWheelScrollLines()
{
ULONG lines;
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &lines, FALSE);
return lines;
}
ULONG SystemConfigurationProvider::GetNumberOfWheelScrollCharacters()
{
ULONG characters;
SystemParametersInfoW(SPI_GETWHEELSCROLLCHARS, 0, &characters, FALSE);
return characters;
}
void SystemConfigurationProvider::GetSettingsFromLink(
_Inout_ Settings* pLinkSettings,
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR pwszTitle,
_Inout_ PDWORD pdwTitleLength,
_In_ PCWSTR pwszCurrDir,
_In_ PCWSTR pwszAppName,
_Inout_opt_ IconInfo* iconInfo)
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
WCHAR wszLinkTarget[MAX_PATH] = { 0 };
WCHAR wszIconLocation[MAX_PATH] = { 0 };
auto iIconIndex = 0;
pLinkSettings->SetCodePage(ServiceLocator::LocateGlobals().uiOEMCP);
// Did we get started from a link?
if (pLinkSettings->GetStartupFlags() & STARTF_TITLEISLINKNAME)
{
auto initializedCom = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
// GH#9458: If it's RPC_E_CHANGED_MODE, that's okay, we're doing a
// defterm and have already started COM. We can continue on here.
if (SUCCEEDED(initializedCom) || initializedCom == RPC_E_CHANGED_MODE)
{
// Don't CoUninitialize if we still need COM for defterm.
auto unInitCom = wil::scope_exit([initializedCom]() { if (SUCCEEDED(initializedCom)){CoUninitialize();} });
const auto cch = *pdwTitleLength / sizeof(wchar_t);
gci.SetLinkTitle(std::wstring(pwszTitle, cch));
const auto linkNameForCsi = new (std::nothrow) wchar_t[gci.GetLinkTitle().length() + 1]{ 0 };
if (linkNameForCsi)
{
gci.GetLinkTitle().copy(linkNameForCsi, gci.GetLinkTitle().length());
}
auto csi = pLinkSettings->CreateConsoleStateInfo();
csi.LinkTitle = linkNameForCsi;
WCHAR wszShortcutTitle[MAX_PATH] = L"\0";
auto fReadConsoleProperties = FALSE;
auto wShowWindow = pLinkSettings->GetShowWindow();
auto dwHotKey = pLinkSettings->GetHotKey();
auto iShowWindow = 0;
WORD wHotKey = 0;
auto Status = ShortcutSerialization::s_GetLinkValues(&csi,
&fReadConsoleProperties,
wszShortcutTitle,
ARRAYSIZE(wszShortcutTitle),
wszLinkTarget,
ARRAYSIZE(wszLinkTarget),
wszIconLocation,
ARRAYSIZE(wszIconLocation),
&iIconIndex,
&iShowWindow,
&wHotKey);
if (NT_SUCCESS(Status))
{
// Convert results back to appropriate types and set.
if (SUCCEEDED(IntToWord(iShowWindow, &wShowWindow)))
{
pLinkSettings->SetShowWindow(wShowWindow);
}
dwHotKey = wHotKey;
pLinkSettings->SetHotKey(dwHotKey);
if (wszLinkTarget[0] != L'\0')
{
// guarantee null termination to make OACR happy.
wszLinkTarget[ARRAYSIZE(wszLinkTarget) - 1] = L'\0';
}
}
// if we got a title, use it. even on overall link value load failure, the title will be correct if
// filled out.
if (wszShortcutTitle[0] != L'\0')
{
// guarantee null termination to make OACR happy.
wszShortcutTitle[ARRAYSIZE(wszShortcutTitle) - 1] = L'\0';
StringCbCopyW(pwszTitle, *pdwTitleLength, wszShortcutTitle);
// OACR complains about the use of a DWORD here, so roundtrip through a size_t
size_t cbTitleLength;
if (SUCCEEDED(StringCbLengthW(pwszTitle, *pdwTitleLength, &cbTitleLength)))
{
// don't care about return result -- the buffer is guaranteed null terminated to at least
// the length of Title
(void)SizeTToDWord(cbTitleLength, pdwTitleLength);
}
}
if (NT_SUCCESS(Status) && fReadConsoleProperties)
{
// copy settings
pLinkSettings->InitFromStateInfo(&csi);
// since we were launched via shortcut, make sure we don't let the invoker's STARTUPINFO pollute the
// shortcut's settings
pLinkSettings->UnsetStartupFlag(STARTF_USESIZE | STARTF_USECOUNTCHARS);
}
else
{
// if we didn't find any console properties, or otherwise failed to load link properties, pretend
// like we weren't launched from a shortcut -- this allows us to at least try to find registry
// settings based on title.
pLinkSettings->UnsetStartupFlag(STARTF_TITLEISLINKNAME);
}
}
}
// Go get the icon
if (wszIconLocation[0] == L'\0')
{
if (PathFileExists(wszLinkTarget))
{
StringCchCopyW(wszIconLocation, ARRAYSIZE(wszIconLocation), wszLinkTarget);
}
else
{
// search for the application along the path so that we can load its icons (if we didn't find one explicitly in
// the shortcut)
const auto dwLinkLen = SearchPathW(pwszCurrDir, pwszAppName, nullptr, ARRAYSIZE(wszIconLocation), wszIconLocation, nullptr);
// If we cannot find the application in the path, then try to fall back and see if the window title is a valid path and use that.
if (dwLinkLen <= 0 || dwLinkLen > ARRAYSIZE(wszIconLocation))
{
if (PathFileExistsW(pwszTitle) && (wcslen(pwszTitle) < ARRAYSIZE(wszIconLocation)))
{
StringCchCopyW(wszIconLocation, ARRAYSIZE(wszIconLocation), pwszTitle);
}
else
{
// If all else fails, just stick the app name into the path and try to resolve just the app name.
StringCchCopyW(wszIconLocation, ARRAYSIZE(wszIconLocation), pwszAppName);
}
}
}
}
if (wszIconLocation[0] != L'\0')
{
// GH#9458, GH#13111 - when this is executed during defterm startup,
// we'll pass in an iconInfo pointer, which we should fill with the
// selected icon path and index, rather than loading the icon with our
// global Icon class.
if (iconInfo)
{
iconInfo->path = std::wstring{ wszIconLocation };
iconInfo->index = iIconIndex;
}
else
{
LOG_IF_FAILED(Icon::Instance().LoadIconsFromPath(wszIconLocation, iIconIndex));
}
}
if (!IsValidCodePage(pLinkSettings->GetCodePage()))
{
// make sure we don't leave this function with an invalid codepage
pLinkSettings->SetCodePage(ServiceLocator::LocateGlobals().uiOEMCP);
}
}