⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stexpeng.pas

📁 条码控件: 一维条码控件 二维条码控件 PDF417Barcode MaxiCodeBarcode
💻 PAS
字号:
(* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is TurboPower SysTools
 *
 * The Initial Developer of the Original Code is
 * TurboPower Software
 *
 * Portions created by the Initial Developer are Copyright (C) 1996-2002
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** *)

{*********************************************************}
{* SysTools: StExpLog.pas 4.03                           *}
{*********************************************************}
{* SysTools: Exception Logging                           *}
{*********************************************************}

{$I StDefine.inc}

unit StExpEng;

interface

uses
  Windows, SysUtils, Classes, StBase, StExpLog;

const
  OnHookInstaller : procedure = nil;

procedure DumpException;

implementation

uses
  Forms;

const
  MaxStackSize  = 48;

type
  TStExceptionHandler = class
  private
    OldOnException : TExceptionEvent;
  protected
    procedure OnException(Sender : TObject; E : Exception);
  end;

  TStExceptionTrace = record
    Count : Integer;
    Trace : array[0..pred(MaxStackSize)] of DWORD;
  end;

const
  EH : TStExceptionHandler = nil;
  WroteInfo : Boolean = False;
  HandlerInstalled : Boolean = False;
  cDelphiException = DWORD($0EEDFADE);
  cCppException = DWORD($0EEFFACE); { used by BCB }

var
  RA2 : procedure (dwExceptionCode, dwExceptionFlags, nNumberOfArguments : DWORD;
    const lpArguments : DWORD); stdcall;
  BaseOfCode, TopOfCode : DWORD;

{ Writes exception to log file }
procedure WriteException(E : Exception);
var
  p1 : Integer;
  RipFileName, S : string;
  FS : TFileStream;
  Buffer : array[0..255] of AnsiChar;
