mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-11 16:51:00 +00:00
222 lines
8.6 KiB
C++
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);
|
|
}
|
|
}
|