Skip to content

Commit

Permalink
Obstruct the user when they try to run WT under WOW (#1648)
Browse files Browse the repository at this point in the history
* Obstruct the user when they try to run under WOW

* Move strings to resource file, add comments to methods, remove extraneous wil include.

* remove excess newline

* output of formatter.
  • Loading branch information
DHowett authored and msftbot[bot] committed Jul 11, 2019
1 parent 594a7e4 commit 60a444c
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 8 deletions.
33 changes: 29 additions & 4 deletions src/cascadia/WindowsTerminal/WindowsTerminal.rc
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,26 @@

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
Expand All @@ -44,11 +45,36 @@ END
#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico"


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE
BEGIN
IDS_ERROR_DIALOG_TITLE "Error"
IDS_ERROR_ARCHITECTURE_FORMAT
"Windows Terminal is designed to run on your system's native architecture (%s).\nYou are currently using the %s version.\n\nPlease use the version of Windows Terminal that matches your system's native architecture."
IDS_X86_ARCHITECTURE "i386"
END

STRINGTABLE
BEGIN
IDS_AMD64_ARCHITECTURE "AMD64"
IDS_ARM64_ARCHITECTURE "ARM64"
IDS_ARM_ARCHITECTURE "ARM"
IDS_UNKNOWN_ARCHITECTURE "Unknown"
END

#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////
Expand All @@ -65,4 +91,3 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico"
87 changes: 87 additions & 0 deletions src/cascadia/WindowsTerminal/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,102 @@

#include "pch.h"
#include "AppHost.h"
#include "resource.h"

using namespace winrt;
using namespace Windows::UI;
using namespace Windows::UI::Composition;
using namespace Windows::UI::Xaml::Hosting;
using namespace Windows::Foundation::Numerics;

// Routine Description:
// - Retrieves the string resource from the current module with the given ID
// from the resources files. See resource.h and the .rc definitions for valid IDs.
// Arguments:
// - id - Resource ID
// Return Value:
// - String resource retrieved from that ID.
static std::wstring GetStringResource(const UINT id)
{
// Calling LoadStringW with a pointer-sized storage and no length will return a read-only pointer
// directly to the resource data instead of copying it immediately into a buffer.
LPWSTR readOnlyResource = nullptr;
const auto length = LoadStringW(wil::GetModuleInstanceHandle(),
id,
reinterpret_cast<LPWSTR>(&readOnlyResource),
0);

// However, the pointer and length given are NOT guaranteed to be zero-terminated
// and most uses of this data will probably want a zero-terminated string.
// So we're going to construct and return a std::wstring copy from the pointer/length
// since those are certainly zero-terminated.
return { readOnlyResource, gsl::narrow<size_t>(length) };
}

// Routine Description:
// - Takes an image architecture and locates a string resource that maps to that architecture.
// Arguments:
// - imageArchitecture - An IMAGE_FILE_MACHINE architecture enum value
// - See https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
// Return Value:
// - A string value representing the human-readable name of this architecture.
static std::wstring ImageArchitectureToString(USHORT imageArchitecture)
{
// clang-format off
const auto id = imageArchitecture == IMAGE_FILE_MACHINE_I386 ? IDS_X86_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_AMD64 ? IDS_AMD64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM64 ? IDS_ARM64_ARCHITECTURE :
imageArchitecture == IMAGE_FILE_MACHINE_ARM ? IDS_ARM_ARCHITECTURE :
IDS_UNKNOWN_ARCHITECTURE;
// clang-format on

return GetStringResource(id);
}

// Routine Description:
// - Blocks the user from launching the application with a message box dialog and early exit
// if the process architecture doesn't match the system platform native architecture.
// - This is because the conhost.exe must match the condrv.sys on the system and the PTY
// infrastructure that powers everything won't work if we have a mismatch.
// Arguments:
// - <none>
// Return Value:
// - <none>
static void EnsureNativeArchitecture()
{
USHORT processMachine{};
USHORT nativeMachine{};
THROW_IF_WIN32_BOOL_FALSE(IsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine));
if (processMachine != IMAGE_FILE_MACHINE_UNKNOWN && processMachine != nativeMachine)
{
const auto formatPattern = GetStringResource(IDS_ERROR_ARCHITECTURE_FORMAT);

const auto nativeArchitecture = ImageArchitectureToString(nativeMachine);
const auto processArchitecture = ImageArchitectureToString(processMachine);

const auto lengthRequired = _scwprintf(formatPattern.data(), nativeArchitecture.data(), processArchitecture.data());
const auto bufferSize = lengthRequired + 1;

std::wstring buffer;
buffer.resize(bufferSize);

swprintf_s(buffer.data(), buffer.size(), formatPattern.data(), nativeArchitecture.data(), processArchitecture.data());

MessageBoxW(nullptr,
buffer.data(),
GetStringResource(IDS_ERROR_DIALOG_TITLE).data(),
MB_OK | MB_ICONERROR);
ExitProcess(0);
}
}

int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
{
// Block the user from starting if they launched the incorrect architecture version of the project.
// This should only be applicable to developer versions. The package installation process
// should choose and install the correct one from the bundle.
EnsureNativeArchitecture();

// Make sure to call this so we get WM_POINTER messages.
EnableMouseInPointer(true);

Expand Down
1 change: 1 addition & 0 deletions src/cascadia/WindowsTerminal/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ Module Name:
#include <winrt/Windows.ui.xaml.media.h>

#include <wil/resource.h>
#include <wil/win32_helpers.h>
15 changes: 11 additions & 4 deletions src/cascadia/WindowsTerminal/resource.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Cascadia.EXE.rc
// Used by WindowsTerminal.rc
//
#define IDI_APPICON 101
#define IDS_ERROR_DIALOG_TITLE 105
#define IDS_ERROR_ARCHITECTURE_FORMAT 110
#define IDS_X86_ARCHITECTURE 111
#define IDS_AMD64_ARCHITECTURE 112
#define IDS_ARM64_ARCHITECTURE 113
#define IDS_ARM_ARCHITECTURE 114
#define IDS_UNKNOWN_ARCHITECTURE 115

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

#define IDI_APPICON 101

0 comments on commit 60a444c

Please sign in to comment.