begin
  if Assigned(ExpLog) then
    RipFileName := ExpLog.FileName;

  if RipFileName = '' then begin
    GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
    RipFileName := ChangeFileExt(PChar(@Buffer),'.RIP');
  end;

  { Open file stream }
  if FileExists(RipFileName) then begin
    FS := TFileStream.Create(RipFileName, fmOpenReadWrite or fmShareDenyWrite);
    FS.Seek(0, soFromEnd);
    S := #13#10#13#10;
    FS.Write(S[1], Length(S));
  end else begin
    FS := TFileStream.Create(RipFileName, fmCreate or fmShareDenyWrite);
  end;

  try
    { Write info if necessary }
    if not WroteInfo and Assigned(ExpLog) then begin
      if (ExpLog.RipInfo <> '') then begin
        S := ExpLog.RipInfo + #13#10#13#10;
        FS.Write(S[1], Length(S));
      end;
      WroteInfo := True;
    end;

    { Write dump info from E.Message }
    p1 := Pos(#0, E.Message);
    S := Copy(E.Message, p1+1, MaxInt) + #13#10;
    FS.Write(S[1], Length(S));

    { Restore E.Message }
    S := E.Message;
    SetLength(S, P1-1);
    E.Message := S;

  finally
    FS.Free;
  end;
end;

{ Dumps Exception }
procedure DumpException;
var
  PutInLog : Boolean;
begin
  PutInLog := True;
  if Assigned(ExpLog) then
    ExpLog.DoExceptionFilter(Exception(ExceptObject),PutInLog);
  if PutInLog then
    WriteException(Exception(ExceptObject));
end;

{ TStExceptionHandler }

procedure TStExceptionHandler.OnException(Sender : TObject; E : Exception);
begin
  DumpException;
  if Assigned(OldOnException) then
    OldOnException(Sender, E)
  else
    Application.ShowException(Exception(ExceptObject));
end;

var
  SaveGetExceptionObject : function(P : PExceptionRecord) : Exception;

procedure HookInstaller;
begin
  EH := TStExceptionHandler.Create;
  EH.OldOnException := Application.OnException;
  Application.OnException := EH.OnException;
end;

procedure StackDump(E : Exception; Root : DWORD);
var
  P : PDWORD;
  C, D, StackTop, N, Prev : DWORD;
  Trace : TStExceptionTrace;
  I : Integer;
  Store : Boolean;
  MsgPtr : PChar;
  MsgLen : Integer;
begin
  if not HandlerInstalled then begin
    if Assigned(OnHookInstaller) then
      OnHookInstaller;
    HandlerInstalled := True;
  end;

  if Root = 0 then
    Trace.Count := 0
  else begin
    Trace.Count := 1;
    Trace.Trace[0] := Root;
  end;

  asm
    mov P,ebp
    mov eax,fs:[4]
    mov [StackTop],eax
  end;

  Prev := 0;
  C := 0;

  while DWORD(P) < DWORD(StackTop) do begin
    D := P^;
    N := 0;
    if (D >= BaseOfCode) and (D < TopOfCode) then
      if (PByte(D-5)^ = $E8)
      or ((PByte(D-6)^ = $FF) and (((PByte(D-5)^ and $38) = $10)))
      or ((PByte(D-4)^ = $FF) and (((PByte(D-3)^ and $38) = $10)))
      or ((PByte(D-3)^ = $FF) and (((PByte(D-2)^ and $38) = $10)))
      or ((PByte(D-2)^ = $FF) and (((PByte(D-1)^ and $38) = $10))) then
        N := D-BaseOfCode;
    if (N <> 0) and (N <> Prev) then begin
     if (Root = 0) then
        Store := C > 0
      else
        Store := C > 1;
      if Store then
        begin
          Trace.Trace[Trace.Count] := N;
          Inc(Trace.Count);
        end;
      Inc(C);
      if C > MaxStackSize then Break;
      Prev := N;
    end;
    Inc(P);
  end;

  if C > 0 then begin
    MsgPtr := PChar(E.Message);
    MsgLen := StrLen(MsgPtr);
    if (MsgLen <> 0) and (MsgPtr[MsgLen - 1] <> '.') then
      E.Message := E.Message + '.';
    E.Message := E.Message  + #0 + Format('Fault : %s'#13#10'Date/time : %s %s'#13#10'Stack dump'#13#10+
      '----------'#13#10,[E.Message,DateToStr(Now),TimeToStr(Now)]);
    for i := 0 to pred(Trace.Count) do
      E.Message := E.Message + Format('%8.8x'#13#10,[Trace.Trace[i]]);
  end;
end;

procedure LRE(dwExceptionCode, dwExceptionFlags, nNumberOfArguments : DWORD;
  const lpArguments : DWORD); stdcall;
var
  E : Exception;
begin
  if (dwExceptionCode = cDelphiException) or (dwExceptionCode = cCppException) then begin
    asm
      push ebx
      mov  ebx,lpArguments
      mov  eax,ss:[ebx+4]
      mov  E,eax
      pop  ebx
    end;
    if assigned(E) then
      StackDump(E, 0);
  end;
  if Assigned(RA2) then
    RA2(dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
end;

function HookGetExceptionObject(P : PExceptionRecord) : Exception;
begin
  Result := SaveGetExceptionObject(P);
  StackDump(Result, DWORD(P^.ExceptionAddress)-BaseOfCode);
end;

procedure InitializeEng;
const
  ImageNumberofDirectoryEntries = 16;
  ImageDirectoryEntryImport     = 1;

type

  PImageImportByName = ^TImageImportByName;
  TImageImportByName = packed record
    Hint : WORD;
    Name : array[0..255] of char;
  end;

  PImageThunkData = ^TImageThunkData;
  TImageThunkData = packed record
    case Integer of
    1 : (Funct : ^DWORD);
    2 : (Ordinal : DWORD);
    3 : (AddressOfData : PImageImportByName);
  end;

  PImageImportDescriptor = ^TImageImportDescriptor;
  TImageImportDescriptor = packed record
    Characteristics : DWORD;
    TimeDateStamp : DWORD;
    ForwarderChain : DWORD;
    Name : DWORD;
    FirstThunk : PImageThunkData;
  end;

  PImageDosHeader = ^TImageDosHeader;
  TImageDosHeader = packed record
    e_magic : WORD;
    e_cblp : WORD;
    e_cp : WORD;
    e_crlc : WORD;
    e_cparhdr : WORD;
    e_minalloc : WORD;
    e_maxalloc : WORD;
    e_ss : WORD;
    e_sp : WORD;
    e_csum : WORD;
    e_ip : WORD;
    e_cs : WORD;
    e_lfarlc : WORD;
    e_ovno : WORD;
    e_res : array [0..3] of WORD;
    e_oemid : WORD;
    e_oeminfo : WORD;
    e_res2 : array [0..9] of WORD;
    e_lfanew : DWORD;
  end;

var
  OriginalProc : Pointer;
  NTHeader : PImageNTHeaders;
  ImportDesc : PImageImportDescriptor;
  Thunk : PImageThunkData;

begin
  RA2 := nil;
  OriginalProc := GetProcAddress(GetModuleHandle('kernel32.dll'), 'RaiseException');

  if OriginalProc <> nil then begin
    NTHeader := PImageNTHeaders(DWORD(hInstance) + PImageDosHeader(hInstance).e_lfanew);
    ImportDesc := PImageImportDescriptor(DWORD(hInstance) +
      NTHeader.OptionalHeader.DataDirectory[ImageDirectoryEntryImport].VirtualAddress);

    BaseOfCode := DWORD(hInstance) + NTHeader.OptionalHeader.BaseOfCode;
    TopOfCode := BaseOfCode + NTHeader.OptionalHeader.SizeOfCode;

    while ImportDesc.Name <> 0 do begin
      if StriComp(PChar(DWORD(hInstance) + ImportDesc.Name), 'kernel32.dll') = 0 then begin
        Thunk := PImageThunkData(DWORD(hInstance) + DWORD(ImportDesc.FirstThunk));
        while Thunk.Funct <> nil do begin
          if Thunk.Funct = OriginalProc then
            Thunk.Funct := @LRE;
          Inc(Thunk);
        end;
      end;
      Inc(ImportDesc);
    end;
    RA2 := OriginalProc;
  end;
  SaveGetExceptionObject := ExceptObjProc;
  ExceptObjProc := @HookGetExceptionObject;
end;

initialization
  OnHookInstaller := HookInstaller;
  {$WARNINGS OFF}  { Yeah, we know DebugHook is platform specific }
  if DebugHook = 0 then InitializeEng;
  {$WARNINGS ON}

finalization
  EH.Free;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -