198 lines
7.4 KiB
C++
198 lines
7.4 KiB
C++
|
/*++
|
||
|
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&);
|
||
|
|
||
|
bool FindProcessName(const WCHAR* pszProcessName, _Out_ size_t *iPosition) const;
|
||
|
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;
|
||
|
WCHAR const * const c_pwszBashExeName = L"bash.exe";
|
||
|
|
||
|
// 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.
|
||
|
size_t _rgiProccessFileNameIndex[c_iMaxProcessesConnected];
|
||
|
// 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);
|