Merged PR 5770253: [Git2Git] Merged PR 5760120: Add propsheet chooser to Windows
[Git2Git] Merged PR 5760120: Add propsheet chooser to Windows Now the inbox console propsheet can choose which terminal is default Related work items: MSFT-32007202 #492 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev d80f506858bd990c267de6cefae7ff55707b3a57
This commit is contained in:
parent
ce99c2a349
commit
3909cc103a
|
@ -56,7 +56,7 @@ try
|
|||
if (SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(isEnabled) && isEnabled))
|
||||
{
|
||||
IID delegationClsid;
|
||||
if (SUCCEEDED(DelegationConfig::s_GetConsole(delegationClsid)))
|
||||
if (SUCCEEDED(DelegationConfig::s_GetDefaultConsoleId(delegationClsid)))
|
||||
{
|
||||
Globals.handoffConsoleClsid = delegationClsid;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace til::pmr
|
|||
// get_default_resource below forces it to be included by the compiler.
|
||||
// I *believe* that if the VC++ Runtime is updated to include the PMR source,
|
||||
// this will safely no-op (since it's an ALTERNATENAME).
|
||||
#if defined(_M_AMD64) || defined(_M_ARM64)
|
||||
#if defined(_M_AMD64) || defined(_M_ARM64) || defined(_M_ARM)
|
||||
#pragma comment(linker, "/ALTERNATENAME:_Aligned_get_default_resource=TIL_PMR_Aligned_get_default_resource")
|
||||
#else
|
||||
#pragma comment(linker, "/ALTERNATENAME:__Aligned_get_default_resource=_TIL_PMR_Aligned_get_default_resource")
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "OptionsPage.h" // For InitializeCursorSize
|
||||
#include "ColorControl.h"
|
||||
#include <functional>
|
||||
#include "../propslib/DelegationConfig.hpp"
|
||||
#include "../types/inc/User32Utils.hpp"
|
||||
|
||||
// From conattrs.h
|
||||
const COLORREF INVALID_COLOR = 0xffffffff;
|
||||
|
@ -87,6 +89,41 @@ void _UpdateTextAndScroll(const HWND hDlg,
|
|||
SendDlgItemMessage(hDlg, scrollItem, UDM_SETPOS, 0, MAKELONG(value, 0));
|
||||
}
|
||||
|
||||
void _PrepDefAppCombo(const HWND hDlg,
|
||||
const int dlgItem,
|
||||
const std::vector<DelegationConfig::DelegationPackage>& list,
|
||||
const DelegationConfig::DelegationPackage& selected)
|
||||
{
|
||||
const HWND hCombo = GetDlgItem(hDlg, dlgItem);
|
||||
ComboBox_ResetContent(hCombo);
|
||||
|
||||
DWORD selectedIndex = 0;
|
||||
for (DWORD i = 0; i < gsl::narrow<DWORD>(list.size()); ++i)
|
||||
{
|
||||
auto& item = list[i];
|
||||
|
||||
// An empty CLSID is a sentinel for the inbox console.
|
||||
if (item.terminal.clsid == CLSID{ 0 })
|
||||
{
|
||||
const auto name = GetStringResource(IDS_TERMINAL_DEF_INBOX);
|
||||
ComboBox_AddString(hCombo, name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ComboBox_AddString(hCombo, item.terminal.name.c_str());
|
||||
}
|
||||
ComboBox_SetItemData(hCombo, i, &item);
|
||||
if (selected == item)
|
||||
{
|
||||
selectedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox_SetCurSel(hCombo, selectedIndex);
|
||||
|
||||
ComboBox_Enable(hCombo, TRUE);
|
||||
}
|
||||
|
||||
bool InitTerminalDialog(const HWND hDlg) noexcept
|
||||
{
|
||||
// Initialize the global handle to this dialog
|
||||
|
@ -181,6 +218,11 @@ bool InitTerminalDialog(const HWND hDlg) noexcept
|
|||
|
||||
CheckDlgButton(hDlg, IDD_DISABLE_SCROLLFORWARD, gpStateInfo->TerminalScrolling);
|
||||
|
||||
_PrepDefAppCombo(hDlg,
|
||||
IDD_TERMINAL_COMBO_DEFTERM,
|
||||
g_availablePackages,
|
||||
g_selectedPackage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -341,11 +383,27 @@ bool TerminalDlgCommand(const HWND hDlg, const WORD item, const WORD command) no
|
|||
break;
|
||||
}
|
||||
case IDD_DISABLE_SCROLLFORWARD:
|
||||
{
|
||||
gpStateInfo->TerminalScrolling = IsDlgButtonChecked(hDlg, IDD_DISABLE_SCROLLFORWARD);
|
||||
UpdateApplyButton(hDlg);
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
case IDD_TERMINAL_COMBO_DEFTERM:
|
||||
{
|
||||
if (CBN_SELCHANGE == command)
|
||||
{
|
||||
const HWND hCombo = GetDlgItem(hDlg, IDD_TERMINAL_COMBO_DEFTERM);
|
||||
const DWORD comboItem = ComboBox_GetCurSel(hCombo);
|
||||
if (CB_ERR != comboItem)
|
||||
{
|
||||
const auto pPackage = reinterpret_cast<const DelegationConfig::DelegationPackage* const>(ComboBox_GetItemData(hCombo, comboItem));
|
||||
g_selectedPackage = *pPackage;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ Revision History:
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
#include "conint.h"
|
||||
|
||||
#pragma hdrstop
|
||||
|
||||
UINT gnCurrentPage;
|
||||
|
@ -94,6 +96,11 @@ void SaveConsoleSettingsIfNeeded(const HWND hwnd)
|
|||
gpStateInfo->FaceName[0] = TEXT('\0');
|
||||
}
|
||||
|
||||
if (g_defAppEnabled)
|
||||
{
|
||||
LOG_IF_FAILED(DelegationConfig::s_SetDefaultByPackage(g_selectedPackage));
|
||||
}
|
||||
|
||||
if (gpStateInfo->LinkTitle != nullptr)
|
||||
{
|
||||
SetGlobalRegistryValues();
|
||||
|
@ -545,7 +552,14 @@ BOOL PopulatePropSheetPageArray(_Out_writes_(cPsps) PROPSHEETPAGE* pPsp, const s
|
|||
{
|
||||
pTerminalPage->dwSize = sizeof(PROPSHEETPAGE);
|
||||
pTerminalPage->hInstance = ghInstance;
|
||||
pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL);
|
||||
if (g_defAppEnabled)
|
||||
{
|
||||
pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL_WITH_DEFTERM);
|
||||
}
|
||||
else
|
||||
{
|
||||
pTerminalPage->pszTemplate = MAKEINTRESOURCE(DID_TERMINAL);
|
||||
}
|
||||
pTerminalPage->pfnDlgProc = TerminalDlgProc;
|
||||
pTerminalPage->lParam = TERMINAL_PAGE_INDEX;
|
||||
pTerminalPage->dwFlags = PSP_DEFAULT;
|
||||
|
@ -611,6 +625,15 @@ INT_PTR ConsolePropertySheet(__in HWND hWnd, __in PCONSOLE_STATE_INFO pStateInfo
|
|||
// since we just triggered font enumeration, recreate our font handles to adapt for DPI
|
||||
RecreateFontHandles(hWnd);
|
||||
|
||||
//
|
||||
// Find the available default console/terminal packages
|
||||
//
|
||||
|
||||
if (SUCCEEDED(Microsoft::Console::Internal::DefaultApp::CheckDefaultAppPolicy(g_defAppEnabled)) && g_defAppEnabled)
|
||||
{
|
||||
LOG_IF_FAILED(DelegationConfig::s_GetAvailablePackages(g_availablePackages, g_selectedPackage));
|
||||
}
|
||||
|
||||
//
|
||||
// Get the current page number
|
||||
//
|
||||
|
|
|
@ -58,6 +58,7 @@ Revision History:
|
|||
// unused 16
|
||||
#define IDS_TOOLTIP_OPACITY 17
|
||||
#define IDS_TOOLTIP_INTERCEPT_COPY_PASTE 18
|
||||
#define IDS_TERMINAL_DEF_INBOX 19
|
||||
// clang-format on
|
||||
|
||||
void MakeAltRasterFont(
|
||||
|
|
|
@ -534,6 +534,17 @@ END
|
|||
#define T_SCROLL_W 100
|
||||
#define T_SCROLL_H 40
|
||||
|
||||
// default application group box
|
||||
#define T_DEFAPP_X T_CCOLOR_X
|
||||
#define T_DEFAPP_Y T_SCROLL_Y
|
||||
#define T_DEFAPP_W T_CCOLOR_W
|
||||
#define T_DEFAPP_H T_SCROLL_H
|
||||
|
||||
#define T_DEFTERM_X (T_DEFAPP_X+P_1)
|
||||
#define T_DEFTERM_Y (T_DEFAPP_Y+P_2)
|
||||
#define T_DEFTERM_W (T_DEFAPP_W-P_4-P_4)
|
||||
#define T_DEFTERM_H 25
|
||||
|
||||
#define UPDOWN_STYLES (UDS_AUTOBUDDY | UDS_SETBUDDYINT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_ALIGNRIGHT)
|
||||
DID_TERMINAL DIALOG 0, 0, 245, 226
|
||||
CAPTION " Terminal "
|
||||
|
@ -624,6 +635,98 @@ BEGIN
|
|||
IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10
|
||||
END
|
||||
|
||||
DID_TERMINAL_WITH_DEFTERM DIALOG 0, 0, 245, 226
|
||||
CAPTION " Terminal "
|
||||
STYLE WS_VISIBLE | WS_CAPTION | WS_CHILD | DS_MODALFRAME
|
||||
FONT 8,"MS Shell Dlg"
|
||||
BEGIN
|
||||
|
||||
// GROUPBOX text, id, x, y, width, height [, style [, extended-style]]
|
||||
// CONTROL text, id, class, style, x, y, width, height [, extended-style]
|
||||
|
||||
GROUPBOX "Terminal Colors", -1, T_COLORS_X, T_COLORS_Y, T_COLORS_W, T_COLORS_H, WS_GROUP
|
||||
|
||||
AUTOCHECKBOX "Use Separate Foreground", IDD_USE_TERMINAL_FG, T_COLORS_X+P_1, T_COLORS_CHECK_Y, T_COLORS_FG_W, 10
|
||||
|
||||
CONTROL "", IDD_TERMINAL_FGCOLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP ,
|
||||
T_COLORS_X+P_2, T_COLORS_RED_Y, COLOR_SIZE, COLOR_SIZE
|
||||
|
||||
LTEXT "Red:", -1, T_COLORS_FG_TEXT_X, T_COLORS_RED_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_FG_RED, T_COLORS_FG_INPUT_X, T_COLORS_RED_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_FG_REDSCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Green:", -1, T_COLORS_FG_TEXT_X, T_COLORS_GREEN_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_FG_GREEN, T_COLORS_FG_INPUT_X, T_COLORS_GREEN_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_FG_GREENSCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Blue:", -1, T_COLORS_FG_TEXT_X, T_COLORS_BLUE_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_FG_BLUE, T_COLORS_FG_INPUT_X, T_COLORS_BLUE_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_FG_BLUESCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
AUTOCHECKBOX "Use Separate Background", IDD_USE_TERMINAL_BG, T_COLORS_BG_X, T_COLORS_CHECK_Y, T_COLORS_FG_W, 10
|
||||
|
||||
CONTROL "", IDD_TERMINAL_BGCOLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP ,
|
||||
T_COLORS_BG_X, T_COLORS_RED_Y, COLOR_SIZE, COLOR_SIZE
|
||||
|
||||
LTEXT "Red:", -1, T_COLORS_BG_TEXT_X, T_COLORS_RED_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_BG_RED, T_COLORS_BG_INPUT_X, T_COLORS_RED_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_BG_REDSCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Green:", -1, T_COLORS_BG_TEXT_X, T_COLORS_GREEN_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_BG_GREEN, T_COLORS_BG_INPUT_X, T_COLORS_GREEN_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_BG_GREENSCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Blue:", -1, T_COLORS_BG_TEXT_X, T_COLORS_BLUE_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_BG_BLUE, T_COLORS_BG_INPUT_X, T_COLORS_BLUE_Y, T_COLORS_EDIT_W, T_COLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_BG_BLUESCROLL, UPDOWN_CLASS,
|
||||
UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
|
||||
GROUPBOX "Cursor Shape", -1, T_CSTYLE_X, T_CSTYLE_Y, T_CSTYLE_W, T_CSTYLE_H
|
||||
AUTORADIOBUTTON "Use Legacy Style", IDD_TERMINAL_LEGACY_CURSOR, T_CSTYLE_X+P_1, T_CSTYLE_R_1_Y, T_CSTYLE_R_W, T_CSTYLE_R_H, WS_TABSTOP|WS_GROUP
|
||||
AUTORADIOBUTTON "Underscore", IDD_TERMINAL_UNDERSCORE, T_CSTYLE_X+P_1, T_CSTYLE_R_2_Y, T_CSTYLE_R_W, T_CSTYLE_R_H,
|
||||
AUTORADIOBUTTON "Vertical Bar", IDD_TERMINAL_VERTBAR, T_CSTYLE_X+P_1, T_CSTYLE_R_3_Y, T_CSTYLE_R_W, T_CSTYLE_R_H,
|
||||
AUTORADIOBUTTON "Empty Box", IDD_TERMINAL_EMPTYBOX, T_CSTYLE_X+P_1, T_CSTYLE_R_4_Y, T_CSTYLE_R_W, T_CSTYLE_R_H,
|
||||
AUTORADIOBUTTON "Solid Box", IDD_TERMINAL_SOLIDBOX, T_CSTYLE_X+P_1, T_CSTYLE_R_5_Y, T_CSTYLE_R_W, T_CSTYLE_R_H,
|
||||
|
||||
|
||||
GROUPBOX "Cursor Colors", -1, T_CCOLOR_X, T_CCOLOR_Y, T_CCOLOR_W, T_CCOLOR_H, WS_GROUP
|
||||
|
||||
AUTORADIOBUTTON "Inverse Color", IDD_TERMINAL_INVERSE_CURSOR, T_CCOLOR_X+P_1, T_CSTYLE_R_1_Y, T_CCOLOR_R_W, T_CSTYLE_R_H, WS_TABSTOP|WS_GROUP
|
||||
|
||||
AUTORADIOBUTTON "Use Color", IDD_TERMINAL_CURSOR_USECOLOR, T_CCOLOR_X+P_1, T_CSTYLE_R_2_Y, T_CCOLOR_R_W, T_CSTYLE_R_H,
|
||||
|
||||
CONTROL "", IDD_TERMINAL_CURSOR_COLOR, "SimpleColor", WS_BORDER | WS_CHILD | WS_GROUP,
|
||||
T_CCOLOR_X+P_2, T_CSTYLE_R_3_Y, COLOR_SIZE, COLOR_SIZE
|
||||
|
||||
LTEXT "Red:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_R_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_CURSOR_RED, T_CCOLOR_EDIT_X, T_CCOLOR_R_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_CURSOR_REDSCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Green:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_G_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_CURSOR_GREEN, T_CCOLOR_EDIT_X, T_CCOLOR_G_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_CURSOR_GREENSCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
LTEXT "Blue:", -1, T_CCOLOR_TEXT_X, T_CCOLOR_B_Y, T_COLORS_TEXT_W, 9
|
||||
EDITTEXT IDD_TERMINAL_CURSOR_BLUE, T_CCOLOR_EDIT_X, T_CCOLOR_B_Y, T_CCOLORS_EDIT_W, T_CCOLORS_EDIT_H, WS_TABSTOP | WS_GROUP | ES_AUTOHSCROLL
|
||||
CONTROL "", IDD_TERMINAL_CURSOR_BLUESCROLL, UPDOWN_CLASS, UPDOWN_STYLES, 0, 0, 0, 0
|
||||
|
||||
|
||||
GROUPBOX "Terminal Scrolling", -1, T_SCROLL_X, T_SCROLL_Y, T_SCROLL_W, T_SCROLL_H
|
||||
AUTOCHECKBOX "Disable Scroll-Forward", IDD_DISABLE_SCROLLFORWARD, T_SCROLL_X+P_1, T_SCROLL_Y+P_2, T_SCROLL_W-P_4-P_4, 10
|
||||
|
||||
GROUPBOX "Default Terminal Application", -1, T_DEFAPP_X, T_DEFAPP_Y, T_DEFAPP_W, T_DEFAPP_H
|
||||
COMBOBOX IDD_TERMINAL_COMBO_DEFTERM, T_DEFTERM_X+P_0, T_DEFTERM_Y, T_DEFTERM_W, 10, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
CONTROL "Find out more about <A HREF=""https://go.microsoft.com/fwlink/?linkid=2028595"">experimental terminal settings</A>",
|
||||
IDD_HELP_TERMINAL, "SysLink", WS_TABSTOP, 10, 225, 200, 10
|
||||
END
|
||||
|
||||
|
||||
//
|
||||
// Strings
|
||||
|
@ -646,6 +749,7 @@ BEGIN
|
|||
IDS_TOOLTIP_EDIT_KEYS, "Enable enhanced keyboard editing on command line."
|
||||
IDS_TOOLTIP_OPACITY, "Adjust the transparency of the console window."
|
||||
IDS_TOOLTIP_INTERCEPT_COPY_PASTE, "Use Ctrl+Shift+C/V as copy/paste shortcuts, regardless of input mode"
|
||||
IDS_TERMINAL_DEF_INBOX, "Windows Console Host"
|
||||
END
|
||||
|
||||
|
||||
|
|
|
@ -164,6 +164,8 @@ Revision History:
|
|||
#define IDD_TERMINAL_CURSOR_GREEN 630
|
||||
#define IDD_TERMINAL_CURSOR_BLUE 631
|
||||
#define IDD_HELP_TERMINAL 632
|
||||
#define DID_TERMINAL_WITH_DEFTERM 640
|
||||
#define IDD_TERMINAL_COMBO_DEFTERM 641
|
||||
|
||||
#define BM_TRUETYPE_ICON 1000
|
||||
|
||||
|
|
|
@ -59,3 +59,7 @@ COLORREF g_fakeCursorColor = RGB(242, 242, 242); // Default bright white
|
|||
|
||||
HWND g_hTerminalDlg = static_cast<HWND>(INVALID_HANDLE_VALUE);
|
||||
HWND g_hOptionsDlg = static_cast<HWND>(INVALID_HANDLE_VALUE);
|
||||
|
||||
bool g_defAppEnabled = false;
|
||||
std::vector<DelegationConfig::DelegationPackage> g_availablePackages;
|
||||
DelegationConfig::DelegationPackage g_selectedPackage;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "font.h"
|
||||
#include "../propslib/DelegationConfig.hpp"
|
||||
|
||||
extern HINSTANCE ghInstance;
|
||||
extern PCONSOLE_STATE_INFO gpStateInfo;
|
||||
|
@ -54,3 +55,7 @@ extern COLORREF g_fakeCursorColor;
|
|||
|
||||
extern HWND g_hTerminalDlg;
|
||||
extern HWND g_hOptionsDlg;
|
||||
|
||||
extern bool g_defAppEnabled;
|
||||
extern std::vector<DelegationConfig::DelegationPackage> g_availablePackages;
|
||||
extern DelegationConfig::DelegationPackage g_selectedPackage;
|
||||
|
|
|
@ -53,6 +53,9 @@
|
|||
<ProjectReference Include="..\propslib\propslib.vcxproj">
|
||||
<Project>{345fd5a4-b32b-4f29-bd1c-b033bd2c35cc}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\internal\internal.vcxproj">
|
||||
<Project>{EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="console.def" />
|
||||
|
|
|
@ -84,6 +84,8 @@ TARGETLIBS = \
|
|||
$(ONECORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\onecore_internal.lib \
|
||||
$(ONECORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\onecoreuap_internal.lib \
|
||||
$(ONECOREUAP_INTERNAL_SDK_LIB_PATH)\onecoreuapuuid.lib \
|
||||
$(ONECORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-dwmapi-ext-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-edputil-policy-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-gdi-dc-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-gdi-dc-create-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-gdi-draw-l1.lib \
|
||||
|
@ -100,10 +102,39 @@ TARGETLIBS = \
|
|||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-syscolors-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-rtcore-ntuser-sysparams-l1.lib\
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-shell-shell32-l1.lib \
|
||||
$(MINCORE_INTERNAL_PRIV_SDK_LIB_VPATH_L)\ext-ms-win-uxtheme-themes-l1.lib \
|
||||
$(ONECOREBASE_INTERNAL_LIB_VPATH_L)\ext-ms-win-appmodel-shellexecute-l1.lib \
|
||||
$(ONECOREWINDOWS_INTERNAL_LIB_PATH_L)\ext-ms-win-gdi-internal-desktop-l1-1-1.lib \
|
||||
$(WINCORE_OBJ_PATH)\console\conint\$(O)\conint.lib \
|
||||
$(WINCORE_OBJ_PATH)\console\open\src\propslib\$(O)\conprops.lib \
|
||||
|
||||
DELAYLOAD = \
|
||||
ext-ms-win-dwmapi-ext-l1.dll; \
|
||||
ext-ms-win-edputil-policy-l1.dll; \
|
||||
ext-ms-win-uxtheme-themes-l1.dll; \
|
||||
ext-ms-win-shell32-shellfolders-l1.dll; \
|
||||
ext-ms-win-gdi-dc-l1.dll; \
|
||||
ext-ms-win-gdi-dc-create-l1.dll; \
|
||||
ext-ms-win-gdi-draw-l1.dll; \
|
||||
ext-ms-win-gdi-font-l1.dll; \
|
||||
ext-ms-win-ntuser-dialogbox-l1.dll; \
|
||||
ext-ms-win-ntuser-draw-l1.dll; \
|
||||
ext-ms-win-ntuser-keyboard-l1.dll; \
|
||||
ext-ms-win-ntuser-gui-l1.dll; \
|
||||
ext-ms-win-ntuser-misc-l1.dll; \
|
||||
ext-ms-win-ntuser-window-l1.dll; \
|
||||
ext-ms-win-rtcore-gdi-object-l1.dll; \
|
||||
ext-ms-win-rtcore-ntuser-cursor-l1.dll; \
|
||||
ext-ms-win-rtcore-ntuser-dc-access-l1.dll; \
|
||||
ext-ms-win-rtcore-ntuser-syscolors-l1.dll; \
|
||||
ext-ms-win-rtcore-ntuser-sysparams-l1.dll; \
|
||||
ext-ms-win-shell-shell32-l1.dll; \
|
||||
ext-ms-win-appmodel-shellexecute-l1.dll; \
|
||||
ext-ms-win-gdi-internal-desktop-l1.dll; \
|
||||
|
||||
|
||||
DLOAD_ERROR_HANDLER = kernelbase
|
||||
|
||||
# -------------------------------------
|
||||
# Side-by-side Manifesting
|
||||
# -------------------------------------
|
||||
|
|
|
@ -33,7 +33,15 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector<T>& vec) noexcept
|
|||
{
|
||||
vec.clear();
|
||||
|
||||
auto coinit = wil::CoInitializeEx(COINIT_MULTITHREADED);
|
||||
T useInbox = { 0 };
|
||||
useInbox.clsid = { 0 };
|
||||
// CLSID of 0 will be sentinel to say "inbox console" or something.
|
||||
// The UI displaying this information will have to go look up appropriate strings
|
||||
// to convey that message.
|
||||
|
||||
vec.push_back(useInbox);
|
||||
|
||||
auto coinit = wil::CoInitializeEx(COINIT_APARTMENTTHREADED);
|
||||
|
||||
ComPtr<IAppExtensionCatalogStatics> catalogStatics;
|
||||
RETURN_IF_FAILED(Windows::Foundation::GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_AppExtensions_AppExtensionCatalog).Get(), &catalogStatics));
|
||||
|
@ -59,24 +67,34 @@ HRESULT _lookupCatalog(PCWSTR extensionName, std::vector<T>& vec) noexcept
|
|||
ComPtr<IPackage> extensionPackage;
|
||||
RETURN_IF_FAILED(extension->get_Package(&extensionPackage));
|
||||
|
||||
ComPtr<IPackage2> extensionPackage2;
|
||||
RETURN_IF_FAILED(extensionPackage.As(&extensionPackage2));
|
||||
|
||||
ComPtr<IPackageId> extensionPackageId;
|
||||
RETURN_IF_FAILED(extensionPackage->get_Id(&extensionPackageId));
|
||||
|
||||
HString publisherId;
|
||||
RETURN_IF_FAILED(extensionPackageId->get_PublisherId(publisherId.GetAddressOf()));
|
||||
|
||||
// PackageId.Name
|
||||
HString name;
|
||||
RETURN_IF_FAILED(extensionPackageId->get_Name(name.GetAddressOf()));
|
||||
|
||||
RETURN_IF_FAILED(extensionPackage2->get_DisplayName(name.GetAddressOf()));
|
||||
extensionMetadata.name = std::wstring{ name.GetRawBuffer(nullptr) };
|
||||
|
||||
// PackageId.Version
|
||||
HString publisher;
|
||||
RETURN_IF_FAILED(extensionPackageId->get_Publisher(publisher.GetAddressOf()));
|
||||
|
||||
RETURN_IF_FAILED(extensionPackage2->get_PublisherDisplayName(publisher.GetAddressOf()));
|
||||
extensionMetadata.author = std::wstring{ publisher.GetRawBuffer(nullptr) };
|
||||
|
||||
HString pfn;
|
||||
RETURN_IF_FAILED(extensionPackageId->get_FamilyName(pfn.GetAddressOf()));
|
||||
extensionMetadata.pfn = std::wstring{ pfn.GetRawBuffer(nullptr) };
|
||||
|
||||
PackageVersion version;
|
||||
RETURN_IF_FAILED(extensionPackageId->get_Version(&version));
|
||||
extensionMetadata.version.major = version.Major;
|
||||
extensionMetadata.version.minor = version.Minor;
|
||||
extensionMetadata.version.build = version.Build;
|
||||
extensionMetadata.version.revision = version.Revision;
|
||||
|
||||
// Fetch the custom properties XML out of the extension information
|
||||
ComPtr<IAsyncOperation<IPropertySet*>> propertiesOperation;
|
||||
RETURN_IF_FAILED(extension->GetExtensionPropertiesAsync(&propertiesOperation));
|
||||
|
@ -149,23 +167,91 @@ try
|
|||
}
|
||||
CATCH_RETURN()
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_SetConsole(const DelegationConsole& console) noexcept
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_GetAvailablePackages(std::vector<DelegationPackage>& packages, DelegationPackage& defPackage) noexcept
|
||||
try
|
||||
{
|
||||
return s_Set(DELEGATION_CONSOLE_KEY_NAME, console.clsid);
|
||||
packages.clear();
|
||||
|
||||
std::vector<DelegationConsole> consoles;
|
||||
RETURN_IF_FAILED(s_GetAvailableConsoles(consoles));
|
||||
|
||||
std::vector<DelegationTerminal> terminals;
|
||||
RETURN_IF_FAILED(s_GetAvailableTerminals(terminals));
|
||||
|
||||
// TODO: I hate this algorithm (it's bad performance), but I couldn't
|
||||
// find an AppModel interface that would let me look up all the extensions
|
||||
// in one package.
|
||||
for (auto& term : terminals)
|
||||
{
|
||||
for (auto& con : consoles)
|
||||
{
|
||||
if (term.IsFromSamePackage(con))
|
||||
{
|
||||
DelegationPackage pkg;
|
||||
pkg.terminal = term;
|
||||
pkg.console = con;
|
||||
packages.push_back(pkg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We should find at least one package.
|
||||
RETURN_HR_IF(E_FAIL, packages.empty());
|
||||
|
||||
// We also find the default here while we have the list of available ones so
|
||||
// we can return the opaque structure instead of the raw IID.
|
||||
IID defCon;
|
||||
RETURN_IF_FAILED(s_GetDefaultConsoleId(defCon));
|
||||
IID defTerm;
|
||||
RETURN_IF_FAILED(s_GetDefaultTerminalId(defTerm));
|
||||
|
||||
// The default one is the 0th one because that's supposed to be the inbox conhost one.
|
||||
DelegationPackage chosenPackage = packages.at(0);
|
||||
|
||||
// Search through and find a package that matches. If we failed to match because
|
||||
// it's torn across multiple or something not in the catalog, we'll offer the inbox conhost one.
|
||||
for (auto& pkg : packages)
|
||||
{
|
||||
if (pkg.console.clsid == defCon && pkg.terminal.clsid == defTerm)
|
||||
{
|
||||
chosenPackage = pkg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
defPackage = chosenPackage;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultConsoleById(const IID& iid) noexcept
|
||||
{
|
||||
return s_Set(DELEGATION_CONSOLE_KEY_NAME, iid);
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_SetTerminal(const DelegationTerminal& terminal) noexcept
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultTerminalById(const IID& iid) noexcept
|
||||
{
|
||||
return s_Set(DELEGATION_TERMINAL_KEY_NAME, terminal.clsid);
|
||||
return s_Set(DELEGATION_TERMINAL_KEY_NAME, iid);
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_GetConsole(IID& iid) noexcept
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_SetDefaultByPackage(const DelegationPackage& package) noexcept
|
||||
{
|
||||
RETURN_IF_FAILED(s_SetDefaultConsoleById(package.console.clsid));
|
||||
RETURN_IF_FAILED(s_SetDefaultTerminalById(package.terminal.clsid));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_GetDefaultConsoleId(IID& iid) noexcept
|
||||
{
|
||||
iid = { 0 };
|
||||
return s_Get(DELEGATION_CONSOLE_KEY_NAME, iid);
|
||||
}
|
||||
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_GetTerminal(IID& iid) noexcept
|
||||
[[nodiscard]] HRESULT DelegationConfig::s_GetDefaultTerminalId(IID& iid) noexcept
|
||||
{
|
||||
iid = { 0 };
|
||||
return s_Get(DELEGATION_TERMINAL_KEY_NAME, iid);
|
||||
}
|
||||
|
||||
|
@ -192,7 +278,7 @@ CATCH_RETURN()
|
|||
RETURN_NTSTATUS(result);
|
||||
}
|
||||
|
||||
auto buffer = std::make_unique<wchar_t[]>(bytesNeeded / sizeof(wchar_t));
|
||||
auto buffer = std::make_unique<wchar_t[]>(bytesNeeded / sizeof(wchar_t) + 1);
|
||||
|
||||
DWORD bytesUsed = 0;
|
||||
|
||||
|
@ -222,7 +308,7 @@ try
|
|||
wil::unique_cotaskmem_string str;
|
||||
RETURN_IF_FAILED(StringFromCLSID(clsid, &str));
|
||||
|
||||
RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(startupKey.get(), value, REG_SZ, reinterpret_cast<BYTE*>(str.get()), gsl::narrow<DWORD>(wcslen(str.get() + 1) * sizeof(wchar_t))));
|
||||
RETURN_IF_NTSTATUS_FAILED(RegistrySerialization::s_SetValue(startupKey.get(), value, REG_SZ, reinterpret_cast<BYTE*>(str.get()), gsl::narrow<DWORD>(wcslen(str.get()) * sizeof(wchar_t))));
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,46 @@ Author(s):
|
|||
class DelegationConfig
|
||||
{
|
||||
public:
|
||||
struct PkgVersion
|
||||
{
|
||||
unsigned short major;
|
||||
unsigned short minor;
|
||||
unsigned short build;
|
||||
unsigned short revision;
|
||||
|
||||
bool operator==(const PkgVersion& other) const
|
||||
{
|
||||
return major == other.major &&
|
||||
minor == other.minor &&
|
||||
build == other.build &&
|
||||
revision == other.revision;
|
||||
}
|
||||
};
|
||||
|
||||
struct DelegationBase
|
||||
{
|
||||
CLSID clsid;
|
||||
std::wstring name;
|
||||
std::wstring author;
|
||||
std::wstring pfn;
|
||||
PkgVersion version;
|
||||
|
||||
bool IsFromSamePackage(const DelegationBase& other) const
|
||||
{
|
||||
return name == other.name &&
|
||||
author == other.author &&
|
||||
pfn == other.pfn &&
|
||||
version == other.version;
|
||||
}
|
||||
|
||||
bool operator==(const DelegationBase& other) const
|
||||
{
|
||||
return clsid == other.clsid &&
|
||||
name == other.name &&
|
||||
author == other.author &&
|
||||
pfn == other.pfn &&
|
||||
version == other.version;
|
||||
}
|
||||
};
|
||||
|
||||
struct DelegationConsole : public DelegationBase
|
||||
|
@ -33,16 +68,32 @@ public:
|
|||
{
|
||||
};
|
||||
|
||||
struct DelegationPackage
|
||||
{
|
||||
DelegationConsole console;
|
||||
DelegationTerminal terminal;
|
||||
|
||||
bool operator==(const DelegationPackage& other) const
|
||||
{
|
||||
return console == other.console &&
|
||||
terminal == other.terminal;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] static HRESULT s_GetAvailablePackages(std::vector<DelegationPackage>& packages, DelegationPackage& default) noexcept;
|
||||
|
||||
[[nodiscard]] static HRESULT s_SetDefaultByPackage(const DelegationPackage& pkg) noexcept;
|
||||
|
||||
[[nodiscard]] static HRESULT s_GetDefaultConsoleId(IID& iid) noexcept;
|
||||
[[nodiscard]] static HRESULT s_GetDefaultTerminalId(IID& iid) noexcept;
|
||||
|
||||
private:
|
||||
[[nodiscard]] static HRESULT s_GetAvailableConsoles(std::vector<DelegationConsole>& consoles) noexcept;
|
||||
[[nodiscard]] static HRESULT s_GetAvailableTerminals(std::vector<DelegationTerminal>& terminals) noexcept;
|
||||
|
||||
[[nodiscard]] static HRESULT s_SetConsole(const DelegationConsole& console) noexcept;
|
||||
[[nodiscard]] static HRESULT s_SetTerminal(const DelegationTerminal& terminal) noexcept;
|
||||
[[nodiscard]] static HRESULT s_SetDefaultConsoleById(const IID& iid) noexcept;
|
||||
[[nodiscard]] static HRESULT s_SetDefaultTerminalById(const IID& iid) noexcept;
|
||||
|
||||
[[nodiscard]] static HRESULT s_GetConsole(IID& iid) noexcept;
|
||||
[[nodiscard]] static HRESULT s_GetTerminal(IID& iid) noexcept;
|
||||
|
||||
private:
|
||||
[[nodiscard]] static HRESULT s_Get(PCWSTR value, IID& iid) noexcept;
|
||||
[[nodiscard]] static HRESULT s_Set(PCWSTR value, const CLSID clsid) noexcept;
|
||||
};
|
||||
|
|
|
@ -51,4 +51,7 @@
|
|||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="$(SolutionDir)tools\ConsoleTypes.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -138,6 +138,79 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleCloseObject(_In_ PCONSOLE_API_MSG pMessag
|
|||
return pMessage;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Uses some information about current console state and
|
||||
// the incoming process state and preferences to determine
|
||||
// whether we should attempt to handoff to a registered console.
|
||||
static bool _shouldAttemptHandoff(const Globals& globals,
|
||||
const CONSOLE_INFORMATION& gci,
|
||||
CONSOLE_API_CONNECTINFO& cac)
|
||||
{
|
||||
// This console is already initialized. Do not
|
||||
// attempt handoff to another one.
|
||||
// Note you can have a non-attach secondary connect for a child process
|
||||
// that is supposed to be inheriting the existing console/window from the parent.
|
||||
if (WI_IsFlagSet(gci.Flags, CONSOLE_INITIALIZED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is an AttachConsole message and not occuring
|
||||
// because of a conclnt!ConsoleInitialize, do not handoff.
|
||||
// ConsoleApp is FALSE for attach.
|
||||
if (!cac.ConsoleApp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it is a PTY session, do not attempt handoff.
|
||||
if (globals.launchArgs.IsHeadless())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we do not have a registered handoff, do not attempt.
|
||||
if (!globals.handoffConsoleClsid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're already a target for receiving another handoff,
|
||||
// do not chain.
|
||||
if (globals.handoffTarget)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the client was started with CREATE_NO_WINDOW to CreateProcess,
|
||||
// this function will say that it does NOT deserve a visible window.
|
||||
// Return false.
|
||||
if (!ConsoleConnectionDeservesVisibleWindow(&cac))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the process is giving us explicit window show information, we need
|
||||
// to look at which one it is.
|
||||
if (WI_IsFlagSet(cac.ConsoleInfo.GetStartupFlags(), STARTF_USESHOWWINDOW))
|
||||
{
|
||||
switch (cac.ConsoleInfo.GetShowWindow())
|
||||
{
|
||||
// For all hide or minimize actions, do not hand off.
|
||||
case SW_HIDE:
|
||||
case SW_SHOWMINIMIZED:
|
||||
case SW_MINIMIZE:
|
||||
case SW_SHOWMINNOACTIVE:
|
||||
case SW_FORCEMINIMIZE:
|
||||
return false;
|
||||
// Intentionally fall through for all others
|
||||
// like maximize and show to hit the true below.
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Used when a client application establishes an initial connection to this console server.
|
||||
// - This is supposed to represent accounting for the process, making the appropriate handles, etc.
|
||||
|
@ -165,12 +238,9 @@ PCONSOLE_API_MSG IoDispatchers::ConsoleHandleConnectionRequest(_In_ PCONSOLE_API
|
|||
goto Error;
|
||||
}
|
||||
|
||||
// If we are NOT a PTY session (headless)...
|
||||
// we have FOUND a CLSID for a different console to be the default startup handler...
|
||||
// we are NOT already receiving an inbound console connection handoff...
|
||||
// and the client app is going to end up showing a window...
|
||||
// If we pass the tests...
|
||||
// then attempt to delegate the startup to the registered replacement.
|
||||
if (!Globals.launchArgs.IsHeadless() && Globals.handoffConsoleClsid && !Globals.handoffTarget && ConsoleConnectionDeservesVisibleWindow(&Cac))
|
||||
if (_shouldAttemptHandoff(Globals, gci, Cac))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue