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

📄 sehterm.dpr

📁 < windos核心编程>>是经典中的经典,书中原代码是用delphi重新编写的.
💻 DPR
字号:
program SEHTerm;

{$R 'SEHTerm.res' 'SEHTerm.rc'}

uses Windows;

type
  TExceptionDisposition = DWORD; // 异常回调返回值类型(C语言中的枚举型占4字节, 而PASCAL只占1字节)
  
  PExceptionFrame = ^TExceptionFrame; // 扩展的异常帧结构(增加了FinallyAddress字段来实现Finally)
  TExceptionFrame = record
    PrevStruct: PExceptionFrame; // 上一节点位置(线程异常帧链表)
    ExceptionHandler: Pointer;   // 异常回调地址(由操作系统调用)
    FinallyAddress: procedure;   // 结束执行地址(由我们自己调用)
  end;

  // 异常回调
function FinallyHandler(var ExceptionRecord: TExceptionRecord; var EstablisherFrame: TExceptionFrame;
  var ContextRecord: TContext; DispatcherContext: Pointer): TExceptionDisposition; Cdecl;
const
  ExceptionContinueSearch = $00000001;
  StatusUnwind = $C0000027;
  ExceptionUnwinding = $00000002;
  ExceptionUnwindingForExit = $00000004;
begin
  if (ExceptionRecord.ExceptionCode = StatusUnwind) or
     (ExceptionRecord.ExceptionFlags = ExceptionUnwinding) or
     (ExceptionRecord.ExceptionFlags = ExceptionUnwindingForExit) then
  begin
    EstablisherFrame.FinallyAddress();
  end;

  Result := ExceptionContinueSearch;
end;

  // 程序入口
const
  lpText1: PChar = 'Perform invalid memory access?';
  lpCaption1: PChar = 'SEHTerm: In try block';

  lpText2: PChar = 'Abnormal termination';
  lpText3: PChar = 'Normal termination';
  lpCaption2: PChar = 'SEHTerm: In finally block';

  lpText4: PChar = 'Normal process termination';
  lpCaption4: PChar = 'SEHTerm: After finally block';

asm
  // 构造TExceptionFrame并将其插入链表
  PUSH OFFSET  @@Finally     // TExceptionFrame.FinallyAddress
  PUSH OFFSET  FinallyHandler// TExceptionFrame.ExceptionHandler
  PUSH FS:[0]                // TExceptionFrame.PrevStruct
  MOV  FS:[0], ESP           // FS:[0]乃TIB.ExceptionList(链表头)

  // MessageBox(0, 'Perform invalid memory access?', 'SEHTerm: In try block', MB_YESNO);
  PUSH $00000004             // MB_YESNO
  PUSH lpCaption1            // 'SEHTerm: In try block'
  PUSH lpText1               // 'Perform invalid memory access?'
  PUSH $00000000
  CALL MessageBox

  // if (n = IDYES) then PByte(0)^ := 5;
  CMP  EAX, $00000006        // (n = ID_YES) ???
  JNZ  @@NoAccess            // 返回值不是IDYES
  MOV  [0], $00000005        // 故意访问非法地址

@@NoAccess:

  // 如果能执行到这里说明没有出错, ^.^
  POP  FS:[0]                // 将我们节点从异常帧链表摘除
  ADD  ESP, $00000008        // 修改栈顶指针(出栈简化动作)
  PUSH OFFSET @@Other        // 准备后面RET指令的跳转地址

@@Finally:

  // 1.如果没有出错, 则会顺序执行到这里, :-)
  // 2.如果出错, 也会从ExceptHandler()转过来

  // if AbnormalTermination() then .. ;
  CMP [ESP], OFFSET @@Other  // 根据栈顶内容是否等于@@Other, 判断之前是否出错
  JNZ @@Abnormal             // (从而使得MessageBox()显示不同内容)

  // MessageBox(0, 'Normal termination', 'SEHTerm: In finally block', MB_OK)
  PUSH $00000000             // MB_OK
  PUSH lpCaption2            // 'SEHTerm: In finally block'
  PUSH lpText3               // 'Normal termination'
  PUSH $00000000
  CALL MessageBox

  JMP @@Return

@@Abnormal:

  // MessageBox(0, 'Abnormal termination', 'SEHTerm: In finally block', MB_OK)
  PUSH $00000000             // MB_OK
  PUSH lpCaption2            // 'SEHTerm: In finally block'
  PUSH lpText2               // 'Abnormal termination'
  PUSH $00000000
  CALL MessageBox

@@Return:

  RET                        // 没发生异常则顺序执行, 否则返回ExceptHandler()

@@Other:

  // MessageBox(0, 'Normal process termination', 'SEHTerm: After finally block', MB_OK);
  PUSH $00000000             // MB_OK
  PUSH lpCaption4            // 'SEHTerm: After finally block'
  PUSH lpText4               // 'Normal process termination'
  PUSH $00000000
  CALL MessageBox
end.

⌨️ 快捷键说明

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