2019-05-03 00:29:04 +02:00
|
|
|
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Licensed under the MIT license.
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
- telemetry.hpp
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
- This module is used for recording all telemetry feedback from the console
|
|
|
|
|
|
|
|
Author(s):
|
|
|
|
- Evan Wirt (EvanWi) 09-Jul-2014
|
|
|
|
- Kourosh Mehrain (KMehrain) 09-Jul-2014
|
|
|
|
- Stephen Somuah (StSomuah) 09-Jul-2014
|
|
|
|
- Anup Manandhar (AnupM) 09-Jul-2014
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <TraceLoggingActivity.h>
|
|
|
|
|
|
|
|
class Telemetry
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// Implement this as a singleton class.
|
|
|
|
static Telemetry& Instance()
|
|
|
|
{
|
|
|
|
static Telemetry s_Instance;
|
|
|
|
return s_Instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetUserInteractive();
|
|
|
|
void SetWindowSizeChanged();
|
|
|
|
void SetContextMenuUsed();
|
|
|
|
void SetKeyboardTextSelectionUsed();
|
|
|
|
void SetKeyboardTextEditingUsed();
|
|
|
|
void SetCtrlPgUpPgDnUsed();
|
|
|
|
void LogCtrlShiftCProcUsed();
|
|
|
|
void LogCtrlShiftCRawUsed();
|
|
|
|
void LogCtrlShiftVProcUsed();
|
|
|
|
void LogCtrlShiftVRawUsed();
|
|
|
|
void LogQuickEditCopyProcUsed();
|
|
|
|
void LogQuickEditCopyRawUsed();
|
|
|
|
void LogQuickEditPasteProcUsed();
|
|
|
|
void LogQuickEditPasteRawUsed();
|
|
|
|
void LogColorSelectionUsed();
|
|
|
|
|
|
|
|
void LogFindDialogNextClicked(const unsigned int iStringLength, const bool fDirectionDown, const bool fMatchCase);
|
|
|
|
void LogProcessConnected(const HANDLE hProcess);
|
|
|
|
void FindDialogClosed();
|
|
|
|
void WriteFinalTraceLog();
|
|
|
|
|
|
|
|
void LogRipMessage(_In_z_ const char* pszMessage, ...) const;
|
|
|
|
|
|
|
|
// Names are from the external API call names. Note that some names can be different
|
|
|
|
// than the internal API calls.
|
|
|
|
// Don't worry about the following APIs, because they are external to our conhost codebase and hard to track through
|
|
|
|
// telemetry: GetStdHandle, SetConsoleCtrlHandler, SetStdHandle
|
|
|
|
// We can't differentiate between these apis, so just log the "-Ex" versions: GetConsoleScreenBufferInfo / GetConsoleScreenBufferInfoEx,
|
|
|
|
// GetCurrentConsoleFontEx / GetCurrentConsoleFont
|
|
|
|
enum ApiCall
|
|
|
|
{
|
|
|
|
AddConsoleAlias = 0,
|
|
|
|
AllocConsole,
|
|
|
|
AttachConsole,
|
|
|
|
CreateConsoleScreenBuffer,
|
|
|
|
FillConsoleOutputAttribute,
|
|
|
|
FillConsoleOutputCharacter,
|
|
|
|
FlushConsoleInputBuffer,
|
|
|
|
FreeConsole,
|
|
|
|
GenerateConsoleCtrlEvent,
|
|
|
|
GetConsoleAlias,
|
|
|
|
GetConsoleAliases,
|
|
|
|
GetConsoleAliasesLength,
|
|
|
|
GetConsoleAliasExes,
|
|
|
|
GetConsoleAliasExesLength,
|
|
|
|
GetConsoleCP,
|
|
|
|
GetConsoleCursorInfo,
|
|
|
|
GetConsoleDisplayMode,
|
|
|
|
GetConsoleFontSize,
|
|
|
|
GetConsoleHistoryInfo,
|
|
|
|
GetConsoleMode,
|
|
|
|
GetConsoleLangId,
|
|
|
|
GetConsoleOriginalTitle,
|
|
|
|
GetConsoleOutputCP,
|
|
|
|
GetConsoleProcessList,
|
|
|
|
GetConsoleScreenBufferInfoEx,
|
|
|
|
GetConsoleSelectionInfo,
|
|
|
|
GetConsoleTitle,
|
|
|
|
GetConsoleWindow,
|
|
|
|
GetCurrentConsoleFontEx,
|
|
|
|
GetLargestConsoleWindowSize,
|
|
|
|
GetNumberOfConsoleInputEvents,
|
|
|
|
GetNumberOfConsoleMouseButtons,
|
|
|
|
PeekConsoleInput,
|
|
|
|
ReadConsole,
|
|
|
|
ReadConsoleInput,
|
|
|
|
ReadConsoleOutput,
|
|
|
|
ReadConsoleOutputAttribute,
|
|
|
|
ReadConsoleOutputCharacter,
|
|
|
|
ScrollConsoleScreenBuffer,
|
|
|
|
SetConsoleActiveScreenBuffer,
|
|
|
|
SetConsoleCP,
|
|
|
|
SetConsoleCursorInfo,
|
|
|
|
SetConsoleCursorPosition,
|
|
|
|
SetConsoleDisplayMode,
|
|
|
|
SetConsoleHistoryInfo,
|
|
|
|
SetConsoleMode,
|
|
|
|
SetConsoleOutputCP,
|
|
|
|
SetConsoleScreenBufferInfoEx,
|
|
|
|
SetConsoleScreenBufferSize,
|
|
|
|
SetConsoleTextAttribute,
|
|
|
|
SetConsoleTitle,
|
|
|
|
SetConsoleWindowInfo,
|
|
|
|
SetCurrentConsoleFontEx,
|
|
|
|
WriteConsole,
|
|
|
|
WriteConsoleInput,
|
|
|
|
WriteConsoleOutput,
|
|
|
|
WriteConsoleOutputAttribute,
|
|
|
|
WriteConsoleOutputCharacter,
|
|
|
|
// Only use this last enum as a count of the number of api enums.
|
|
|
|
NUMBER_OF_APIS
|
|
|
|
};
|
|
|
|
void LogApiCall(const ApiCall api);
|
|
|
|
void LogApiCall(const ApiCall api, const BOOLEAN fUnicode);
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Used to prevent multiple instances
|
|
|
|
Telemetry();
|
|
|
|
~Telemetry();
|
|
|
|
Telemetry(Telemetry const&);
|
|
|
|
void operator=(Telemetry const&);
|
|
|
|
|
2019-06-11 22:27:09 +02:00
|
|
|
bool FindProcessName(const WCHAR* pszProcessName, _Out_ size_t* iPosition) const;
|
2019-05-03 00:29:04 +02:00
|
|
|
void TotalCodesForPreviousProcess();
|
|
|
|
|
|
|
|
static const int c_iMaxProcessesConnected = 100;
|
|
|
|
|
|
|
|
TraceLoggingActivity<g_hConhostV2EventTraceProvider> _activity;
|
|
|
|
|
|
|
|
float _fpFindStringLengthAverage;
|
|
|
|
float _fpDirectionDownAverage;
|
|
|
|
float _fpMatchCaseAverage;
|
|
|
|
unsigned int _uiFindNextClickedTotal;
|
|
|
|
unsigned int _uiColorSelectionUsed;
|
|
|
|
time_t _tStartedAt;
|
2019-06-11 22:27:09 +02:00
|
|
|
WCHAR const* const c_pwszBashExeName = L"bash.exe";
|
2019-05-03 00:29:04 +02:00
|
|
|
|
|
|
|
// The current recommendation is to keep telemetry events 4KB or less, so let's keep our array at less than 2KB (1000 * 2 bytes).
|
|
|
|
WCHAR _wchProcessFileNames[1000];
|
|
|
|
// Index into our specially packed string, where to insert the next string.
|
|
|
|
size_t _iProcessFileNamesNext;
|
|
|
|
// Index for the currently connected process.
|
|
|
|
size_t _iProcessConnectedCurrently;
|
|
|
|
// An array of indexes into the _wchProcessFileNames array, which point to the individual process names.
|
2020-02-10 21:40:01 +01:00
|
|
|
size_t _rgiProcessFileNameIndex[c_iMaxProcessesConnected];
|
2019-05-03 00:29:04 +02:00
|
|
|
// Number of times each process has connected to the console.
|
|
|
|
unsigned int _rguiProcessFileNamesCount[c_iMaxProcessesConnected];
|
|
|
|
// To speed up searching the Process Names, create an alphabetically sorted index.
|
|
|
|
size_t _rgiAlphabeticalIndex[c_iMaxProcessesConnected];
|
|
|
|
// Total of how many codes each process used
|
|
|
|
unsigned int _rguiProcessFileNamesCodesCount[c_iMaxProcessesConnected];
|
|
|
|
// Total of how many failed codes each process used
|
|
|
|
unsigned int _rguiProcessFileNamesFailedCodesCount[c_iMaxProcessesConnected];
|
|
|
|
// Total of how many failed codes each process used outside the valid range.
|
|
|
|
unsigned int _rguiProcessFileNamesFailedOutsideCodesCount[c_iMaxProcessesConnected];
|
|
|
|
unsigned int _rguiTimesApiUsed[NUMBER_OF_APIS];
|
|
|
|
// Most of this array will be empty, and is only used if an API has an ansi specific variant.
|
|
|
|
unsigned int _rguiTimesApiUsedAnsi[NUMBER_OF_APIS];
|
|
|
|
// Total number of file names we've added.
|
|
|
|
UINT16 _uiNumberProcessFileNames;
|
|
|
|
|
|
|
|
bool _fBashUsed;
|
|
|
|
bool _fKeyboardTextEditingUsed;
|
|
|
|
bool _fKeyboardTextSelectionUsed;
|
|
|
|
bool _fUserInteractiveForTelemetry;
|
|
|
|
bool _fCtrlPgUpPgDnUsed;
|
|
|
|
|
|
|
|
// Linux copy and paste keyboard shortcut telemetry
|
|
|
|
unsigned int _uiCtrlShiftCProcUsed;
|
|
|
|
unsigned int _uiCtrlShiftCRawUsed;
|
|
|
|
unsigned int _uiCtrlShiftVProcUsed;
|
|
|
|
unsigned int _uiCtrlShiftVRawUsed;
|
|
|
|
|
|
|
|
// Quick edit copy and paste usage telemetry
|
|
|
|
unsigned int _uiQuickEditCopyProcUsed;
|
|
|
|
unsigned int _uiQuickEditCopyRawUsed;
|
|
|
|
unsigned int _uiQuickEditPasteProcUsed;
|
|
|
|
unsigned int _uiQuickEditPasteRawUsed;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Log the RIPMSG through telemetry, and also through a normal OutputDebugStringW call.
|
|
|
|
// These are drop-in substitutes for the RIPMSG0-4 macros from \windows\Core\ntcon2\conhost\consrv.h
|
|
|
|
#define RIPMSG0(flags, msg) Telemetry::Instance().LogRipMessage(msg);
|
|
|
|
#define RIPMSG1(flags, msg, a) Telemetry::Instance().LogRipMessage(msg, a);
|
|
|
|
#define RIPMSG2(flags, msg, a, b) Telemetry::Instance().LogRipMessage(msg, a, b);
|
|
|
|
#define RIPMSG3(flags, msg, a, b, c) Telemetry::Instance().LogRipMessage(msg, a, b, c);
|
|
|
|
#define RIPMSG4(flags, msg, a, b, c, d) Telemetry::Instance().LogRipMessage(msg, a, b, c, d);
|