[Windows] Refactor Windows debug logging to use Event Tracing for Windows

This commit is contained in:
Marc Durdin 2018-10-16 10:23:54 +11:00
parent 94447d462e
commit b3b5c244ea
44 changed files with 794 additions and 1214 deletions

View file

@ -35,7 +35,6 @@ uses
CRC32 in '..\..\global\delphi\general\CRC32.pas',
KeyNames in '..\..\global\delphi\general\KeyNames.pas',
wininet5 in '..\..\global\delphi\general\wininet5.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
GlobalProxySettings in '..\..\global\delphi\general\GlobalProxySettings.pas',
ErrorControlledRegistry in '..\..\global\delphi\vcl\ErrorControlledRegistry.pas',
utilexecute in '..\..\global\delphi\general\utilexecute.pas',

View file

@ -122,7 +122,6 @@
<DCCReference Include="..\..\global\delphi\general\CRC32.pas"/>
<DCCReference Include="..\..\global\delphi\general\KeyNames.pas"/>
<DCCReference Include="..\..\global\delphi\general\wininet5.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\general\GlobalProxySettings.pas"/>
<DCCReference Include="..\..\global\delphi\vcl\ErrorControlledRegistry.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilexecute.pas"/>

View file

@ -7,7 +7,6 @@ uses
klog in '..\..\global\delphi\general\klog.pas',
utilfiletypes in '..\..\global\delphi\general\utilfiletypes.pas',
RegistryKeys in '..\..\global\delphi\general\RegistryKeys.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
GetOsVersion in '..\..\global\delphi\general\GetOsVersion.pas',
VersionInfo in '..\..\global\delphi\general\VersionInfo.pas',
ErrorControlledRegistry in '..\..\global\delphi\vcl\ErrorControlledRegistry.pas',

View file

@ -7,7 +7,7 @@
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Console</AppType>
<FrameworkType>None</FrameworkType>
<ProjectVersion>18.2</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@ -90,7 +90,6 @@
<DCCReference Include="..\..\global\delphi\general\klog.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilfiletypes.pas"/>
<DCCReference Include="..\..\global\delphi\general\RegistryKeys.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\general\GetOsVersion.pas"/>
<DCCReference Include="..\..\global\delphi\general\VersionInfo.pas"/>
<DCCReference Include="..\..\global\delphi\vcl\ErrorControlledRegistry.pas"/>

View file

@ -47,7 +47,6 @@ uses
utilxml in '..\..\global\delphi\general\utilxml.pas',
UfrmInstallKeyboardFromWeb in 'install\UfrmInstallKeyboardFromWeb.pas' {frmInstallKeyboardFromWeb},
UfrmWebContainer in '..\..\global\delphi\ui\UfrmWebContainer.pas' {frmWebContainer},
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
MessageIdentifierConsts in '..\..\global\delphi\cust\MessageIdentifierConsts.pas',
UfrmDownloadProgress in 'util\UfrmDownloadProgress.pas' {frmDownloadProgress},
kmcomapi_errors in '..\..\global\delphi\general\kmcomapi_errors.pas',

View file

@ -163,7 +163,6 @@
<DCCReference Include="..\..\global\delphi\ui\UfrmWebContainer.pas">
<Form>frmWebContainer</Form>
</DCCReference>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\cust\MessageIdentifierConsts.pas"/>
<DCCReference Include="util\UfrmDownloadProgress.pas">
<Form>frmDownloadProgress</Form>
@ -391,18 +390,18 @@
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Profiling\AQtimeModule1.aqt" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="kmshell.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>kmshell.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Profiling\AQtimeModule1.aqt" Configuration="Debug" Class="ProjectFile">
<Platform Name="Win32">
<RemoteDir>.\</RemoteDir>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="OSX32">
<Operation>1</Operation>

View file

@ -11,7 +11,6 @@ uses
Upload_Settings in '..\..\global\delphi\general\Upload_Settings.pas',
DebugPaths in '..\..\global\delphi\general\DebugPaths.pas',
GetOsVersion in '..\..\global\delphi\general\GetOsVersion.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
TntDialogHelp in 'TntDialogHelp.pas',
httpuploader_messageprocessor_windows in 'httpuploader_messageprocessor_windows.pas',
SetupForm in 'SetupForm.pas',

View file

@ -104,7 +104,6 @@
<DCCReference Include="..\..\global\delphi\general\Upload_Settings.pas"/>
<DCCReference Include="..\..\global\delphi\general\DebugPaths.pas"/>
<DCCReference Include="..\..\global\delphi\general\GetOsVersion.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="TntDialogHelp.pas"/>
<DCCReference Include="httpuploader_messageprocessor_windows.pas"/>
<DCCReference Include="SetupForm.pas"/>

View file

@ -146,11 +146,9 @@ uses
UfrmDebugStatus in 'child\UfrmDebugStatus.pas' {frmDebugStatus},
UfrmDebugStatus_Key in 'debug\UfrmDebugStatus_Key.pas' {frmDebugStatus_Key},
UfrmDebugStatus_Child in 'debug\UfrmDebugStatus_Child.pas' {frmDebugStatus_Child},
DebugManager in '..\..\global\delphi\debug\DebugManager.pas',
OnlineUpdateCheck in '..\..\global\delphi\online\OnlineUpdateCheck.pas',
UfrmOnlineUpdateNewVersion in '..\..\global\delphi\online\UfrmOnlineUpdateNewVersion.pas' {frmOnlineUpdateNewVersion},
DebugPaths in '..\..\global\delphi\general\DebugPaths.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
MessageDefaults in 'kct\MessageDefaults.pas',
UfrmDownloadProgress in 'main\UfrmDownloadProgress.pas' {frmDownloadProgress},
UframeOnScreenKeyboardEditor in 'main\UframeOnScreenKeyboardEditor.pas' {frameOnScreenKeyboardEditor},

View file

@ -313,13 +313,11 @@
<DCCReference Include="debug\UfrmDebugStatus_Child.pas">
<Form>frmDebugStatus_Child</Form>
</DCCReference>
<DCCReference Include="..\..\global\delphi\debug\DebugManager.pas"/>
<DCCReference Include="..\..\global\delphi\online\OnlineUpdateCheck.pas"/>
<DCCReference Include="..\..\global\delphi\online\UfrmOnlineUpdateNewVersion.pas">
<Form>frmOnlineUpdateNewVersion</Form>
</DCCReference>
<DCCReference Include="..\..\global\delphi\general\DebugPaths.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="kct\MessageDefaults.pas"/>
<DCCReference Include="main\UfrmDownloadProgress.pas">
<Form>frmDownloadProgress</Form>

View file

@ -414,7 +414,6 @@ uses
Keyman.Developer.System.CEFManager,
CharMapDropTool,
DebugManager,
HTMLHelpViewer,
KLog,
keymanapi_TLB,
@ -530,15 +529,6 @@ begin
frmHelp := TfrmHelp.Create(Application);
KL.Log('GetDebugManager start');
try
GetDebugManager(Handle);
except
on E:Exception do
KL.LogError('GetDebugManager failed: '+E.Message);
end;
KL.Log('GetDebugManager finish');
Application.OnActivate := AppOnActivate;
LoadDockLayout;

View file

@ -31,7 +31,6 @@ uses
utilkeyboard in '..\..\global\delphi\general\utilkeyboard.pas',
unicode in '..\..\global\delphi\general\unicode.pas',
utilhttp in '..\..\global\delphi\general\utilhttp.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
GetOsVersion in '..\..\global\delphi\general\GetOsVersion.pas',
UfrmTike in '..\TIKE\main\UfrmTike.pas' {TikeForm: TTntForm},
CompilePackageInstaller in '..\..\global\delphi\general\CompilePackageInstaller.pas',

View file

@ -130,7 +130,6 @@
<DCCReference Include="..\..\global\delphi\general\utilkeyboard.pas"/>
<DCCReference Include="..\..\global\delphi\general\unicode.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilhttp.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\general\GetOsVersion.pas"/>
<DCCReference Include="..\TIKE\main\UfrmTike.pas">
<Form>TikeForm</Form>

View file

@ -12,7 +12,6 @@ uses
Upload_Settings in '..\..\global\delphi\general\Upload_Settings.pas',
DebugPaths in '..\..\global\delphi\general\DebugPaths.pas',
GetOsVersion in '..\..\global\delphi\general\GetOsVersion.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
TntDialogHelp in 'TntDialogHelp.pas',
httpuploader_messageprocessor_windows in 'httpuploader_messageprocessor_windows.pas',
SetupForm in 'SetupForm.pas',

View file

@ -93,7 +93,6 @@
<DCCReference Include="..\..\global\delphi\general\Upload_Settings.pas"/>
<DCCReference Include="..\..\global\delphi\general\DebugPaths.pas"/>
<DCCReference Include="..\..\global\delphi\general\GetOsVersion.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="TntDialogHelp.pas"/>
<DCCReference Include="httpuploader_messageprocessor_windows.pas"/>
<DCCReference Include="SetupForm.pas"/>

10
windows/src/engine/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
keyman32/MSG00001.bin
keyman32/keyman-debug-etw.h
keyman32/keyman-debug-etw.rc
keyman32/keyman-debug-etw.res
keyman32/keyman-debug-etwTEMP.BIN
keyman64/MSG00001.bin
keyman64/keyman-debug-etw.h
keyman64/keyman-debug-etw.rc
keyman64/keyman-debug-etw.res
keyman64/keyman-debug-etwTEMP.BIN

View file

@ -20,7 +20,6 @@ uses
CRC32 in '..\..\..\global\delphi\general\CRC32.pas',
VersionInfo in '..\..\..\global\delphi\general\VersionInfo.pas',
GetOsVersion in '..\..\..\global\delphi\general\GetOsVersion.pas',
SystemDebugPath in '..\..\..\global\delphi\general\SystemDebugPath.pas',
OnlineConstants in '..\..\..\global\delphi\productactivation\OnlineConstants.pas',
ErrorControlledRegistry in '..\..\..\global\delphi\vcl\ErrorControlledRegistry.pas',
Unicode in '..\..\..\global\delphi\general\Unicode.pas',

View file

@ -7,7 +7,7 @@
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Library</AppType>
<FrameworkType>None</FrameworkType>
<ProjectVersion>18.1</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@ -74,7 +74,7 @@
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_Namespace>Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<Icon_MainIcon>insthelper_Icon.ico</Icon_MainIcon>
@ -86,7 +86,7 @@
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
@ -94,7 +94,7 @@
<DCC_Optimize>false</DCC_Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<VerInfo_Keys>CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Keys>CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName)</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
</PropertyGroup>
<ItemGroup>
@ -106,7 +106,6 @@
<DCCReference Include="..\..\..\global\delphi\general\CRC32.pas"/>
<DCCReference Include="..\..\..\global\delphi\general\VersionInfo.pas"/>
<DCCReference Include="..\..\..\global\delphi\general\GetOsVersion.pas"/>
<DCCReference Include="..\..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\..\global\delphi\productactivation\OnlineConstants.pas"/>
<DCCReference Include="..\..\..\global\delphi\vcl\ErrorControlledRegistry.pas"/>
<DCCReference Include="..\..\..\global\delphi\general\Unicode.pas"/>
@ -175,6 +174,7 @@
</Excluded_Packages>
</Delphi.Personality>
<Platforms>
<Platform value="Linux64">False</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">False</Platform>
</Platforms>

View file

@ -30,7 +30,7 @@ type
implementation
uses
DebugManager,
Keyman.System.DebugLogClient,
UfrmKeyman7Main;
const
@ -78,7 +78,7 @@ begin
// ATOM construction copied from TLangSwitchKeyboard
s := IntToStr(TIP.Profile.langid) + '|' + GUIDToString(TGUID(TIP.Profile.clsid)) + '|' + GUIDToString(TGUID(TIP.Profile.guidProfile));
TDebugManager.WriteMessage('TGlobalKeyboardChangeManager.PostChange: '+s, []);
TDebugLogClient.Instance.WriteMessage('TGlobalKeyboardChangeManager.PostChange: '+s, []);
if s <> FLastKeyboard then
begin
@ -92,7 +92,7 @@ begin
WinKB := Keyboard as TLangSwitchKeyboard_WinKeyboard;
s := IntToStr(WinKB.HKL);
TDebugManager.WriteMessage('TGlobalKeyboardChangeManager.PostChange: '+s, []);
TDebugLogClient.Instance.WriteMessage('TGlobalKeyboardChangeManager.PostChange: '+s, []);
if s <> FLastKeyboard then
begin

