spiegel-keyman/windows/src/engine/keyman32/k32_dbg.cpp
2020-10-05 09:30:55 +11:00

321 lines
10 KiB
C++

/*
Name: K32_DBG
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 14 Sep 2006
Modified Date: 9 Aug 2015
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 14 Sep 2006 - mcdurdin - Rework internal debugging to use mailslot passing to Keyman
05 Dec 2006 - mcdurdin - Disable temporary file-based logging
15 Jan 2007 - mcdurdin - Use _FILELOG define
16 Jan 2009 - mcdurdin - Clearer logging of key messages
30 Jan 2009 - mcdurdin - I1835 - Improve performance of debugging
11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
07 Sep 2009 - mcdurdin - I2098 - Some debug messages lost in multithreaded apps
30 Nov 2009 - mcdurdin - I2157 - Deletion of buffer crash if LIBRARY_NAME has no version info
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
11 Dec 2009 - mcdurdin - I934 - identify x64 debugging
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
22 Mar 2010 - mcdurdin - I2248 - Crash in Keyman Engine outputting log information
29 Mar 2010 - mcdurdin - I2263 - Show thread and process info in debug log
19 Apr 2010 - mcdurdin - I2310 - system.log needs to be reformatted for simple import into database
04 May 2010 - mcdurdin - I2348 - Debug log needs some reworking
04 May 2010 - mcdurdin - I2349 - Pause key to send debug log event
04 May 2010 - mcdurdin - I2352 - Debug logging not reliable in some apps
04 May 2010 - mcdurdin - I2353 - Need to report Win32 failures more reliably
28 Jun 2010 - mcdurdin - I2445 - Try and reconnect debug pipe on error
31 Jan 2011 - mcdurdin - I2690 - Add ForegroundWindow info to debug log
12 May 2011 - mcdurdin - I2908 - Fix double strike issue - clear up logging
05 Nov 2012 - mcdurdin - I3547 - V9.0 Use _countof to tidyup code
17 Nov 2012 - mcdurdin - I3569 - V9.0 - Simplify debug logs by removing unused data
17 Nov 2012 - mcdurdin - I3570 - V9.0 - Output debug log to debug console
13 Dec 2012 - mcdurdin - I3656 - V9.0 - Debug logs show too many columns for host messages
07 Nov 2013 - mcdurdin - I3951 - V9.0 - Add debug-to-console hidden option for Keyman32
24 Apr 2014 - mcdurdin - I4196 - V9.0 - wm_kmmoreposting must be refactored for TIP work as it is not sequential
09 Aug 2015 - mcdurdin - I4843 - Log reported modifier state as well as Keyman current modifier state
*/
#include "pch.h"
#include <stdio.h>
#include <stdarg.h>
#include <evntprov.h>
//#define _FILELOG
#ifdef _FILELOG
//FILE *fp = NULL;
#endif
// {DA621615-E08B-4283-918E-D2502D3757AE}
static const GUID guid_EtwProviderId =
{ 0xda621615, 0xe08b, 0x4283, { 0x91, 0x8e, 0xd2, 0x50, 0x2d, 0x37, 0x57, 0xae } };
enum {NO_DEBUG_WINDOWS=100, UNABLE_TO_CREATE_FILE_MAPPING, UNABLE_TO_MAP_VIEW_OF_FILE};
extern void GetWindowsVersion(char *buf);
void InitDebuggingEx(PKEYMAN64THREADDATA _td) {
if(Globals::get_debug_KeymanLog()) {
DWORD dwErr = EventRegister(&guid_EtwProviderId, NULL, NULL, &_td->etwRegHandle);
if (dwErr != ERROR_SUCCESS) {
OutputDebugString("Keyman k32_dbg: Failed to EventRegister");//TODO: Build a helper function with GLE?
}
}
}
void InitDebugging() {
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
InitDebuggingEx(_td);
_td->debug_DebugInit = TRUE;
if(Globals::get_debug_KeymanLog())
{
VS_FIXEDFILEINFO *ffi;
DWORD sz;
UINT ffilen;
char *buf = new char[1024], fname[260];
GetWindowsVersion(buf);
SendDebugMessage(0, sdmKeyboard, 0, buf);
delete buf;
GetModuleFileName(GetModuleHandle(LIBRARY_NAME), fname, 260);
sz = GetFileVersionInfoSize(fname, 0);
if(sz > 0)
{
buf = new char[sz];
GetFileVersionInfo(fname, 0, sz, buf);
VerQueryValue(buf, "\\", (void **) &ffi, &ffilen);
SendDebugMessageFormat(0, sdmKeyboard, 0, "Keyman version: %d.%d.%d.%d",
HIWORD(ffi->dwProductVersionMS), LOWORD(ffi->dwProductVersionMS),
HIWORD(ffi->dwProductVersionLS), LOWORD(ffi->dwProductVersionLS));
delete buf; // I2157
}
else
SendDebugMessage(0, sdmKeyboard, 0, "Keyman version: damaged");
}
}
void UninitDebuggingEx()
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
if (_td->etwRegHandle != NULL) {
EventUnregister(_td->etwRegHandle);
_td->etwRegHandle = NULL;
}
_td->debug_DebugInit = FALSE;
}
void UninitDebugging() {
SendDebugMessage(0, sdmGlobal, 0, "--- UninitDebugging() - shutting down ---");
}
const TSDMState DebugState[] = {sdmInternat, sdmAIDefault, sdmMessage, sdmKeyboard, sdmGlobal, sdmMenu, sdmDebug, sdmLoad, sdmOther};
BOOL ShouldDebug_1() {
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
if (!_td->debug_DebugInit) InitDebuggingEx(_td);
_td->debug_DebugInit = TRUE;
return Globals::get_debug_KeymanLog();
}
int SendDebugMessageFormat_1(HWND hwnd, TSDMState state, int kmn_lineno, char *file, int line, char *fmt, ...)
{
char fmtbuf[256];
va_list vars;
va_start(vars, fmt);
vsnprintf_s(fmtbuf, _countof(fmtbuf), _TRUNCATE, fmt, vars); // I2248 // I3547
fmtbuf[255] = 0;
SendDebugMessage_1(hwnd, state, kmn_lineno, file, line, fmtbuf);
return 0;
}
/*void FillWindowInfo(HWND hwnd, char *sClassName, char *sWindowText)
{
if(hwnd == 0 || !GetClassName(hwnd, sClassName, 32))
sClassName[0] = 0;
else
sClassName[31] = 0;
WCHAR wsWindowText[32];
if(hwnd == 0 || !InternalGetWindowText(hwnd, wsWindowText, 32))
sWindowText[0] = 0;
else
{
WideCharToMultiByte(CP_ACP, 0, wsWindowText, -1, sWindowText, 32, NULL, NULL);
sWindowText[31] = 0;
}
}*/
int SendDebugMessage_1(HWND hwnd, TSDMState state, int kmn_lineno, char *file, int line, char *msg)
{
UNREFERENCED_PARAMETER(hwnd);
UNREFERENCED_PARAMETER(state); // I3569
UNREFERENCED_PARAMETER(kmn_lineno);
// TODO: convert debugging to Unicode
PWSTR msgW = strtowstr(msg);
Keyman_WriteDebugEvent(file, line, msgW);
delete msgW;
return 0;
}
const
char *msgnames[] = {
"WM_KEYDOWN",
"WM_KEYUP",
"WM_CHAR",
"WM_DEADCHAR",
"WM_SYSKEYDOWN",
"WM_SYSKEYUP",
"WM_SYSCHAR",
"WM_SYSDEADCHAR",
"WM_x108",
"WM_UNICHAR"
};
void DebugMessage(LPMSG msg, WPARAM wParam) // I2908
{
char ds[256];
if(msg->message == wm_keymankeydown)
wsprintf(ds, "DebugMessage(%x, wm_keymankeydown: %s lParam: %X) [message flags: %x time: %d]", PtrToInt(msg->hwnd),
Debug_VirtualKey((WORD) msg->wParam), (unsigned int) msg->lParam, wParam, (int) msg->time);
else if(msg->message == wm_keymankeyup)
wsprintf(ds, "DebugMessage(%x, wm_keymankeyup: %s lParam: %X) [message flags: %x time: %d]", PtrToInt(msg->hwnd),
Debug_VirtualKey((WORD) msg->wParam), (unsigned int) msg->lParam, wParam, (int) msg->time);
else if (msg->message == wm_keyman_keyevent)
wsprintf(ds, "DebugMessage(%x, wm_keyman_keyevent: %s lParam: %X) [message flags: %x time: %d]", PtrToInt(msg->hwnd),
Debug_VirtualKey((WORD)msg->wParam), (unsigned int) msg->lParam, wParam, (int) msg->time);
else if(msg->message == WM_KEYDOWN || msg->message == WM_KEYUP || msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSKEYUP)
wsprintf(ds, "DebugMessage(%x, %s, wParam: %s, lParam: %X) [message flags: %x time: %d extra: %x]",
PtrToInt(msg->hwnd),
msgnames[msg->message-WM_KEYDOWN],
Debug_VirtualKey((WORD) msg->wParam),
(unsigned int) msg->lParam,
wParam,
(int) msg->time,
(unsigned int) GetMessageExtraInfo());
else if(msg->message >= WM_KEYDOWN && msg->message <= WM_UNICHAR)
wsprintf(ds, "DebugMessage(%x, %s, wParam: '%c' (U+%04X), lParam: %X) [message flags: %x time: %d extra: %x]",
PtrToInt(msg->hwnd),
msgnames[msg->message-WM_KEYDOWN],
msg->wParam,
msg->wParam,
(unsigned int) msg->lParam,
wParam,
(int) msg->time,
(unsigned int) GetMessageExtraInfo());
else
wsprintf(ds, "%x: %d: wParam: %d, lParam: %X [message flags: %x time: %d]", PtrToInt(msg->hwnd), msg->message, msg->wParam, (unsigned int) msg->lParam, wParam, (int) msg->time);
SendDebugMessage(msg->hwnd, sdmMessage, 0, ds);
}
void DebugShift(char *function, char *point)
{
BYTE kbd[256];
GetKeyboardState(kbd);
SendDebugMessageFormat(0, sdmKeyboard, 0, "%s - %s Alt: [%x] %x %x Ctrl: [%x] %x %x Shift: %x",
function, point,
kbd[VK_MENU],
kbd[VK_LMENU],
kbd[VK_RMENU],
kbd[VK_CONTROL],
kbd[VK_LCONTROL],
kbd[VK_RCONTROL],
kbd[VK_SHIFT]);
}
BOOL DebugSignalPause(BOOL fIsUp)
{
if(ShouldDebug(sdmDebug))
{
if(fIsUp)
{
SendDebugMessage_1(NULL, sdmDebug, -1, NULL, 0, NULL); // Signals an event to the controller
}
return TRUE;
}
return FALSE;
}
void DebugLastError_1(DWORD err, char *context, char *file, int line, char *func)
{
if(ShouldDebug(sdmDebug))
{
char msg[256];
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, err, 0, msg, sizeof(msg), NULL) == 0) msg[0] = 0;
for (char *p = msg; *p; p++) {
if (*p == '\r' || *p == '\n') *p = ' ';
}
SendDebugMessageFormat_1(NULL, sdmDebug, 0, file, line, "ERROR %d in %s calling %s: %s", err, func, context, msg);
}
}
char *Debug_VirtualKey(WORD vk) {
__declspec(thread) static char buf[256];
if (!ShouldDebug(sdmDebug)) {
return "";
}
if (vk < 256) {
wsprintf(buf, "['%s' 0x%x]", KeyNames[vk], vk);
}
else {
wsprintf(buf, "[0x%x]", vk);
}
return buf;
}
char *Debug_UnicodeString(PWSTR s, int x) {
if (!ShouldDebug(sdmDebug)) {
return "";
}
__declspec(thread) static char bufout[2][128 * 7];
WCHAR *p;
char *q;
for (p = s, q = bufout[x]; *p && (p - s < 128); p++)
{
wsprintf(q, "U+%4.4X ", *p); q = strchr(q, 0);
}
//WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL);
return bufout[x];
}
#ifdef _DEBUG
void _OutputThreadDebugString(char *s) {
char buf[256];
sprintf_s(buf, "[%d]: %s\n", GetCurrentThreadId(), s);
OutputDebugString(buf);
}
#endif
void WINAPI Keyman_Diagnostic(int mode) {
if (mode == 0) {
RaiseException(0xDEADBEEF, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
}