/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StExpEng.pas
ViewVC logotype

Contents of /dao/DelphiScanner/Components/tpsystools_4.04/source/StExpEng.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 9456 byte(s)
Added tpsystools component
1 (* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is TurboPower SysTools
15 *
16 * The Initial Developer of the Original Code is
17 * TurboPower Software
18 *
19 * Portions created by the Initial Developer are Copyright (C) 1996-2002
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * ***** END LICENSE BLOCK ***** *)
25
26 {*********************************************************}
27 {* SysTools: StExpLog.pas 4.03 *}
28 {*********************************************************}
29 {* SysTools: Exception Logging *}
30 {*********************************************************}
31
32 {$I StDefine.inc}
33
34 unit StExpEng;
35
36 interface
37
38 uses
39 Windows, SysUtils, Classes, StBase, StExpLog;
40
41 const
42 OnHookInstaller : procedure = nil;
43
44 procedure DumpException;
45
46 implementation
47
48 uses
49 Forms;
50
51 const
52 MaxStackSize = 48;
53
54 type
55 TStExceptionHandler = class
56 private
57 OldOnException : TExceptionEvent;
58 protected
59 procedure OnException(Sender : TObject; E : Exception);
60 end;
61
62 TStExceptionTrace = record
63 Count : Integer;
64 Trace : array[0..pred(MaxStackSize)] of DWORD;
65 end;
66
67 const
68 EH : TStExceptionHandler = nil;
69 WroteInfo : Boolean = False;
70 HandlerInstalled : Boolean = False;
71 cDelphiException = DWORD($0EEDFADE);
72 cCppException = DWORD($0EEFFACE); { used by BCB }
73
74 var
75 RA2 : procedure (dwExceptionCode, dwExceptionFlags, nNumberOfArguments : DWORD;
76 const lpArguments : DWORD); stdcall;
77 BaseOfCode, TopOfCode : DWORD;
78
79 { Writes exception to log file }
80 procedure WriteException(E : Exception);
81 var
82 p1 : Integer;
83 RipFileName, S : string;
84 FS : TFileStream;
85 Buffer : array[0..255] of AnsiChar;
86 begin
87 if Assigned(ExpLog) then
88 RipFileName := ExpLog.FileName;
89
90 if RipFileName = '' then begin
91 GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
92 RipFileName := ChangeFileExt(PChar(@Buffer),'.RIP');
93 end;
94
95 { Open file stream }
96 if FileExists(RipFileName) then begin
97 FS := TFileStream.Create(RipFileName, fmOpenReadWrite or fmShareDenyWrite);
98 FS.Seek(0, soFromEnd);
99 S := #13#10#13#10;
100 FS.Write(S[1], Length(S));
101 end else begin
102 FS := TFileStream.Create(RipFileName, fmCreate or fmShareDenyWrite);
103 end;
104
105 try
106 { Write info if necessary }
107 if not WroteInfo and Assigned(ExpLog) then begin
108 if (ExpLog.RipInfo <> '') then begin
109 S := ExpLog.RipInfo + #13#10#13#10;
110 FS.Write(S[1], Length(S));
111 end;
112 WroteInfo := True;
113 end;
114
115 { Write dump info from E.Message }
116 p1 := Pos(#0, E.Message);
117 S := Copy(E.Message, p1+1, MaxInt) + #13#10;
118 FS.Write(S[1], Length(S));
119
120 { Restore E.Message }
121 S := E.Message;
122 SetLength(S, P1-1);
123 E.Message := S;
124
125 finally
126 FS.Free;
127 end;
128 end;
129
130 { Dumps Exception }
131 procedure DumpException;
132 var
133 PutInLog : Boolean;
134 begin
135 PutInLog := True;
136 if Assigned(ExpLog) then
137 ExpLog.DoExceptionFilter(Exception(ExceptObject),PutInLog);
138 if PutInLog then
139 WriteException(Exception(ExceptObject));
140 end;
141
142 { TStExceptionHandler }
143
144 procedure TStExceptionHandler.OnException(Sender : TObject; E : Exception);
145 begin
146 DumpException;
147 if Assigned(OldOnException) then
148 OldOnException(Sender, E)
149 else
150 Application.ShowException(Exception(ExceptObject));
151 end;
152
153 var
154 SaveGetExceptionObject : function(P : PExceptionRecord) : Exception;
155
156 procedure HookInstaller;
157 begin
158 EH := TStExceptionHandler.Create;
159 EH.OldOnException := Application.OnException;
160 Application.OnException := EH.OnException;
161 end;
162
163 procedure StackDump(E : Exception; Root : DWORD);
164 var
165 P : PDWORD;
166 C, D, StackTop, N, Prev : DWORD;
167 Trace : TStExceptionTrace;
168 I : Integer;
169 Store : Boolean;
170 MsgPtr : PChar;
171 MsgLen : Integer;
172 begin
173 if not HandlerInstalled then begin
174 if Assigned(OnHookInstaller) then
175 OnHookInstaller;
176 HandlerInstalled := True;
177 end;
178
179 if Root = 0 then
180 Trace.Count := 0
181 else begin
182 Trace.Count := 1;
183 Trace.Trace[0] := Root;
184 end;
185
186 asm
187 mov P,ebp
188 mov eax,fs:[4]
189 mov [StackTop],eax
190 end;
191
192 Prev := 0;
193 C := 0;
194
195 while DWORD(P) < DWORD(StackTop) do begin
196 D := P^;
197 N := 0;
198 if (D >= BaseOfCode) and (D < TopOfCode) then
199 if (PByte(D-5)^ = $E8)
200 or ((PByte(D-6)^ = $FF) and (((PByte(D-5)^ and $38) = $10)))
201 or ((PByte(D-4)^ = $FF) and (((PByte(D-3)^ and $38) = $10)))
202 or ((PByte(D-3)^ = $FF) and (((PByte(D-2)^ and $38) = $10)))
203 or ((PByte(D-2)^ = $FF) and (((PByte(D-1)^ and $38) = $10))) then
204 N := D-BaseOfCode;
205 if (N <> 0) and (N <> Prev) then begin
206 if (Root = 0) then
207 Store := C > 0
208 else
209 Store := C > 1;
210 if Store then
211 begin
212 Trace.Trace[Trace.Count] := N;
213 Inc(Trace.Count);
214 end;
215 Inc(C);
216 if C > MaxStackSize then Break;
217 Prev := N;
218 end;
219 Inc(P);
220 end;
221
222 if C > 0 then begin
223 MsgPtr := PChar(E.Message);
224 MsgLen := StrLen(MsgPtr);
225 if (MsgLen <> 0) and (MsgPtr[MsgLen - 1] <> '.') then
226 E.Message := E.Message + '.';
227 E.Message := E.Message + #0 + Format('Fault : %s'#13#10'Date/time : %s %s'#13#10'Stack dump'#13#10+
228 '----------'#13#10,[E.Message,DateToStr(Now),TimeToStr(Now)]);
229 for i := 0 to pred(Trace.Count) do
230 E.Message := E.Message + Format('%8.8x'#13#10,[Trace.Trace[i]]);
231 end;
232 end;
233
234 procedure LRE(dwExceptionCode, dwExceptionFlags, nNumberOfArguments : DWORD;
235 const lpArguments : DWORD); stdcall;
236 var
237 E : Exception;
238 begin
239 if (dwExceptionCode = cDelphiException) or (dwExceptionCode = cCppException) then begin
240 asm
241 push ebx
242 mov ebx,lpArguments
243 mov eax,ss:[ebx+4]
244 mov E,eax
245 pop ebx
246 end;
247 if assigned(E) then
248 StackDump(E, 0);
249 end;
250 if Assigned(RA2) then
251 RA2(dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
252 end;
253
254 function HookGetExceptionObject(P : PExceptionRecord) : Exception;
255 begin
256 Result := SaveGetExceptionObject(P);
257 StackDump(Result, DWORD(P^.ExceptionAddress)-BaseOfCode);
258 end;
259
260 procedure InitializeEng;
261 const
262 ImageNumberofDirectoryEntries = 16;
263 ImageDirectoryEntryImport = 1;
264
265 type
266
267 PImageImportByName = ^TImageImportByName;
268 TImageImportByName = packed record
269 Hint : WORD;
270 Name : array[0..255] of char;
271 end;
272
273 PImageThunkData = ^TImageThunkData;
274 TImageThunkData = packed record
275 case Integer of
276 1 : (Funct : ^DWORD);
277 2 : (Ordinal : DWORD);
278 3 : (AddressOfData : PImageImportByName);
279 end;
280
281 PImageImportDescriptor = ^TImageImportDescriptor;
282 TImageImportDescriptor = packed record
283 Characteristics : DWORD;
284 TimeDateStamp : DWORD;
285 ForwarderChain : DWORD;
286 Name : DWORD;
287 FirstThunk : PImageThunkData;
288 end;
289
290 PImageDosHeader = ^TImageDosHeader;
291 TImageDosHeader = packed record
292 e_magic : WORD;
293 e_cblp : WORD;
294 e_cp : WORD;
295 e_crlc : WORD;
296 e_cparhdr : WORD;
297 e_minalloc : WORD;
298 e_maxalloc : WORD;
299 e_ss : WORD;
300 e_sp : WORD;
301 e_csum : WORD;
302 e_ip : WORD;
303 e_cs : WORD;
304 e_lfarlc : WORD;
305 e_ovno : WORD;
306 e_res : array [0..3] of WORD;
307 e_oemid : WORD;
308 e_oeminfo : WORD;
309 e_res2 : array [0..9] of WORD;
310 e_lfanew : DWORD;
311 end;
312
313 var
314 OriginalProc : Pointer;
315 NTHeader : PImageNTHeaders;
316 ImportDesc : PImageImportDescriptor;
317 Thunk : PImageThunkData;
318
319 begin
320 RA2 := nil;
321 OriginalProc := GetProcAddress(GetModuleHandle('kernel32.dll'), 'RaiseException');
322
323 if OriginalProc <> nil then begin
324 NTHeader := PImageNTHeaders(DWORD(hInstance) + PImageDosHeader(hInstance).e_lfanew);
325 ImportDesc := PImageImportDescriptor(DWORD(hInstance) +
326 NTHeader.OptionalHeader.DataDirectory[ImageDirectoryEntryImport].VirtualAddress);
327
328 BaseOfCode := DWORD(hInstance) + NTHeader.OptionalHeader.BaseOfCode;
329 TopOfCode := BaseOfCode + NTHeader.OptionalHeader.SizeOfCode;
330
331 while ImportDesc.Name <> 0 do begin
332 if StriComp(PChar(DWORD(hInstance) + ImportDesc.Name), 'kernel32.dll') = 0 then begin
333 Thunk := PImageThunkData(DWORD(hInstance) + DWORD(ImportDesc.FirstThunk));
334 while Thunk.Funct <> nil do begin
335 if Thunk.Funct = OriginalProc then
336 Thunk.Funct := @LRE;
337 Inc(Thunk);
338 end;
339 end;
340 Inc(ImportDesc);
341 end;
342 RA2 := OriginalProc;
343 end;
344 SaveGetExceptionObject := ExceptObjProc;
345 ExceptObjProc := @HookGetExceptionObject;
346 end;
347
348 initialization
349 OnHookInstaller := HookInstaller;
350 {$WARNINGS OFF} { Yeah, we know DebugHook is platform specific }
351 if DebugHook = 0 then InitializeEng;
352 {$WARNINGS ON}
353
354 finalization
355 EH.Free;
356
357 end.

  ViewVC Help
Powered by ViewVC 1.1.20