View file

@ -1,80 +0,0 @@
object frmDebugNotify: TfrmDebugNotify
Left = 0
Top = 0
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = 'Keyman Debug Notification'
ClientHeight = 321
ClientWidth = 553
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsStayOnTop
OldCreateOrder = False
Position = poScreenCenter
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object lblNotes: TLabel
Left = 12
Top = 17
Width = 240
Height = 13
Caption = 'Note &details about this issue to store in the log file'
FocusControl = memoNotes
end
object lblLogFileName: TLabel
Left = 12
Top = 259
Width = 67
Height = 13
Caption = '&Log file name:'
FocusControl = editLogFileName
end
object memoNotes: TMemo
Left = 12
Top = 36
Width = 529
Height = 209
TabOrder = 0
end
object editLogFileName: TEdit
Left = 92
Top = 256
Width = 449
Height = 21
TabStop = False
ParentColor = True
ReadOnly = True
TabOrder = 1
end
object chkNotepad: TCheckBox
Left = 92
Top = 288
Width = 133
Height = 17
Caption = 'Open log file in &Notepad'
TabOrder = 2
end
object cmdOK: TButton
Left = 472
Top = 283
Width = 73
Height = 25
Caption = 'OK'
Default = True
TabOrder = 4
OnClick = cmdOKClick
end
object chkClipboard: TCheckBox
Left = 244
Top = 288
Width = 145
Height = 17
Caption = '&Copy file to clipboard'
TabOrder = 3
end
end

View file

@ -1,181 +0,0 @@
(*
Name: UfrmDebugNotify
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 4 May 2010
Modified Date: 8 Jun 2012
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 04 May 2010 - mcdurdin - I2348 - Rework of debug log
04 May 2010 - mcdurdin - I2349 - Debug log capture hotkey
08 Jun 2012 - mcdurdin - I3349 - V9.0 - Consolidate all process creation into TUtilExecute
*)
unit UfrmDebugNotify;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, UserMessages;
type
TfrmDebugNotify = class(TForm)
memoNotes: TMemo;
lblNotes: TLabel;
editLogFileName: TEdit;
chkNotepad: TCheckBox;
cmdOK: TButton;
lblLogFileName: TLabel;
chkClipboard: TCheckBox;
procedure FormShow(Sender: TObject);
procedure cmdOKClick(Sender: TObject);
private
FLogFileHandle: THandle;
FLogFileIndex: Integer;
procedure SetLogFileIndex(const Value: Integer);
procedure WMUserFormShown(var Message: TMessage); message WM_USER_FormShown;
procedure SetClipboardToFilename(const Filename: string);
{ Private declarations }
public
{ Public declarations }
property LogFileHandle: THandle read FLogFileHandle write FLogFileHandle;
property LogFileIndex: Integer read FLogFileIndex write SetLogFileIndex;
end;
implementation
uses
Clipbrd,
DebugManager,
ShellApi,
ShlObj,
utilexecute;
{$R *.dfm}
{ TfrmDebugNotify }
////////////////////////////////////////////////////////////////
// copies filenames from "Filenames" to the clipboard.
// "Filenames" can contain file- and directory names.
function Sto_CopyFilenamesToClipboard(Filenames: TStrings): Boolean;
var
sFilenames: String;
iIndex: Integer;
hBuffer: HGLOBAL;
pBuffer: PDropFiles;
begin
// check entry conditions
Result := (Filenames <> nil) and (Filenames.Count > 0);
if (not Result) then Exit;
// bring the filenames in a form,
// separated by #0 and ending with a double #0#0
sFilenames := '';
for iIndex := 0 to Filenames.Count - 1 do
sFilenames := sFilenames +
ExcludeTrailingPathDelimiter(Filenames.Strings[iIndex]) + #0;
sFilenames := sFilenames + #0;
// allocate memory with the size of the "DropFiles" structure plus the
// length of the filename buffer.
hBuffer := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT,
SizeOf(DROPFILES) + Length(sFilenames));
try
Result := (hBuffer <> 0);
if (Result) then
begin
pBuffer := GlobalLock(hBuffer);
try
// prepare the "DROPFILES" structure
pBuffer^.pFiles := SizeOf(DROPFILES);
// behind the "DROPFILES" structure we place the filenames
pBuffer := Pointer(Integer(pBuffer) + SizeOf(DROPFILES));
CopyMemory(pBuffer, PChar(sFilenames), Length(sFilenames));
finally
GlobalUnlock(hBuffer);
end;
// copy buffer to the clipboard
Clipboard.Open;
try
Clipboard.SetAsHandle(CF_HDROP, hBuffer);
finally
Clipboard.Close;
end;
end;
except
Result := False;
// free only if handle could not be passed to the clipboard
GlobalFree(hBuffer);
end;
end;
procedure TfrmDebugNotify.SetClipboardToFilename(const Filename: string);
var
s: TStrings;
begin
s := TSTringList.Create;
try
s.Add(Filename);
Sto_CopyFilenamesToClipboard(s);
finally
s.Free;
end;
end;
type
TDebugManagerEx = class(TDebugManager)
end;
procedure TfrmDebugNotify.cmdOKClick(Sender: TObject);
begin
TDebugManagerEx.WriteString(FLogFileHandle, memoNotes.Text);
{
buf := PChar(memoNotes.Text);
buflen := Length(buf);
WriteFile(FLogFileHandle, PChar(buf)^, buflen, n, nil);
WriteFile(FLogFileHandle, #13#10, 2, n, nil);
}
TDebugManagerEx.CloseLogFile(FLogFileHandle);
if chkNotepad.Checked then
if not TUtilExecute.Shell(Handle, editLogFileName.Text, GetCurrentDir) then // I3349
ShowMessage(SysErrorMessage(GetLastError));
if chkClipboard.Checked then
SetClipboardToFilename(editLogFileName.Text);
ModalResult := mrOk;
end;
procedure TfrmDebugNotify.FormShow(Sender: TObject);
begin
PostMessage(Handle, WM_USER_FormShown, 0, 0);
end;
procedure TfrmDebugNotify.SetLogFileIndex(const Value: Integer);
begin
FLogFileIndex := Value;
editLogFileName.Text := TDebugManager.DebugLogFileName(Value);
end;
procedure TfrmDebugNotify.WMUserFormShown(var Message: TMessage);
var
FThreadID: DWord;
begin
FThreadID := GetWindowThreadProcessId(GetForegroundWindow);
if FThreadID <> GetCurrentThreadId then
AttachThreadInput(GetCurrentThreadId, FThreadID, True);
BringToFront;
SetFocus;
if FThreadID <> GetCurrentThreadId then
AttachThreadInput(GetCurrentThreadId, FThreadID, False);
end;
end.

View file

@ -148,6 +148,9 @@ uses
Vcl.StdCtrls,
Vcl.ImgList,
Keyman.System.DebugLogClient,
Keyman.System.DebugLogManager,
keymanapi_TLB,
//TOUCH UfrmTouchKeyboard,
GlobalKeyboardChangeManager,
@ -155,7 +158,6 @@ uses
KeymanTrayIcon,
KeymanMenuItem,
custinterfaces,
DebugManager,
Menu_KeyboardItems,
UserMessages,
UfrmKeymanMenu,
@ -240,7 +242,6 @@ type
procedure WMUserParameterPass(var Message: TMessage); message WM_USER_ParameterPass;
procedure WMUserSendFontChange(var Message: TMessage); message WM_USER_SendFontChange;
procedure WMUserPlatformComms(var Message: TMessage); message WM_USER_PlatformComms;
procedure WMUserDebugNotify(var Message: TMessage); message WM_USER_DebugNotify;
procedure WMUserVisualKeyboardClosed(var Message: TMessage); message WM_USER_VisualKeyboardClosed; // I4243
procedure SetTrayIcon(rp: TRunningProduct; kbd: IKeymanKeyboardInstalled);
procedure TrayIconMouseUp(Sender: TObject; Button: TMouseButton;
@ -378,7 +379,6 @@ uses
UfrmHelp,
UILanguages,
UfrmOSKCharacterMap,
UfrmDebugNotify,
utilstr,
utilwow64,
KeymanEngineControl,
@ -715,7 +715,7 @@ begin
end
else if Message.Msg = wm_keyman_globalswitch then
begin
TDebugManager.WriteMessage('wm_keyman_globalswitch for Application Handle: %x %x', [Message.wParam, Message.lParam]);
TDebugLogClient.Instance.WriteMessage('wm_keyman_globalswitch for Application Handle: %x %x', [Message.wParam, Message.lParam]);
case Message.wParam of
skHKL, // A windows language has been selected so select the most appropriate Keyman keyboard
@ -733,9 +733,9 @@ begin
Exit;
end;
TDebugManager.WriteMessage('wm_keyman_control for Application Handle: %x %x', [Message.wParam, Message.lParam]);
TDebugLogClient.Instance.WriteMessage('wm_keyman_control for Application Handle: %x %x', [Message.wParam, Message.lParam]);
Message.Result := ProcessWMKeymanControl(LoWord(Message.WParam), HiWord(Message.WParam), Message.LParam); // I3961
TDebugManager.WriteMessage('wm_keyman_control-exit for Application Handle: %x %x -> %x', [Message.wParam, Message.lParam, Message.Result]); // I3961
TDebugLogClient.Instance.WriteMessage('wm_keyman_control-exit for Application Handle: %x %x -> %x', [Message.wParam, Message.lParam, Message.Result]); // I3961
end
else
Result := False;
@ -748,21 +748,21 @@ begin
gti.cbSize := SizeOf(gti);
if not GetGUIThreadInfo(0, gti) then
begin
TDebugManager.WriteLastError('UpdateFocusInfo', 'GetGUIThreadInfo');
TDebugLogClient.Instance.WriteLastError('UpdateFocusInfo', 'GetGUIThreadInfo');
Exit;
end;
TDebugManager.WriteMessage('UpdateFocusInfo: last focus=%x last active=%x', [FLastFocus, FLastActive]);
TDebugManager.WriteMessage('UpdateFocusInfo: new focus=%x new active=%x', [gti.hwndFocus, gti.hwndActive]);
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: last focus=%x last active=%x', [FLastFocus, FLastActive]);
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: new focus=%x new active=%x', [gti.hwndFocus, gti.hwndActive]);
if IsControllerWindow(gti.hwndFocus) then // I4731
TDebugManager.WriteMessage('UpdateFocusInfo: new focus is controller window, not updating', [])
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: new focus is controller window, not updating', [])
else if IsSysTrayWindow(gti.hwndFocus) then // I4731
TDebugManager.WriteMessage('UpdateFocusInfo: new focus is systray window, not updating', [])
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: new focus is systray window, not updating', [])
else if IsControllerWindow(gti.hwndActive) then // I4731
TDebugManager.WriteMessage('UpdateFocusInfo: new active is controller window, not updating', [])
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: new active is controller window, not updating', [])
else if IsSysTrayWindow(gti.hwndActive) then // I4731
TDebugManager.WriteMessage('UpdateFocusInfo: new active is systray window, not updating', [])
TDebugLogClient.Instance.WriteMessage('UpdateFocusInfo: new active is systray window, not updating', [])
else
begin
FLastFocus := gti.hwndFocus;
@ -928,14 +928,14 @@ begin
if Assigned(kbd) then
begin
case kbd.ItemType of
lsitWinKeyboard: TDebugManager.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = lsitWinKeyboard, value = %x', [(kbd as TLangSwitchKeyboard_WinKeyboard).HKL]);
lsitTIP: TDebugManager.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = lsitTIP, value = %s', [(kbd as TLangSwitchKeyboard_TIP).Caption]);
else TDebugManager.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = somthing else', []);
lsitWinKeyboard: TDebugLogClient.Instance.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = lsitWinKeyboard, value = %x', [(kbd as TLangSwitchKeyboard_WinKeyboard).HKL]);
lsitTIP: TDebugLogClient.Instance.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = lsitTIP, value = %s', [(kbd as TLangSwitchKeyboard_TIP).Caption]);
else TDebugLogClient.Instance.WriteMessage('LanguageSwitchFormHidden: kbd assigned, type = somthing else', []);
end;
kbd.Activate(hwnd);
end
else
TDebugManager.WriteMessage('LanguageSwitchFormHidden: kbd NOT assigned',[]);
TDebugLogClient.Instance.WriteMessage('LanguageSwitchFormHidden: kbd NOT assigned',[]);
end;
procedure TfrmKeyman7Main.ShowMenu(Sender: TObject; Location: TCustomisationMenuItemLocation; NearTray: Boolean; IconRect: TRect); // I3990 // I3991
@ -1155,18 +1155,6 @@ begin
end;
end;
procedure TfrmKeyman7Main.WMUserDebugNotify(var Message: TMessage);
begin
with TfrmDebugNotify.Create(Self) do
try
LogFileHandle := Message.LParam;
LogFileIndex := Message.WParam;
ShowModal;
finally
Free;
end;
end;
procedure TfrmKeyman7Main.WMUserSendFontChange(var Message: TMessage);
begin
PostMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
@ -1377,7 +1365,7 @@ procedure TfrmKeyman7Main.ActivateKeyboard(Keyboard: TLangSwitchKeyboard); //
var
hwnd: THandle;
begin
TDebugManager.WriteMessage('ActivateKeyboard: LastFocus=%x LastActive=%x Keyboard=%s KeymanID=%d', [FLastFocus, FLastActive, Keyboard.Caption, Keyboard.KeymanID]); // I4674
TDebugLogClient.Instance.WriteMessage('ActivateKeyboard: LastFocus=%x LastActive=%x Keyboard=%s KeymanID=%d', [FLastFocus, FLastActive, Keyboard.Caption, Keyboard.KeymanID]); // I4674
hwnd := FLastFocus;
AllowSetForegroundWindow(ASFW_ANY); // I3933
PostMessage(FLastActive, wm_keyman_control_internal, KMCI_SETFOREGROUND, FLastFocus); // I3933
@ -1405,23 +1393,23 @@ begin
tid := GetWindowThreadProcessId(FLastFocus, nil);
if tid = 0 then
begin
TDebugManager.WriteLastError('SetLastFocus', 'GetWindowThreadProcessId');
TDebugLogClient.Instance.WriteLastError('SetLastFocus', 'GetWindowThreadProcessId');
Exit;
end;
if not AttachThreadInput(tid, GetCurrentThreadId, TRUE) then
begin
TDebugManager.WriteLastError('SetLastFocus', 'AttachThreadInput:1');
TDebugLogClient.Instance.WriteLastError('SetLastFocus', 'AttachThreadInput:1');
Exit;
end;
//Windows.SetForegroundWindow(FLastFocus); //FLastActive);
if Winapi.Windows.SetFocus(FLastFocus) = 0 then
TDebugManager.WriteLastError('SetLastFocus', 'SetFocus');
TDebugLogClient.Instance.WriteLastError('SetLastFocus', 'SetFocus');
if not AttachThreadInput(tid, GetCurrentThreadId, FALSE) then
begin
TDebugManager.WriteLastError('SetLastFocus', 'AttachThreadInput:2');
TDebugLogClient.Instance.WriteLastError('SetLastFocus', 'AttachThreadInput:2');
Exit;
end;
end;

View file

@ -52,11 +52,10 @@ uses
UfrmCharacterMapFilter in '..\..\global\delphi\charmap\UfrmCharacterMapFilter.pas' {frmCharacterMapFilter},
FixedTrackbar in '..\..\global\delphi\comp\FixedTrackbar.pas',
Menu_KeyboardItems in 'Menu_KeyboardItems.pas',
DebugManager in '..\..\global\delphi\debug\DebugManager.pas',
Keyman.System.DebugLogManager in '..\..\global\delphi\debug\Keyman.System.DebugLogManager.pas',
PaintPanel in '..\..\global\delphi\comp\PaintPanel.pas',
exImageList in '..\..\global\delphi\comp\exImageList.pas',
utilhttp in '..\..\global\delphi\general\utilhttp.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
VistaMessages in 'VistaMessages.pas',
MessageIdentifierConsts in '..\..\global\delphi\cust\MessageIdentifierConsts.pas',
VisualKeyboardExportXML in '..\..\global\delphi\visualkeyboard\VisualKeyboardExportXML.pas',
@ -93,7 +92,6 @@ uses
WebSoundControl in '..\..\global\delphi\general\WebSoundControl.pas',
VKeyChars in '..\..\global\delphi\general\VKeyChars.pas',
usp10 in '..\..\global\delphi\general\usp10.pas',
UfrmDebugNotify in 'UfrmDebugNotify.pas' {frmDebugNotify},
UserMessages in '..\..\global\delphi\general\UserMessages.pas',
UfrmKeymanMenu in 'UfrmKeymanMenu.pas' {frmKeymanMenu},
UILanguages in '..\..\desktop\kmshell\util\UILanguages.pas',
@ -139,7 +137,9 @@ uses
Keyman.System.Standards.BCP47SubtagRegistry in '..\..\global\delphi\standards\Keyman.System.Standards.BCP47SubtagRegistry.pas',
Keyman.System.Standards.BCP47SuppressScriptRegistry in '..\..\global\delphi\standards\Keyman.System.Standards.BCP47SuppressScriptRegistry.pas',
Keyman.System.Standards.LibPalasoAllTagsRegistry in '..\..\global\delphi\standards\Keyman.System.Standards.LibPalasoAllTagsRegistry.pas',
Keyman.System.CanonicalLanguageCodeUtils in '..\..\global\delphi\general\Keyman.System.CanonicalLanguageCodeUtils.pas';
Keyman.System.CanonicalLanguageCodeUtils in '..\..\global\delphi\general\Keyman.System.CanonicalLanguageCodeUtils.pas',
Keyman.System.DebugLogClient in '..\..\global\delphi\debug\Keyman.System.DebugLogClient.pas',
Keyman.System.DebugLogCommon in '..\..\global\delphi\debug\Keyman.System.DebugLogCommon.pas';
{$R ICONS.RES}
{$R VERSION.RES}

View file

@ -149,11 +149,10 @@
</DCCReference>
<DCCReference Include="..\..\global\delphi\comp\FixedTrackbar.pas"/>
<DCCReference Include="Menu_KeyboardItems.pas"/>
<DCCReference Include="..\..\global\delphi\debug\DebugManager.pas"/>
<DCCReference Include="..\..\global\delphi\debug\Keyman.System.DebugLogManager.pas"/>
<DCCReference Include="..\..\global\delphi\comp\PaintPanel.pas"/>
<DCCReference Include="..\..\global\delphi\comp\exImageList.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilhttp.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="VistaMessages.pas"/>
<DCCReference Include="..\..\global\delphi\cust\MessageIdentifierConsts.pas"/>
<DCCReference Include="..\..\global\delphi\visualkeyboard\VisualKeyboardExportXML.pas"/>
@ -205,9 +204,6 @@
<DCCReference Include="..\..\global\delphi\general\WebSoundControl.pas"/>
<DCCReference Include="..\..\global\delphi\general\VKeyChars.pas"/>
<DCCReference Include="..\..\global\delphi\general\usp10.pas"/>
<DCCReference Include="UfrmDebugNotify.pas">
<Form>frmDebugNotify</Form>
</DCCReference>
<DCCReference Include="..\..\global\delphi\general\UserMessages.pas"/>
<DCCReference Include="UfrmKeymanMenu.pas">
<Form>frmKeymanMenu</Form>
@ -264,6 +260,8 @@
<DCCReference Include="..\..\global\delphi\standards\Keyman.System.Standards.BCP47SuppressScriptRegistry.pas"/>
<DCCReference Include="..\..\global\delphi\standards\Keyman.System.Standards.LibPalasoAllTagsRegistry.pas"/>
<DCCReference Include="..\..\global\delphi\general\Keyman.System.CanonicalLanguageCodeUtils.pas"/>
<DCCReference Include="..\..\global\delphi\debug\Keyman.System.DebugLogClient.pas"/>
<DCCReference Include="..\..\global\delphi\debug\Keyman.System.DebugLogCommon.pas"/>
<None Include="Profiling\AQtimeModule1.aqt"/>
<BuildConfiguration Include="Debug">
<Key>Cfg_2</Key>

View file

@ -245,7 +245,7 @@ uses
// System.StrUtils,
DebugManager,
Keyman.System.DebugLogClient,
glossary,
InterfaceHotkeys,
kmint,
@ -361,18 +361,18 @@ var
ppEnum: IEnumTfInputProcessorProfiles;
FItem: TLangSwitchKeyboard;
begin
TDebugManager.WriteMessage('[EnumTSFKeyboards] ENTER -------------', []);
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] ENTER -------------', []);
Assert(Assigned(FProfileMgr)); // I2864 // I4220
for I := 0 to FLanguages.Count - 1 do
begin
TDebugManager.WriteMessage('[EnumTSFKeyboards] LangID=%x', [FLanguages[i].LangID]);
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] LangID=%x', [FLanguages[i].LangID]);
FProfileMgr.EnumProfiles(FLanguages[i].LangID, ppEnum);
hr := ppEnum.Next(1, profile, pcFetch);
while hr = S_OK do
begin
try
TDebugManager.WriteMessage('[EnumTSFKeyboards] LangID=%x type=%d hkl=%x flags=%x', [FLanguages[i].LangID, profile.dwProfileType, profile.HKL, profile.dwFlags]);
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] LangID=%x type=%d hkl=%x flags=%x', [FLanguages[i].LangID, profile.dwProfileType, profile.HKL, profile.dwFlags]);
if (profile.dwFlags and TF_IPP_FLAG_ENABLED) = 0 then // I4207
begin
@ -382,12 +382,12 @@ begin
if profile.dwProfileType = TF_PROFILETYPE_KEYBOARDLAYOUT then
begin
FItem := TLangSwitchKeyboard_WinKeyboard.Create(Self, FLanguages[i], profile.HKL); //, (profile.dwFlags and TF_IPP_FLAG_ACTIVE) = TF_IPP_FLAG_ACTIVE); // I3961
TDebugManager.WriteMessage('[EnumTSFKeyboards] Creating WinKeyboard hkl=%x, valid=%s', [profile.HKL, BoolToStr(FItem.Valid)]); // I4648
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] Creating WinKeyboard hkl=%x, valid=%s', [profile.HKL, BoolToStr(FItem.Valid)]); // I4648
end
else if (profile.catid = GUID_TFCAT_TIP_KEYBOARD) then // I2826 // I3933 // I4005
begin
FItem := TLangSwitchKeyboard_TIP.Create(Self, FLanguages[i], profile); // I3961
TDebugManager.WriteMessage('[EnumTSFKeyboards] Creating TSF TIP guid=%s keymanid=%d, valid=%s', [GuidToString(profile.guidProfile), FItem.KeymanID, BoolToStr(FItem.Valid)]); // I4648
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] Creating TSF TIP guid=%s keymanid=%d, valid=%s', [GuidToString(profile.guidProfile), FItem.KeymanID, BoolToStr(FItem.Valid)]); // I4648
end
else
begin
@ -402,7 +402,7 @@ begin
end;
end;
end;
TDebugManager.WriteMessage('[EnumTSFKeyboards] EXIT ---------------', []);
TDebugLogClient.Instance.WriteMessage('[EnumTSFKeyboards] EXIT ---------------', []);
end;
procedure TLangSwitchManager.Refresh; // I3933
@ -682,7 +682,7 @@ procedure TLangSwitchKeyboard_WinKeyboard.Activate(hwnd: THandle);
begin
// Assert(FValid); // I4715
FManager.SetActiveItem(Self); // I3933
TDebugManager.WriteMessage('TLangSwitchKeyboard_WinKeyboard.Activate hwnd=%x keyboard=%x', [hwnd, FHKL]); // I4674
TDebugLogClient.Instance.WriteMessage('TLangSwitchKeyboard_WinKeyboard.Activate hwnd=%x keyboard=%x', [hwnd, FHKL]); // I4674
PostMessage(hwnd, wm_keyman_control_internal, KMCI_SELECTKEYBOARD, FHKL); // I3933
end;
@ -773,7 +773,7 @@ begin
FManager.SetActiveItem(Self); // I3933
s := IntToStr(FProfile.langid) + '|' + GUIDToString(TGUID(FProfile.clsid)) + '|' + GUIDToString(TGUID(FProfile.guidProfile));
FAtom := GlobalAddAtom(PChar(s));
TDebugManager.WriteMessage('TLangSwitchKeyboard_TIP.Activate hwnd=%x keyboard=%s', [hwnd, s]); // I4674
TDebugLogClient.Instance.WriteMessage('TLangSwitchKeyboard_TIP.Activate hwnd=%x keyboard=%s', [hwnd, s]); // I4674
PostMessage(hwnd, wm_keyman_control_internal, KMCI_SELECTKEYBOARD_TSF, FAtom); // I3933
end;

View file

@ -146,7 +146,7 @@ implementation
uses
System.Math,
DebugManager,
Keyman.System.DebugLogClient,
KeymanControlMessages,
keymanapi_TLB,
UfrmKeyman7Main,
@ -261,7 +261,7 @@ procedure TfrmLanguageSwitch.FormKeyDown(Sender: TObject; var Key: Word;
end;
begin
TDebugManager.WriteMessage('TfrmLanguageSwitch.FormKeyDown ENTER: %d [%d %d]', [Key, FSelectedLanguage, FSelectedKeyboard]);
TDebugLogClient.Instance.WriteMessage('TfrmLanguageSwitch.FormKeyDown ENTER: %d [%d %d]', [Key, FSelectedLanguage, FSelectedKeyboard]);
try
if FSelectedLanguage = -1 then FSelectedLanguage := 0;
if FSelectedKeyboard = -1 then FSelectedKeyboard := 0;
@ -362,7 +362,7 @@ begin
EndCanvas;
end;
finally
TDebugManager.WriteMessage('TfrmLanguageSwitch.FormKeyDown EXIT: %d [%d %d]', [Key, FSelectedLanguage, FSelectedKeyboard]);
TDebugLogClient.Instance.WriteMessage('TfrmLanguageSwitch.FormKeyDown EXIT: %d [%d %d]', [Key, FSelectedLanguage, FSelectedKeyboard]);
end;
Key := 0;
end;
@ -389,7 +389,7 @@ begin
DrawLayer; // I2677
TDebugManager.WriteMessage('TfrmLanguageSwitch.FormShow EXIT: [%d %d]', [FSelectedLanguage, FSelectedKeyboard]);
TDebugLogClient.Instance.WriteMessage('TfrmLanguageSwitch.FormShow EXIT: [%d %d]', [FSelectedLanguage, FSelectedKeyboard]);
end;
procedure TfrmLanguageSwitch.GetColors(y: Integer; var cc: array of Cardinal);

View file

@ -46,24 +46,33 @@
#include "keyman64.h"
#include <stdio.h>
#include <stdarg.h>
#include <evntprov.h>
#include "keyman-debug-etw.h"
//#define _FILELOG
#ifdef _WIN64
#define DEBUG_PLATFORM_STRING "x64"
#define DEBUG_PLATFORM_STRINGW L"x64"
#else
#define DEBUG_PLATFORM_STRING "x86"
#define DEBUG_PLATFORM_STRINGW L"x86"
#endif
#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)
{
void InitDebuggingEx(PKEYMAN64THREADDATA _td) {
RegistryReadOnly reg(HKEY_CURRENT_USER);
if(reg.OpenKeyReadOnly(REGSZ_KeymanCU)) {
_td->debug_KeymanLog = reg.ValueExists(REGSZ_Debug) && reg.ReadInteger(REGSZ_Debug);
@ -75,55 +84,15 @@ void InitDebuggingEx(PKEYMAN64THREADDATA _td)
}
if(_td->debug_KeymanLog)
{
if(_td->debug_hLogMailSlot != 0 && _td->debug_hLogMailSlot != INVALID_HANDLE_VALUE)
CloseHandle(_td->debug_hLogMailSlot);
_td->debug_hLogMailSlot = CreateFile("\\\\.\\mailslot\\Tavultesoft_KeymanEngine_Debug",
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, // required to write to a mailslot
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if(_td->debug_hLogEvent) CloseHandle(_td->debug_hLogEvent);
_td->debug_hLogEvent = CreateEvent(NULL, FALSE, FALSE, "Tavultesoft_KeymanEngine_DebugWrite");
/*
FILE *fp = fopen("c:\\keyman.log", "at");
fprintf(fp, "opening log %d (error=%d)\n", hLogMailSlot, GetLastError());
fclose(fp);*/
#ifdef _FILELOG
char filenamebuf[256];
wsprintf(filenamebuf, "c:\\keymanlog\\system-%d-%d.log", GetCurrentProcessId(), GetCurrentThreadId());
_td->debug_fp = (void*) fopen(filenamebuf, "at");
#endif
if (_td->debug_hLogMailSlot == INVALID_HANDLE_VALUE)
{
_td->debug_hLogMailSlot = 0;
}
}
else
{
if(_td->debug_hLogMailSlot != 0) CloseHandle(_td->debug_hLogMailSlot);
_td->debug_hLogMailSlot = 0;
if(_td->debug_hLogEvent) CloseHandle(_td->debug_hLogEvent);
_td->debug_hLogEvent = 0;
if(_td->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?
}
}
}
inline void TestInitDebug(PKEYMAN64THREADDATA _td)
{
if(!_td->debug_DebugInit) InitDebuggingEx(_td);
_td->debug_DebugInit = TRUE;
}
void InitDebugging()
{
void InitDebugging() {
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
@ -164,30 +133,26 @@ void UninitDebuggingEx()
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
if(_td->debug_hLogMailSlot) CloseHandle(_td->debug_hLogMailSlot);
_td->debug_hLogMailSlot = 0;
if(_td->debug_hLogEvent) CloseHandle(_td->debug_hLogEvent);
_td->debug_hLogEvent = 0;
#ifdef _FILELOG
if(_td->debug_fp) fclose((FILE*)_td->debug_fp);
_td->debug_fp = NULL;
#endif
if (_td->etwRegHandle != NULL) {
EventUnregister(_td->etwRegHandle);
_td->etwRegHandle = NULL;
}
_td->debug_DebugInit = FALSE;
}
void UninitDebugging()
{
void UninitDebugging() {
SendDebugMessage(0, sdmGlobal, 0, "--- UninitDebugging() - shutting down ---");
}
const TSDMState DebugState[] = {sdmInternat, sdmAIDefault, sdmMessage, sdmKeyboard, sdmGlobal, sdmMenu, sdmDebug, sdmLoad, sdmOther};
BOOL ShouldDebug_1() //TSDMState state)
{
BOOL ShouldDebug_1() {
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
TestInitDebug(_td);
if (!_td->debug_DebugInit) InitDebuggingEx(_td);
_td->debug_DebugInit = TRUE;
return _td->debug_KeymanLog;
}
@ -245,47 +210,38 @@ int SendDebugMessage_1(HWND hwnd, TSDMState state, int kmn_lineno, char *file, i
{
UNREFERENCED_PARAMETER(hwnd);
UNREFERENCED_PARAMETER(state); // I3569
UNREFERENCED_PARAMETER(kmn_lineno);
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return 0;
if(_td->debug_KeymanLog)
{
OVERLAPPED ov;
DWORD cbWritten;
char windowinfo[1024];
if (msg == NULL) {
return 0;
}
if(msg == NULL)
{
switch(kmn_lineno)
{
case -1: // Signal an event to the controller
strcpy(windowinfo, "*");
break;
}
}
else
{
GUITHREADINFO gti;
char
//sClassName[32], sWindowText[32],
//sFocusClassName[32], sFocusWindowText[32],
//sActiveClassName[32], sActiveWindowText[32],
sProcessPath[256], sProcessName[32];
if(_td->debug_KeymanLog) {
GUITHREADINFO gti;
char
//sClassName[32], sWindowText[32],
//sFocusClassName[32], sFocusWindowText[32],
//sActiveClassName[32], sActiveWindowText[32],
sProcessPath[256], sProcessName[32];
gti.cbSize = sizeof(gti);
GetGUIThreadInfo(GetCurrentThreadId(), &gti);
gti.cbSize = sizeof(gti);
GetGUIThreadInfo(GetCurrentThreadId(), &gti);
//FillWindowInfo(hwnd, sClassName, sWindowText); // I3656
//FillWindowInfo(gti.hwndActive, sActiveClassName, sActiveWindowText); // I3656
//FillWindowInfo(gti.hwndFocus, sFocusClassName, sFocusWindowText); // I3656
//FillWindowInfo(hwnd, sClassName, sWindowText); // I3656
//FillWindowInfo(gti.hwndActive, sActiveClassName, sActiveWindowText); // I3656
//FillWindowInfo(gti.hwndFocus, sFocusClassName, sFocusWindowText); // I3656
GetModuleFileName(NULL, sProcessPath, 256);
_splitpath_s(sProcessPath, NULL, 0, NULL, 0, sProcessName, 32, NULL, 0);
sProcessName[31] = 0;
GetModuleFileName(NULL, sProcessPath, 256);
_splitpath_s(sProcessPath, NULL, 0, NULL, 0, sProcessName, 32, NULL, 0);
sProcessName[31] = 0;
if(strlen(msg) > 256) msg[255] = 0;
if(strlen(msg) > 256) msg[255] = 0;
wsprintf(windowinfo,
if(_td->debug_ToConsole) { // I3951
char windowinfo[1024];
wsprintf(windowinfo,
DEBUG_PLATFORM_STRING TAB //"Platform" TAB
"%s" TAB //"Process" TAB
"%x" TAB //"PID" TAB
@ -309,7 +265,7 @@ int SendDebugMessage_1(HWND hwnd, TSDMState state, int kmn_lineno, char *file, i
"%8x" TAB //"ActiveHKL" TAB
"%s:%d" TAB //"SourceFile" TAB
"%s", //"Message"
sProcessName, //"Process" TAB
GetCurrentProcessId(), //"PID" TAB
GetCurrentThreadId(), //"TID" TAB
@ -337,46 +293,53 @@ int SendDebugMessage_1(HWND hwnd, TSDMState state, int kmn_lineno, char *file, i
GetKeyboardLayout(0), //"ActiveHKL" TAB
file, line, //"SourceFile" TAB
msg); //"Message"
}
#ifdef _FILELOG
if(_td->debug_fp)
{
fputs(windowinfo, (FILE*)_td->debug_fp);
fputs("\n", (FILE*)_td->debug_fp);
}
#endif
if(_td->debug_ToConsole) { // I3951
OutputDebugString(windowinfo); // I3570 // I3951
OutputDebugString("\n"); // I3570 // I3951
}
if(_td->debug_hLogMailSlot != 0)
{
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = _td->debug_hLogEvent;
if(!WriteFile(_td->debug_hLogMailSlot,
windowinfo,
(DWORD) strlen(windowinfo) + 1, // include terminating null
&cbWritten,
&ov))
{
switch(GetLastError()) // I2445 - Try and reconnect debug pipe on error
{
case ERROR_HANDLE_EOF:
case ERROR_BROKEN_PIPE:
UninitDebuggingEx();
InitDebuggingEx(_td);
if(WriteFile(_td->debug_hLogMailSlot,
windowinfo,
(DWORD) strlen(windowinfo) + 1, // include terminating null
&cbWritten,
&ov)) break;
default:
UninitDebuggingEx();
_td->debug_KeymanLog = FALSE; /// Failed again - we could log to system log I guess
}
if (_td->etwRegHandle != NULL) {
#define MAX_DESCRIPTORS 12
// TODO: convert debugging to Unicode
PWSTR sProcessNameW = strtowstr(sProcessName);
PWSTR fileW = strtowstr(file);
PWSTR msgW = strtowstr(msg);
EVENT_DATA_DESCRIPTOR Descriptors[MAX_DESCRIPTORS];
DWORD pid = GetCurrentProcessId();
DWORD tid = GetCurrentThreadId();
DWORD shiftState = Globals::get_ShiftState();
DWORD actualShiftState = GetActualShiftState();
DWORD tickCount = GetTickCount();
HKL activeHKL = GetKeyboardLayout(0);
#ifdef _WIN64
DWORD platform = 2;
#else
DWORD platform = 1;
#endif
// These must match the manifest template in keyman-debug-etw.man
EventDataDescCreate(&Descriptors[0], &platform, sizeof(DWORD)); // <data name = "Platform" inType = "Platform" / >
EventDataDescCreate(&Descriptors[1], sProcessNameW, (ULONG) (wcslen(sProcessNameW) + 1) * sizeof(WCHAR)); // <data name = "Process" inType = "win:UnicodeString" / >
EventDataDescCreate(&Descriptors[2], &pid, sizeof(DWORD)); // <data name = "PID" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[3], &tid, sizeof(DWORD)); // <data name = "TID" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[4], &shiftState, sizeof(DWORD)); // <data name = "ShiftState" inType = "ShiftState" / >
EventDataDescCreate(&Descriptors[5], &actualShiftState, sizeof(DWORD)); // <data name = "ActualShiftState" inType = "ShiftState" / >
EventDataDescCreate(&Descriptors[6], &tickCount, sizeof(DWORD)); // <data name = "TickCount" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[7], (PDWORD)&gti.hwndFocus, sizeof(DWORD)); // <data name = "FocusHWND" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[8], (PDWORD)&activeHKL, sizeof(DWORD)); // <data name = "ActiveHKL" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[9], fileW, (ULONG) (wcslen(fileW)+1) * sizeof(WCHAR)); // <data name = "SourceFile" inType = "win:UnicodeString" / >
EventDataDescCreate(&Descriptors[10], (PDWORD)&line, sizeof(DWORD)); // <data name = "SourceLine" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[11], msgW, (ULONG) (wcslen(msgW)+1) * sizeof(WCHAR)); // <data name = "Message" inType = "win:UnicodeString" / >
DWORD dwErr = EventWrite(_td->etwRegHandle, &DebugEvent, (ULONG)MAX_DESCRIPTORS, &Descriptors[0]);
if (dwErr != ERROR_SUCCESS) {
OutputDebugString("Keyman k32_dbg: Failed to call EventWrite");
}
delete sProcessNameW;
delete fileW;
delete msgW;
}
}

View file

@ -342,11 +342,24 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="keyman-debug-etw.man">
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling keyman-debug-etw</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename.h);MSG00001.bin</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling keyman-debug-etw</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename.h);MSG00001.bin</Outputs>
<SubType>Designer</SubType>
</CustomBuild>
<None Include="KEYMAN32.DEF" />
<None Include="..\..\global\res\bmp\arrow.bmp" />
<None Include="..\..\global\res\bmp\mask.bmp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="keyman-debug-etw.rc" />
<ResourceCompile Include="KEYMAN32.RC">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -368,6 +381,7 @@
<ClInclude Include="..\..\global\inc\keyman64.h" />
<ClInclude Include="..\..\global\inc\keymanapi.h" />
<ClInclude Include="..\..\global\inc\keymancontrol.h" />
<ClInclude Include="keyman-debug-etw.h" />
<ClInclude Include="keystate.h" />
<ClInclude Include="..\..\global\inc\Km95api.h" />
<ClInclude Include="..\..\global\inc\rc4.h" />

View file

@ -136,6 +136,9 @@
<ResourceCompile Include="KEYMAN32.RC">
<Filter>Source Files</Filter>
</ResourceCompile>
<ResourceCompile Include="keyman-debug-etw.rc">
<Filter>Source Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="addins.h">
@ -204,5 +207,11 @@
<ClInclude Include="k32_tsf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="keyman-debug-etw.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="keyman-debug-etw.man" />
</ItemGroup>
</Project>

View file

@ -52,6 +52,8 @@
#ifndef _globals_h
#define _globals_h
#include <evntprov.h>
#define GLOBAL_ContextStackSize 80
#define GLOBAL_MsgStackSize 80
#define GLOBAL_MaxKeyboards 32
@ -216,13 +218,12 @@ typedef struct tagKEYMAN64THREADDATA
int CurrentAddin;
HWND CurrenthWnd;
void *debug_fp;
HANDLE debug_hLogMailSlot, debug_hLogEvent;
BOOL debug_DebugInit, debug_KeymanLog, debug_ToConsole; // I3951
char debug_buf[64];
// I3617 // I3618
REGHANDLE etwRegHandle;
/* TSF Manager Globals */

View file

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<instrumentationManifest
xmlns="http://schemas.microsoft.com/win/2004/08/events"
xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<instrumentation>
<events>
<!-- resourceFileName and messageFileName must be set at install time -->
<provider name="Keyman-Debug-ETWProvider"
guid="{DA621615-E08B-4283-918E-D2502D3757AE}"
symbol="ProviderGuid"
resourceFileName="c:\program files (x86)\common files\keyman\keyman engine\keyman32.dll"
messageFileName="c:\program files (x86)\common files\keyman\keyman engine\keyman32.dll"
message="$(string.Provider.Name)"
>
<maps>
<valueMap name="Platform">
<map value="1" message="$(string.Map.x86)"/>
<map value="2" message="$(string.Map.x64)"/>
</valueMap>
<bitMap name="ShiftState">
<map value="0x1" message="$(string.Map.LCTRL)"/>
<map value="0x2" message="$(string.Map.RCTRL)"/>
<map value="0x4" message="$(string.Map.LALT)"/>
<map value="0x8" message="$(string.Map.RALT)"/>
<map value="0x10" message="$(string.Map.SHIFT)"/>
<map value="0x20" message="$(string.Map.CTRL)"/>
<map value="0x40" message="$(string.Map.ALT)"/>
<map value="0x100" message="$(string.Map.CAPSLOCK)"/>
<map value="0x200" message="$(string.Map.NOTCAPSOCK)"/>
<map value="0x400" message="$(string.Map.NUMLOCK)"/>
<map value="0x800" message="$(string.Map.NOTNUMLOCK)"/>
<map value="0x1000" message="$(string.Map.SCROLLLOCK)"/>
<map value="0x2000" message="$(string.Map.NOTSCROLLLOCK)"/>
<map value="0x4000" message="$(string.Map.ISVIRTUALKEY)"/>
<map value="0x8000" message="$(string.Map.VIRTUALCHARKEY)"/>
</bitMap>
</maps>
<channels>
<channel name="Keyman-Debug-ETWProvider/Debug" chid="C1" type="Debug" />
</channels>
<templates>
<!-- This template must match the EventDataDescCreate calls in K32_DBG.CPP and Keyman.System.DebugLogClient.pas -->
<template tid="DebugEntryTemplate">
<data name="Platform" inType="win:UInt32" map="Platform" />
<data name="Process" inType="win:UnicodeString" />
<data name="PID" inType="win:UInt32" />
<data name="TID" inType="win:UInt32" />
<data name="ShiftState" inType="win:UInt32" map="ShiftState" />
<data name="ActualShiftState" inType="win:UInt32" map="ShiftState" />
<data name="TickCount" inType="win:UInt32" />
<data name="FocusHWND" inType="win:UInt32" />
<data name="ActiveHKL" inType="win:UInt32" />
<data name="SourceFile" inType="win:UnicodeString" />
<data name="SourceLine" inType="win:UInt32" />
<data name="Message" inType="win:UnicodeString" />
</template>
</templates>
<events>
<!-- DebugEvent is defined in Keyman.System.DebugLogClient.pas and needs to be updated if this changes -->
<event value="1"
channel="C1"
level="win:Informational"
template="DebugEntryTemplate"
symbol="DebugEvent"
message="$(string.EventMessage)" />
</events>
</provider>
</events>
</instrumentation>
<localization>
<resources culture="en-US">
<stringTable>
<string id="Provider.Name" value="Keyman-Debug-ETWProvider"/>
<string id="EventMessage" value="[%1] [%2] [%3] [%4] (%5 %6) %7 %8 %9 %10:%11 %12" />
<string id="Map.x86" value="x86" />
<string id="Map.x64" value="x64" />
<string id="Map.LCTRL" value="LCTRL" />
<string id="Map.RCTRL" value="RCTRL" />
<string id="Map.LALT" value="LALT" />
<string id="Map.RALT" value="RALT" />
<string id="Map.SHIFT" value="SHIFT" />
<string id="Map.CTRL" value="CTRL" />
<string id="Map.ALT" value="ALT" />
<string id="Map.CAPSLOCK" value="CAPSLOCK" />
<string id="Map.NOTCAPSOCK" value="NOTCAPSOCK" />
<string id="Map.NUMLOCK" value="NUMLOCK" />
<string id="Map.NOTNUMLOCK" value="NOTNUMLOCK" />
<string id="Map.SCROLLLOCK" value="SCROLLLOCK" />
<string id="Map.NOTSCROLLLOCK" value="NOTSCROLLLOCK" />
<string id="Map.ISVIRTUALKEY" value="ISVIRTUALKEY" />
<string id="Map.VIRTUALCHARKEY" value="VIRTUALCHARKEY" />
</stringTable>
</resources>
</localization>
</instrumentationManifest>

View file

@ -298,6 +298,7 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\keyman32\keyman-debug-etw.rc" />
<ResourceCompile Include="Keyman64.RC" />
</ItemGroup>
<ItemGroup>
@ -325,6 +326,7 @@
<ClInclude Include="..\..\global\inc\keymanapi.h" />
<ClInclude Include="..\..\global\inc\keymancontrol.h" />
<ClInclude Include="..\..\global\inc\KEYNAMES.H" />
<ClInclude Include="..\keyman32\keyman-debug-etw.h" />
<ClInclude Include="..\keyman32\keystate.h" />
<ClInclude Include="..\..\global\inc\Kl95api.h" />
<ClInclude Include="..\..\global\inc\Km95api.h" />
@ -344,6 +346,25 @@
<ItemGroup>
<None Include="..\..\global\res\bmp\arrow.bmp" />
<None Include="..\..\global\res\bmp\mask.bmp" />
<CustomBuild Include="..\keyman32\keyman-debug-etw.man">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc %(FullPath)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(Filename).rc;%(Filename).h;MSG00001.bin</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc %(FullPath)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Filename).rc;%(Filename).h;MSG00001.bin</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">mc %(FullPath)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(Filename).rc;%(Filename).h;MSG00001.bin</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">mc %(FullPath)</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(Filename).rc;%(Filename).h;MSG00001.bin</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling %(Filename).man</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling %(Filename).man</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compiling %(Filename).man</Message>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compiling %(Filename).man</Message>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -113,6 +113,9 @@
<ResourceCompile Include="Keyman64.RC">
<Filter>Source Files</Filter>
</ResourceCompile>
<ResourceCompile Include="..\keyman32\keyman-debug-etw.rc">
<Filter>Source Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\keyman32\addins.h">
@ -232,6 +235,9 @@
<ClInclude Include="..\keyman32\vkscancodes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\keyman32\keyman-debug-etw.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\global\res\bmp\arrow.bmp">
@ -240,5 +246,8 @@
<None Include="..\..\global\res\bmp\mask.bmp">
<Filter>Resource Files</Filter>
</None>
<None Include="..\keyman32\keyman-debug-etw.man">
<Filter>Source Files</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -101,7 +101,6 @@ uses
utildir in '..\..\global\delphi\general\utildir.pas',
utiltsf in '..\..\global\delphi\general\utiltsf.pas',
OnlineConstants in '..\..\global\delphi\productactivation\OnlineConstants.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
MessageDefaults in '..\..\global\delphi\cust\MessageDefaults.pas',
MessageIdentifierConsts in '..\..\global\delphi\cust\MessageIdentifierConsts.pas',
KeymanEngineControl in '..\..\global\delphi\general\KeymanEngineControl.pas',

View file

@ -238,7 +238,6 @@
<DCCReference Include="..\..\global\delphi\general\utildir.pas"/>
<DCCReference Include="..\..\global\delphi\general\utiltsf.pas"/>
<DCCReference Include="..\..\global\delphi\productactivation\OnlineConstants.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\cust\MessageDefaults.pas"/>
<DCCReference Include="..\..\global\delphi\cust\MessageIdentifierConsts.pas"/>
<DCCReference Include="..\..\global\delphi\general\KeymanEngineControl.pas"/>

View file

@ -31,7 +31,6 @@ uses
klog in '..\..\global\delphi\general\klog.pas',
utildir in '..\..\global\delphi\general\utildir.pas',
utilsystem in '..\..\global\delphi\general\utilsystem.pas',
SystemDebugPath in '..\..\global\delphi\general\SystemDebugPath.pas',
ErrorControlledRegistry in '..\..\global\delphi\vcl\ErrorControlledRegistry.pas',
Unicode in '..\..\global\delphi\general\Unicode.pas',
utilexecute in '..\..\global\delphi\general\utilexecute.pas',

View file

@ -7,7 +7,7 @@
<TargetedPlatforms>1</TargetedPlatforms>
<AppType>Application</AppType>
<FrameworkType>VCL</FrameworkType>
<ProjectVersion>18.3</ProjectVersion>
<ProjectVersion>18.4</ProjectVersion>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
@ -175,7 +175,6 @@
<DCCReference Include="..\..\global\delphi\general\klog.pas"/>
<DCCReference Include="..\..\global\delphi\general\utildir.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilsystem.pas"/>
<DCCReference Include="..\..\global\delphi\general\SystemDebugPath.pas"/>
<DCCReference Include="..\..\global\delphi\vcl\ErrorControlledRegistry.pas"/>
<DCCReference Include="..\..\global\delphi\general\Unicode.pas"/>
<DCCReference Include="..\..\global\delphi\general\utilexecute.pas"/>

View file

@ -2001,7 +2001,7 @@ function FlushTrace; external advapi32 name 'FlushTrace'+AWSuffix;
{$ENDIF WINXP_UP}
function ControlTraceW; external advapi32 name 'ControlTraceW';
function ControlTraceA; external advapi32 name 'ControlTraceA';
function ControlTrace; external advapi32 name 'ControlTraceA'+AWSuffix;
function ControlTrace; external advapi32 name 'ControlTrace'+AWSuffix;
function QueryAllTracesW; external advapi32 name 'QueryAllTracesW';
function QueryAllTracesA; external advapi32 name 'QueryAllTracesA';

View file

@ -1,643 +0,0 @@
(*
Name: DebugManager
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 - Initial version
04 Jan 2007 - mcdurdin - Add ShouldDebug function
19 Jun 2007 - mcdurdin - Widestring it
19 Nov 2007 - mcdurdin - I1157 - const string parameters
04 May 2010 - mcdurdin - I2348 - Rework columns in debug log
04 May 2010 - mcdurdin - I2349 - Hotkey to capture debug log
04 May 2010 - mcdurdin - I2350 - Keyman.exe should be able to report events in debug log
04 May 2010 - mcdurdin - I2352 - Debug logging not reliable in some apps due to security
15 Jun 2010 - mcdurdin - I2423 - Fix crash in debug manager
24 Jun 2010 - mcdurdin - I2422 - Recreate, not rewrite existing log files
29 Jun 2010 - mcdurdin - I2446 - Keyman Engine crashes due to debug manager being freed late
17 Dec 2010 - mcdurdin - Add extra column to raw strings
11 Jan 2011 - mcdurdin - I2640 - Raise error at appropriate location so it isn't masked by cascading issue
31 Jan 2011 - mcdurdin - I2685 - Reduce registry noise from ShouldDebug function
31 Jan 2011 - mcdurdin - I2690 - Add foreground window info to debug log
31 Jan 2011 - mcdurdin - I2691 - Fix handle leaks
18 Feb 2011 - mcdurdin - I2685 : 9827 - Fix shoulddebug refresh counter not resetting
03 May 2011 - mcdurdin - I2890 - Record diagnostic data when encountering registry errors
18 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support
08 Jun 2012 - mcdurdin - I3310 - V9.0 - Unicode in Delphi fixes
28 Nov 2012 - mcdurdin - I3601 - V9.0 - Debug messages were written partially Unicode, partially ANSI
13 Dec 2012 - mcdurdin - I3656 - V9.0 - Debug logs show too many columns for host messages
01 Jan 2013 - mcdurdin - I3692 - V9.0 - [host] entries in system.log out by 1 tabstop
09 Aug 2015 - mcdurdin - I4843 - Log reported modifier state as well as Keyman current modifier state
*)
unit DebugManager; // I3306
interface
uses
Windows,
Classes,
SysUtils,
UserMessages;
type
TDebugManagerMessageEvent = procedure(Sender: TObject; const Message: string) of object;
TDebugManager = class(TThread)
private
FOwner: HWND;
hLogFile, hMailSlot: THandle;
hEvent: THandle;
FDebugLogIndex: Integer;
FOnMessage: TDebugManagerMessageEvent;
const
crlf: AnsiString = #13#10;
procedure WriteHeadingString;
procedure WriteMessage(buf: PAnsiChar; buflen: Integer); overload; // I3310
procedure StartNewLogFile;
procedure FindFirstLogFileName;
protected
procedure Execute; override;
class procedure CloseLogFile(var Handle: THandle);
class procedure WriteString(Handle: THandle; const s: string);
class procedure WriteMessage(Handle: THandle; buf: PAnsiChar; buflen: Integer); overload; // I3310
class procedure WriteRawString(Handle: THandle; const s: string); static;
public
constructor Create(AOwner: HWND); reintroduce;
destructor Destroy; override;
class procedure WriteLastError(const ParentMethod, FailingMethod: string; const Message: string = '');
class procedure WriteMessage(const Format: string; const Args: array of const); overload;
class function DebugLogFileName(n: Integer): WideString;
property OnMessage: TDebugManagerMessageEvent read FOnMessage write FOnMessage;
end;
function GetDebugManager(AOwner: HWND): TDebugManager;
implementation
uses
Accctrl,
AclApi,
ErrorControlledRegistry,
RegistryKeys,
SystemDebugPath,
Unicode;
var
FDebugManager: TDebugManager = nil;
FTerminating: Boolean = False;
FShouldDebug: Boolean = False;
FShouldDebugLastTick: Cardinal = 0;
function ShouldDebug: Boolean;
var
t1: Cardinal;
begin
t1 := GetTickCount;
if (t1 < FShouldDebugLastTick) or (t1 - FShouldDebugLastTick > 5000) then // I2685
begin
with TRegistryErrorControlled.Create do // I2890
try
if OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and ValueExists(SRegValue_KeymanDebug)
then FShouldDebug := ReadBool(SRegValue_KeymanDebug)
else FShouldDebug := False;
finally
Free;
end;
FShouldDebugLastTick := GetTickCount; // I2685:9827
end;
Result := FShouldDebug;
end;
function GetDebugManager(AOwner: HWND): TDebugManager;
begin
Assert(not FTerminating);
if ShouldDebug then
begin
if not Assigned(FDebugManager) then
FDebugManager := TDebugManager.Create(AOwner);
Result := FDebugManager;
end
else
Result := nil;
end;
{ TDebugManager }
class procedure TDebugManager.CloseLogFile(var Handle: THandle);
begin
if Handle <> 0 then
begin
WriteString(Handle, '---- Log file closed '+FormatDateTime('C', now) + '----');
CloseHandle(Handle);
Handle := 0;
end;
end;
const LOW_INTEGRITY_SDDL_SACL_W: WideString = 'S:(ML;;NW;;;LW)';
const LABEL_SECURITY_INFORMATION = $00000010;
const SDDL_REVISION_1 = 1;
function ConvertStringSecurityDescriptorToSecurityDescriptor(
{IN} StringSecurityDescriptor: LPCWSTR;
{IN} StringSDRevision: DWORD;
{OUT} var SecurityDescriptor: PSECURITY_DESCRIPTOR;
{OUT} SecurityDescriptorSize: PULONG {OPTIONAL}
): BOOL; stdcall; external 'advapi32.dll' name 'ConvertStringSecurityDescriptorToSecurityDescriptorW';
function SetObjectToLowIntegrity(hObject: THandle; _type: SE_OBJECT_TYPE = SE_KERNEL_OBJECT): BOOL;
var
dwErr: DWORD;
pSD: PSECURITY_DESCRIPTOR;
pSacl: PACL;
fSaclPresent: BOOL;
fSaclDefaulted: BOOL;
begin
//BOOL bRet = FALSE;
//dwErr := ERROR_SUCCESS;
Result := False;
pSD := nil;
pSacl := nil;
fSaclPresent := FALSE;
fSaclDefaulted := FALSE;
if LOBYTE(LOWORD(GetVersion())) >= 6 then
begin
if ConvertStringSecurityDescriptorToSecurityDescriptor(PWideChar(LOW_INTEGRITY_SDDL_SACL_W), SDDL_REVISION_1, pSD, nil) then
begin
if GetSecurityDescriptorSacl(pSD, fSaclPresent, pSacl, fSaclDefaulted) then
begin
dwErr := SetSecurityInfo(
hObject, _type, LABEL_SECURITY_INFORMATION,
nil, nil, nil, pSacl);
Result := ERROR_SUCCESS = dwErr;
end;
end;
LocalFree(Cardinal(pSD));
end
else
Result := True;
end;
constructor TDebugManager.Create(AOwner: HWND);
const
lpszSlotName: string = '\\.\mailslot\tavultesoft_keymanengine_debug';
var
pSD: PSECURITY_DESCRIPTOR;
//sd: SECURITY_DESCRIPTOR;
sa: SECURITY_ATTRIBUTES;
//bSaclPresent: LongBool;
//pSacl: PACL;
//bSaclDefaulted: LongBool;
//fSaclPresent: LongBool;
begin
FOwner := AOwner;
if LOBYTE(LOWORD(GetVersion())) >= 6 then
begin
if ConvertStringSecurityDescriptorToSecurityDescriptor(PWideChar(LOW_INTEGRITY_SDDL_SACL_W), SDDL_REVISION_1, pSD, nil) then
begin
sa.nLength := sizeof(sa);
sa.lpSecurityDescriptor := pSD;
sa.bInheritHandle := FALSE;
hMailSlot := CreateMailslot(PChar(lpszSlotName),
0, // no maximum message size
10, // 10 msec time-out for operations
@sa);
if hMailSlot = INVALID_HANDLE_VALUE then RaiseLastOSError; // I2640 - Raise error at appropriate location so it isn't masked by cascading issue
// For some reason the mailslot does not have full access for everyone so we need to set it afterwards anyway!
if SetSecurityInfo(hMailSlot, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, nil, nil) <> ERROR_SUCCESS then
RaiseLastOSError;
LocalFree(Cardinal(pSD));
end
else RaiseLastOSError;
end
else
begin
hMailSlot := CreateMailslot(PChar(lpszSlotName),
0, // no maximum message size
10, // 10 msec time-out for operations
nil);
if hMailSlot = INVALID_HANDLE_VALUE then RaiseLastOSError;
end;
try
FindFirstLogFileName;
StartNewLogFile;
try
hEvent := CreateEvent(nil, FALSE, FALSE, 'Tavultesoft_KeymanEngine_Debug');
if hEvent = 0 then RaiseLastOSError;
if not SetObjectToLowIntegrity(hEvent) then RaiseLastOSError;
try
SetFilePointer(hLogFile, 0, nil, FILE_END);
FreeOnTerminate := False; // I2446 - Keyman Engine crashes due to debug manager being freed late
inherited Create(False);
except
on E:Exception do
begin
CloseHandle(hEvent);
hEvent := 0;
raise;
end;
end;
except
on E:Exception do
begin
CloseHandle(hLogFile);
hLogFile := 0;
raise;
end;
end;
except
on E:Exception do
begin
CloseHandle(hMailSlot);
hMailSlot := 0;
raise;
end;
end;
end;
destructor TDebugManager.Destroy;
begin
CloseLogFile(hLogFile);
if hMailSlot <> 0 then CloseHandle(hMailSlot);
if hEvent <> 0 then CloseHandle(hEvent);
inherited Destroy;
end;
const
MAXDEBUGLOGS = 16;
class function TDebugManager.DebugLogFileName(n: Integer): WideString;
begin
Result := GetSystemDebugPath + 'system' + IntToStr(n) + '.log';
end;
procedure TDebugManager.FindFirstLogFileName;
var
FSelectedTime: TDateTime;
i: Integer;
f: TSearchRec;
begin
FSelectedTime := MaxDateTime;
FDebugLogIndex := 0;
for i := 0 to MAXDEBUGLOGS - 1 do
begin
if FindFirst(DebugLogFileName(i), 0, f) = 0 then
begin
if f.TimeStamp < FSelectedTime then
begin
FDebugLogIndex := i;
FSelectedTime := f.TimeStamp;
end;
FindClose(f);
end
else
begin
FDebugLogIndex := i;
Break;
end;
end;
Dec(FDebugLogIndex); // It will be immediately incremented by StartNewLogFile
end;
procedure TDebugManager.StartNewLogFile;
var
FDebugLogFileName: WideString;
begin
if hLogFile <> 0 then
CloseHandle(hLogFile);
Inc(FDebugLogIndex);
if FDebugLogIndex > MAXDEBUGLOGS then
FDebugLogIndex := 0;
FDebugLogFileName := 'system' + IntToStr(FDebugLogIndex) + '.log';
hLogFile := CreateFile(PChar(DebugLogFileName(FDebugLogIndex)), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, 0, 0);
if hLogFile = INVALID_HANDLE_VALUE then RaiseLastOSError;
WriteHeadingString;
end;
procedure TDebugManager.Execute;
var
szBuffer, cbMessage, cMessage, cbRead: DWord;
lpszBuffer: PAnsiChar; // I3310
ov: TOverlapped;
begin
//
try
cbMessage := 0;
cMessage := 0;
cbRead := 0;
szBuffer := 0;
lpszBuffer := nil;
ov.Offset := 0;
ov.OffsetHigh := 0;
ov.hEvent := hEvent;
try
repeat
if not GetMailslotInfo(hMailSlot, // mailslot handle
nil, // no maximum message size
cbMessage, // size of next message
@cMessage, // number of messages
nil) then // no read time-out
RaiseLastOSError;
if cbMessage = MAILSLOT_NO_MESSAGE then { Sleep 10 msec }
begin
Sleep(10);
Continue;
end;
while (cMessage > 0) and not Terminated do // retrieve all messages
begin
if szBuffer < cbMessage then
begin
if Assigned(lpszBuffer) then FreeMem(lpszBuffer);
lpszBuffer := AllocMem(cbMessage);
end;
if not Assigned(lpszBuffer) then
raise Exception.Create('Invalid buffer');
lpszBuffer^ := #0;
if not ReadFile(hMailSlot,
lpszBuffer^,
cbMessage,
cbRead,
@ov) then
RaiseLastOSError;
WriteMessage(lpszBuffer, cbRead - 1); // Ignore terminating nul
// Concatenate the message and the message-number string.
if not GetMailslotInfo(hMailSlot, // mailslot handle
nil, // no maximum message size
cbMessage, // size of next message
@cMessage, // number of messages
nil) then // no read time-out
RaiseLastOSError;
end;
until Terminated;
finally
if Assigned(lpszBuffer) then FreeMem(lpszBuffer);
end;
except
on E:Exception do
WriteString(hLogFile, '*** Exception '+E.ClassName+' in TDebugManager: '+E.Message);
end;
end;
procedure TDebugManager.WriteHeadingString;
begin
WriteRawString(hLogFile, // I3656
'Platform' + #9 +
'Process' + #9 +
'PID' + #9 +
'TID' + #9 +
//'QueueStatus' + #9 +
'ShiftState' + #9 +
'ActualShiftState' + #9 + // I4843
'TickCount' + #9 +
//'LogHWND' + #9 +
//'LogWindowClassName' + #9 +
//'LogWindowText' + #9 +
'FocusHWND' + #9 +
//'FocusWindowClassName' + #9 +
//'FocusWindowText' + #9 +
//'ActiveHWND' + #9 +
//'ActiveWindowClassName' + #9 +
//'ActiveWindowText' + #9 +
//'ForegroundHWND' + #9 + // I2690
//'MessageType' + #9 +
//'SourceLine' + #9 +
'ActiveHKL' + #9 +
'SourceFile' + #9 +
'Message');
WriteString(hLogFile, '---- Log file opened '+FormatDateTime('C', now) + '----');
end;
var
hLogMailSlot: THandle = 0;
hLogEvent: THandle = 0;
class procedure TDebugManager.WriteLastError(const ParentMethod, FailingMethod: string; const Message: string = '');
var
FLastError: DWord;
FLastErrorString: string;
begin
FLastError := GetLastError;
FLastErrorString := SysErrorMessage(GetLastError);
WriteMessage('ERROR %d in %s [%s]: %s %s', [FLastError, FailingMethod, ParentMethod, FLastErrorString, Message]);
end;
class procedure TDebugManager.WriteMessage(const Format: string;
const Args: array of const);
var
bufa: ansistring;
buf: string;
ov: OVERLAPPED;
cbWritten: DWORD;
gti: TGUIThreadInfo;
begin
if not ShouldDebug then Exit;
if hLogMailSlot = 0 then
begin
hLogMailSlot := CreateFile('\\.\mailslot\Tavultesoft_KeymanEngine_Debug',
GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, // required to write to a mailslot
nil,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL,
0);
hLogEvent := CreateEvent(nil, False, False, 'Tavultesoft_KeymanEngine_DebugWrite');
if hLogMailSlot = 0 then Exit;
if hLogEvent = 0 then Exit;
end;
gti.cbSize := SizeOf(TGUIThreadInfo); // I2690
GetGUIThreadInfo(0, gti);
buf :=
SysUtils.Format( // I3656
'x86' + #9 +
'keyman[host]' + #9 +
'%x' + #9 +
'%x' + #9 +
//'' + #9 +
'' + #9 + // shift state
'' + #9 + // actual shift state // I4843
IntToStr(GetTickCount) + #9 +
//'' + #9 +
//'' + #9 +
//'' + #9 +
'%x' + #9 +
//'' + #9 +
//'' + #9 +
//'%x' + #9 +
//'' + #9 +
//'' + #9 +
//'%x' + #9 +
//'' + #9 +
//'' + #9 + // I3692
'' + #9 +
'' + #9,
[GetCurrentProcessId,
GetCurrentThreadId,
gti.hwndFocus
//gti.hwndActive,
{GetForegroundWindow}]) +
SysUtils.Format(Format, Args);
ov.Offset := 0;
ov.OffsetHigh := 0;
ov.hEvent := hLogEvent;
bufa := String_UtoA(buf); // I3601
WriteFile(hLogMailSlot,
bufa[1], // I3601
Length(bufa) + 1,
cbWritten,
@ov);
end;
procedure TDebugManager.WriteMessage(buf: PAnsiChar; buflen: Integer); // I3310
var
Control: AnsiChar; // I3310
begin
if (buflen > 0) then Control := buf[0] else Control := #0;
if Control = '*' then
begin
if FOwner <> 0 then
begin
if PostMessage(FOwner, WM_USER_DebugNotify, FDebugLogIndex, hLogFile) then
hLogFile := 0;
end;
StartNewLogFile;
end
else
begin
if Assigned(FOnMessage) then
begin
FOnMessage(Self, string(Copy(buf, 1, buflen) + crlf));
end;
WriteMessage(hLogFile, buf, buflen);
end;
end;
class procedure TDebugManager.WriteString(Handle: THandle; const s: string);
var
gti: TGUIThreadInfo;
begin
gti.cbSize := SizeOf(TGUIThreadInfo);
GetGUIThreadInfo(0, gti); // I2690
WriteRawString(Handle, // I3656
SysUtils.Format(
'x86' + #9 +
'keyman[host]' + #9 +
'%x' + #9 +
'%x' + #9 +
//'' + #9 +
'' + #9 + // shift state
'' + #9 + // actual shift state // I4843
IntToStr(GetTickCount) + #9 +
//'' + #9 +
//'' + #9 +
//'' + #9 +
'%x' + #9 +
//'' + #9 +
//'' + #9 +
//'%x' + #9 +
//'' + #9 +
//'' + #9 +
//'%x' + #9 +
//'' + #9 +
//'' + #9 + // I3692
'' + #9 +
'' + #9,
[GetCurrentProcessId,
GetCurrentThreadId,
gti.hwndFocus {,
gti.hwndActive,
GetForegroundWindow}]) +
s);
end;
class procedure TDebugManager.WriteRawString(Handle: THandle; const s: string);
var
sa: AnsiString; // I3310
begin
sa := String_UtoA(s); // I3310
WriteMessage(Handle, PAnsiChar(sa), Length(sa));
end;
class procedure TDebugManager.WriteMessage(Handle: THandle; buf: PAnsiChar; buflen: Integer); // I3310
var
n: DWord;
begin
if Handle = 0 then Exit;
WriteFile(Handle, buf^, buflen, n, nil);
WriteFile(Handle, PAnsiChar(crlf)^, 2, n, nil); // I3601
end;
procedure CloseHandles; // I2691
begin
if hLogEvent <> 0 then CloseHandle(hLogEvent);
if hLogMailSlot <> 0 then CloseHandle(hLogMailSlot);
hLogMailSlot := 0;
hLogEvent := 0;
end;
initialization
finalization
FTerminating := True;
if Assigned(FDebugManager) then // I2446 - Keyman Engine crashes due to debug manager being freed late
FDebugManager.Terminate;
FreeAndNil(FDebugManager);
CloseHandles; // I2691
end.

View file

@ -0,0 +1,141 @@
unit Keyman.System.DebugLogClient;
interface
uses
Winapi.Windows,
JwaEventDefs,
JwaEventTracing,
JwaEvntProv;
type
TDebugLogClient = class
private
FRegHandle: TRegHandle;
class var FInstance: TDebugLogClient;
public
constructor Create;
destructor Destroy; override;
procedure WriteLastError(const ParentMethod, FailingMethod: string; const Message: string = '');
procedure WriteMessage(const Format: string; const Args: array of const);
class function Instance: TDebugLogClient;
end;
implementation
uses
System.SysUtils,
Keyman.System.DebugLogCommon;
{ TDebugLogClient }
const
// This comes from keyman-debug-etw.h. If the event descriptor is ever changed,
// then this needs to be updated.
DebugEvent: EVENT_DESCRIPTOR = (
Id : $1;
Version : $0;
Channel : $10;
Level : $4;
Opcode : $0;
Task : $0;
Keyword : $8000000000000000
);
constructor TDebugLogClient.Create;
var
status: ULONG;
begin
if ShouldDebug then
begin
status := EventRegister(@DebugLogProviderGuid, nil, nil, FRegHandle);
if ERROR_SUCCESS <> status then
begin
FRegHandle := 0;
RaiseLastOSError(status, 'EventRegister');
end;
end;
end;
destructor TDebugLogClient.Destroy;
var
status: ULONG;
begin
if FRegHandle <> 0 then
begin
status := EventUnregister(FRegHandle);
if ERROR_SUCCESS <> status then
OutputDebugString(PChar('EventUnregister failed with '+IntToStr(status)));
end;
inherited Destroy;
end;
class function TDebugLogClient.Instance: TDebugLogClient;
begin
if not Assigned(FInstance) then
FInstance := TDebugLogClient.Create;
Result := FInstance;
end;
procedure TDebugLogClient.WriteLastError(const ParentMethod,
FailingMethod, Message: string);
var
FLastError: DWord;
FLastErrorString: string;
begin
FLastError := GetLastError;
FLastErrorString := SysErrorMessage(GetLastError);
WriteMessage('ERROR %d in %s [%s]: %s %s', [FLastError, FailingMethod, ParentMethod, FLastErrorString, Message]);
end;
procedure TDebugLogClient.WriteMessage(const Format: string;
const Args: array of const);
const
MAX_DESCRIPTORS = 12;
var
Descriptors: array[0..MAX_DESCRIPTORS-1] of EVENT_DATA_DESCRIPTOR;
dwPlatform: DWORD;
sDummy, sMsg, sProcessName: string;
pid, tid: DWORD;
dwTickCount, dwDummy: DWORD;
status: ULONG;
begin
if not ShouldDebug then
Exit;
pid := GetCurrentProcessId;
tid := GetCurrentThreadId;
dwTickCount := GetTickCount;
dwPlatform := 1; // x86
dwDummy := 0;
sProcessName := 'keyman[host]';
sMsg := System.SysUtils.Format(Format, Args);
// These must match the manifest template in keyman-debug-etw.man
EventDataDescCreate(Descriptors[0], @dwPlatform, sizeof(DWORD)); // <data name = "Platform" inType = "Platform" / >
EventDataDescCreate(&Descriptors[1], PChar(sProcessName), (Length(sProcessName) + 1) * sizeof(WCHAR)); // <data name = "Process" inType = "win:UnicodeString" / >
EventDataDescCreate(&Descriptors[2], @pid, sizeof(DWORD)); // <data name = "PID" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[3], @tid, sizeof(DWORD)); // <data name = "TID" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[4], @dwDummy, sizeof(DWORD)); // <data name = "ShiftState" inType = "ShiftState" / >
EventDataDescCreate(&Descriptors[5], @dwDummy, sizeof(DWORD)); // <data name = "ActualShiftState" inType = "ShiftState" / >
EventDataDescCreate(&Descriptors[6], @dwTickCount, sizeof(DWORD)); // <data name = "TickCount" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[7], @dwDummy, sizeof(DWORD)); // <data name = "FocusHWND" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[8], @dwDummy, sizeof(DWORD)); // <data name = "ActiveHKL" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[9], PChar(sDummy), sizeof(WCHAR)); // <data name = "SourceFile" inType = "win:UnicodeString" / >
EventDataDescCreate(&Descriptors[10], @dwDummy, sizeof(DWORD)); // <data name = "SourceLine" inType = "win:UInt32" / >
EventDataDescCreate(&Descriptors[11], PChar(sMsg), (Length(sMsg)+1) * sizeof(WCHAR)); // <data name = "Message" inType = "win:UnicodeString" / >
status := EventWrite(FRegHandle, @DebugEvent, MAX_DESCRIPTORS, @Descriptors[0]);
if ERROR_SUCCESS <> status then
OutputDebugString(PChar('EventWrite failed with '+IntToStr(status)));
end;
initialization
finalization
FreeAndNil(TDebugLogClient.FInstance);
end.

View file

@ -0,0 +1,36 @@
unit Keyman.System.DebugLogCommon;
interface
const
// GUID that identifies the provider that you want
// to enable to your session.
DebugLogProviderGuid: TGUID = '{DA621615-E08B-4283-918E-D2502D3757AE}';
function ShouldDebug: Boolean;
implementation
uses
System.Win.Registry,
RegistryKeys;
var
FShouldDebug: Boolean;
function ShouldDebug: Boolean;
begin
Result := FShouldDebug;
end;
initialization
with TRegistry.Create do // I2890
try
if OpenKeyReadOnly(SRegKey_KeymanEngine_CU) and ValueExists(SRegValue_KeymanDebug)
then FShouldDebug := ReadBool(SRegValue_KeymanDebug)
else FShouldDebug := False;
finally
Free;
end;
end.

View file

@ -0,0 +1,289 @@
(*
Name: DebugManager
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 - Initial version
04 Jan 2007 - mcdurdin - Add ShouldDebug function
19 Jun 2007 - mcdurdin - Widestring it
19 Nov 2007 - mcdurdin - I1157 - const string parameters
04 May 2010 - mcdurdin - I2348 - Rework columns in debug log
04 May 2010 - mcdurdin - I2349 - Hotkey to capture debug log
04 May 2010 - mcdurdin - I2350 - Keyman.exe should be able to report events in debug log
04 May 2010 - mcdurdin - I2352 - Debug logging not reliable in some apps due to security
15 Jun 2010 - mcdurdin - I2423 - Fix crash in debug manager
24 Jun 2010 - mcdurdin - I2422 - Recreate, not rewrite existing log files
29 Jun 2010 - mcdurdin - I2446 - Keyman Engine crashes due to debug manager being freed late
17 Dec 2010 - mcdurdin - Add extra column to raw strings
11 Jan 2011 - mcdurdin - I2640 - Raise error at appropriate location so it isn't masked by cascading issue
31 Jan 2011 - mcdurdin - I2685 - Reduce registry noise from ShouldDebug function
31 Jan 2011 - mcdurdin - I2690 - Add foreground window info to debug log
31 Jan 2011 - mcdurdin - I2691 - Fix handle leaks
18 Feb 2011 - mcdurdin - I2685 : 9827 - Fix shoulddebug refresh counter not resetting
03 May 2011 - mcdurdin - I2890 - Record diagnostic data when encountering registry errors
18 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls + Win9x support
08 Jun 2012 - mcdurdin - I3310 - V9.0 - Unicode in Delphi fixes
28 Nov 2012 - mcdurdin - I3601 - V9.0 - Debug messages were written partially Unicode, partially ANSI
13 Dec 2012 - mcdurdin - I3656 - V9.0 - Debug logs show too many columns for host messages
01 Jan 2013 - mcdurdin - I3692 - V9.0 - [host] entries in system.log out by 1 tabstop
09 Aug 2015 - mcdurdin - I4843 - Log reported modifier state as well as Keyman current modifier state
*)
unit Keyman.System.DebugLogManager; // I3306
interface
uses
System.Classes,
System.SysUtils,
Winapi.Windows,
JwaWmiStr,
JwaEventTracing,
Keyman.System.DebugLogCommon,
UserMessages;
type
TDebugLogManager = class
private
FOwner: HWND;
FDebugLogIndex: Integer;
FDebugLogFileName: string;
pSessionProperties: PEVENT_TRACE_PROPERTIES;
FSessionHandle: TRACEHANDLE;
FTraceRunning: Boolean;
procedure StartNewLogFile;
procedure FindFirstLogFileName;
function DebugLogFileName(n: Integer): string;
public
constructor Create(AOwner: HWND); reintroduce;
destructor Destroy; override;
end;
function GetDebugManager(AOwner: HWND): TDebugLogManager;
implementation
uses
Accctrl,
AclApi,
ErrorControlledRegistry,
ErrLogPath,
RegistryKeys,
Unicode;
var
FDebugManager: TDebugLogManager = nil;
FTerminating: Boolean = False;
FShouldDebug: Boolean = False;
FShouldDebugLastTick: Cardinal = 0;
const
// GUID that identifies your trace session.
// Remember to create your own session GUID.
SessionGuid: TGUID = '{FADEA67E-0EE9-452B-AF04-22E342D1227A}';
function GetDebugManager(AOwner: HWND): TDebugLogManager;
begin
Assert(not FTerminating);
if ShouldDebug then
begin
if not Assigned(FDebugManager) then
FDebugManager := TDebugLogManager.Create(AOwner);
Result := FDebugManager;
end
else
Result := nil;
end;
{ TDebugManager }
const LOGSESSION_NAME: string = 'Keyman Event Trace Session';
function StringBufferSize(const s: string): Integer;
begin
Result := (Length(s) + 1) * sizeof(WCHAR);
end;
constructor TDebugLogManager.Create(AOwner: HWND);
var
BufferSize: ULONG;
status: ULONG;
// BOOL TraceOn = TRUE;
// BOOL bTraceAlreadyStarted = FALSE;
begin
FOwner := AOwner;
FindFirstLogFileName;
StartNewLogFile;
// Allocate memory for the session properties. The memory must
// be large enough to include the log file name and session name,
// which get appended to the end of the session properties structure.
BufferSize := sizeof(EVENT_TRACE_PROPERTIES) + StringBufferSize(FDebugLogFileName) + StringBufferSize(LOGSESSION_NAME);
pSessionProperties := PEVENT_TRACE_PROPERTIES(AllocMem(BufferSize));
// Set the session properties. You only append the log file name
// to the properties structure; the StartTrace function appends
// the session name for you.
pSessionProperties.Wnode.BufferSize := BufferSize;
pSessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID;
pSessionProperties.Wnode.ClientContext := 1; //QPC clock resolution
pSessionProperties.Wnode.Guid := SessionGuid;
pSessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_SEQUENTIAL;
pSessionProperties.MaximumFileSize := 1; // 1 MB
pSessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES);
pSessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGSESSION_NAME);
StrPCopy(PWideChar(PByte(pSessionProperties) + pSessionProperties.LoggerNameOffset), LOGSESSION_NAME);
StrPCopy(PWideChar(PByte(pSessionProperties) + pSessionProperties.LogFileNameOffset), FDebugLogFileName);
// StringCbCopy((LPWSTR)((char*)pSessionProperties + pSessionProperties->LogFileNameOffset), sizeof(LOGFILE_PATH), LOGFILE_PATH);
status := StartTrace(@FSessionHandle, PWideChar(LOGSESSION_NAME), pSessionProperties^);
if ERROR_ALREADY_EXISTS = status then
begin
// The trace was already started, perhaps Keyman did not close down cleanly
// We'll stop it and restart it
status := ControlTraceW(FSessionHandle, PWideChar(LOGSESSION_NAME), pSessionProperties^, EVENT_TRACE_CONTROL_STOP);
if ERROR_SUCCESS <> status then
OutputDebugString(PChar('ControlTrace failed with '+IntToStr(status)));
status := StartTrace(@FSessionHandle, PWideChar(LOGSESSION_NAME), pSessionProperties^);
end;
if ERROR_SUCCESS <> status then
RaiseLastOSError(status, 'StartTrace');
// Enable the providers that you want to log events to your session.
status := EnableTraceEx(
@DebugLogProviderGuid,
@SessionGuid,
FSessionHandle,
1, // Enable
TRACE_LEVEL_INFORMATION,
0,
0,
0,
nil
);
if ERROR_SUCCESS <> status then
RaiseLastOSError(status, 'EnableTraceEx');
FTraceRunning := True;
end;
destructor TDebugLogManager.Destroy;
var
status: ULONG;
begin
if FSessionHandle <> 0 then
begin
if FTraceRunning then
begin
status := EnableTraceEx(
@DebugLogProviderGuid,
@SessionGuid,
FSessionHandle,
0, // Disable
TRACE_LEVEL_INFORMATION,
0,
0,
0,
nil
);
if ERROR_SUCCESS <> status then
OutputDebugString(PChar('EnableTraceEx(FALSE) failed with '+IntToStr(status)));
FTraceRunning := False;
end;
// We use ControlTraceW because JwaEventTracing has a typo for ControlTrace
status := ControlTraceW(FSessionHandle, PWideChar(LOGSESSION_NAME), pSessionProperties^, EVENT_TRACE_CONTROL_STOP);
if ERROR_SUCCESS <> status then
OutputDebugString(PChar('ControlTrace failed with '+IntToStr(status)));
FSessionHandle := 0;
end;
if pSessionProperties <> nil then
begin
FreeMem(pSessionProperties);
pSessionProperties := nil;
end;
inherited Destroy;
end;
const
MAXDEBUGLOGS = 16;
function TDebugLogManager.DebugLogFileName(n: Integer): string;
begin
Result := GetErrLogPath + 'system' + IntToStr(n) + '.etl';
end;
procedure TDebugLogManager.FindFirstLogFileName;
var
FSelectedTime: TDateTime;
i: Integer;
f: TSearchRec;
begin
FSelectedTime := MaxDateTime;
FDebugLogIndex := 0;
for i := 0 to MAXDEBUGLOGS - 1 do
begin
if FindFirst(DebugLogFileName(i), 0, f) = 0 then
begin
if f.TimeStamp < FSelectedTime then
begin
FDebugLogIndex := i;
FSelectedTime := f.TimeStamp;
end;
System.SysUtils.FindClose(f);
end
else
begin
FDebugLogIndex := i;
Break;
end;
end;
Dec(FDebugLogIndex); // It will be immediately incremented by StartNewLogFile
end;
procedure TDebugLogManager.StartNewLogFile;
begin
Inc(FDebugLogIndex);
if FDebugLogIndex > MAXDEBUGLOGS then
FDebugLogIndex := 0;
FDebugLogFileName := DebugLogFileName(FDebugLogIndex);
if FileExists(FDebugLogFileName) then
System.SysUtils.DeleteFile(FDebugLogFileName);
end;
initialization
finalization
FTerminating := True;
FreeAndNil(FDebugManager);
end.

View file

@ -1,74 +0,0 @@
(*
Name: SystemDebugPath
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 4 Dec 2006
Modified Date: 26 Jun 2012
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 04 Dec 2006 - mcdurdin - Initial version
19 Jun 2007 - mcdurdin - Widestrings
03 May 2011 - mcdurdin - I2890 - Record diagnostic data when encountering registry errors
04 May 2012 - mcdurdin - I3306 - V9.0 - Remove TntControls
26 Jun 2012 - mcdurdin - I3379 - KM9 - Remove old Winapi references now in Delphi libraries
*)
unit SystemDebugPath; // I3306
interface
function GetSystemDebugPath: WideString;
implementation
uses
ActiveX, ShellApi, ShlObj, ErrorControlledRegistry, SysUtils, Windows;
function GetFolderPath(csidl: Integer): WideString;
var
buf: array[0..260] of WideChar;
idl: PItemIDList;
mm: IMalloc;
begin
Result := '';
if SHGetMalloc(mm) = NOERROR then
begin
if SHGetSpecialFolderLocation(0, csidl, idl) = NOERROR then
begin
if SHGetPathFromIDList(idl, buf) then
begin
Result := Buf;
end;
mm.Free(idl);
end;
mm._Release;
end;
if (Result = '') and (csidl = CSIDL_PROGRAM_FILES) then
with TRegistryErrorControlled.Create do // I2890
try
RootKey := HKEY_LOCAL_MACHINE;
if not OpenKeyReadOnly('Software\Microsoft\Windows\CurrentVersion') then // I2890
RaiseLastRegistryError;
Result := ReadString('ProgramFilesDir');
finally
Free;
end;
if Result <> '' then Result := IncludeTrailingPathDelimiter(Result);
if Result[Length(Result)] <> '\' then Result := Result + '\';
end;
function GetSystemDebugPath: WideString;
begin
Result := GetFolderPath(CSIDL_DESKTOPDIRECTORY) + 'keymanlog';
if not DirectoryExists(Result) then CreateDir(Result); // assumes write permissions!
Result := Result + '\';
end;
end.

View file

@ -32,7 +32,6 @@ const
WM_USER_ParameterPass = WM_USER+100;
WM_USER_SendFontChange = WM_USER+102;
WM_USER_PlatformComms = WM_USER+103;
WM_USER_DebugNotify = WM_USER+104;
WM_USER_VisualKeyboardClosed = WM_USER+105; // I4242
const