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

📄 sehsoft.dpr

📁 一本已经绝版的好书
💻 DPR
字号:

// Module name: SEHSoft.C ->> SEHSoft.dpr
// Notices: Copyright (c) 1995-1997 Jeffrey Richter
// Translator: 刘麻子, Liu_mazi@126.com

program SEHSoft;

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

uses
  Windows, Messages,
  Other in '..\Other.pas', CmnHdr in '..\CmnHdr.pas', WindowsX in '..\WindowsX.pas';

const
  g_szModName = 'SEHSoft';
  IDD_SEHSOFT     =   1;
  IDC_NUMACCESSES = 100;
  IDC_LOG         = 101;
  IDI_SEHSOFT     = 101;

  // 数组结构
type
  PElement = ^TElement;
  TElement = record
    bReserved: array[0..4*1024-1] of Byte;
  end;
  PArray = ^TArray;
  TArray = array[0..0] of TElement;

  // 数组长度
const
  NUMELEMENTS  = 50;
  NUMBYTESINARRAY = SizeOf(TElement) * NUMELEMENTS;

  // 自定义异常编码
const
  SE_ZERO_ELEM =
    (ERROR_SEVERITY_ERROR) or // 严重性(31~30)
    (1 shl 29) or             // 客户/微软(29)
    (0 shl 28) or             // 保留(28)
    (FACILITY_NULL shl 16) or // 设备代码(27~16)
    (1);                      // 异常代码(15~0)

  // 扩展的SEH节点
type
  PEstablisherFrame = ^TEstablisherFrame;
  TEstablisherFrame = record
    Prev: PEstablisherFrame;
    Handler: TfnPerThreadExcptionHandler;
    case Byte of
      1: (FinallyEip, FinallyEbp: DWORD);  // LeaveException
      2: (lpbArray: PByte; hWndLog: HWND); // EXCEPTION_ACCESS_VIOLATION
      3: (ExceptEip, ExceptEbp: DWORD; PExceptRec: PExceptionRecord); // SE_ZERO_ELEM
  end;

  // 函数前置声明
function ExpFilter(var lpEP: TExceptionPointers; lpbArray: PByte; lNumBytesInArray: DWORD; hWndLog: HWND): Integer; forward;

  // 线程异常回调
function ExceptHandler(var ExceptionRecord: TExceptionRecord; var EstablisherFrame: TEstablisherFrame;
  var ContextRecord: TContext; DispatcherContext: Pointer): TExceptionDisposition; cdecl;
var
  EPs: TExceptionPointers;
begin
  case ExceptionRecord.ExceptionCode of
    EXCEPTION_ACCESS_VIOLATION:
      begin
        EPs.ExceptionRecord := @ExceptionRecord;
        EPs.ContextRecord := @ContextRecord;
        
        Result := ExpFilter(EPs, EstablisherFrame.lpbArray, NUMBYTESINARRAY, EstablisherFrame.hWndLog) + 1; // **
      end;

    SE_ZERO_ELEM:
      begin
        EstablisherFrame.PExceptRec^ := ExceptionRecord;
        ContextRecord.Ebp := EstablisherFrame.ExceptEbp;
        ContextRecord.Eip := EstablisherFrame.ExceptEip;        
        ContextRecord.Esp := DWORD(@EstablisherFrame);

        Result := ExceptionContinueExecution;
      end;

    LeaveException:
      begin
        ContextRecord.Ebp := EstablisherFrame.FinallyEbp;
        ContextRecord.Eip := EstablisherFrame.FinallyEip;
        ContextRecord.Esp := DWORD(@EstablisherFrame);

        Result := ExceptionContinueExecution;
      end;

    else Result := ExceptionContinueSearch;
  end;
end;

  // 提交物理内存
procedure CommitMemory(hWndLog: HWND; var lpEP: TExceptionPointers; lpbAttemptedAddr: PByte);
var
  fAttemptedWrite: BOOL;
  szBuf: array[0..100] of Char;
begin
  // 读/写导致异常
  fAttemptedWrite := BOOL(lpEP.ExceptionRecord.ExceptionInformation[0]);

  // 显示到ListBox
  _wvsprintf(szBuf, '---> Committing memory (%s attempted)', [DWORD(IfThen(fAttemptedWrite, 'write', 'read'))]);
  ListBox_AddString(hWndLog, szBuf);

  // 分配物理内存
  VirtualAlloc(lpbAttemptedAddr, SizeOf(TElement), MEM_COMMIT, PAGE_READWRITE);

  // 抛出自定异常
  if (fAttemptedWrite = FALSE) then RaiseException(SE_ZERO_ELEM, 0, 1, @lpbAttemptedAddr); // **
end;

  // 异常"过滤器"
function ExpFilter(var lpEP: TExceptionPointers; lpbArray: PByte; lNumBytesInArray: DWORD; hWndLog: HWND): Integer;
label
  FinallyDo, ExceptDo, NoExcept;
var
  lpbAttemptedAddr: PByte;
  dwExceptionCode: DWORD;
  nFilterResult: Integer;
  SavedExceptRec: TExceptionRecord;
  lpArrayElementToZero: PElement;
begin
  asm
    MOV  nFilterResult, EXCEPTION_CONTINUE_SEARCH
  end;
  dwExceptionCode := lpEP.ExceptionRecord.ExceptionCode;

  // 异常保护 (LeaveException)
  asm
    PUSH EBP                  // TEstablisherFrame.FinallyEbp := EBP
    PUSH OFFSET FinallyDo     // TEstablisherFrame.FinallyEip := FinallyDo
    PUSH OFFSET ExceptHandler // TEstablisherFrame.Handler := @ExceptHandler
    PUSH FS:[0]               // TEstablisherFrame.Prev := TEB.ExceptionList
    MOV  FS:[0], ESP          // TEB.ExceptionList := @TEstablisherFrame
  end;

  // 异常类型
  if (dwExceptionCode <> EXCEPTION_ACCESS_VIOLATION) then _leave;

  // 数组地址
  if (lpbArray = nil) then _leave;

  // 出错地址
  lpbAttemptedAddr := Pointer(lpEP.ExceptionRecord.ExceptionInformation[1]);
  if (DWORD(lpbAttemptedAddr) < DWORD(lpbArray)) or
     (DWORD(lpbArray) + lNumBytesInArray <= DWORD(lpbAttemptedAddr))
  then _leave;

  // 异常保护 (SE_ZERO_ELEM)
  asm
    LEA  EAX, SavedExceptRec
    PUSH EAX                    // TEstablisherFrame.PExceptRec := @SavedExceptRec;
    PUSH EBP                    // TEstablisherFrame.ExceptEbp := EBP
    PUSH OFFSET ExceptDo        // TEstablisherFrame.ExceptEip := ExceptDo
    PUSH OFFSET ExceptHandler   // TEstablisherFrame.Handler := @ExceptHandler
    PUSH FS:[0]                 // TEstablisherFrame.Prev := TEB.ExceptionList
    MOV  FS:[0], ESP            // TEB.ExceptionList := @TEstablisherFrame
  end;

  // 提交内存
  CommitMemory(hWndLog, lpEP, lpbAttemptedAddr);

  // 没有异常
  goto NoExcept;

  // 发生异常
ExceptDo:
  lpArrayElementToZero := PElement(SavedExceptRec.ExceptionInformation[0]);
  chINITSTRUCT(lpArrayElementToZero^, SizeOf(TElement), FALSE);
  ListBox_AddString(hWndLog, '---> Zeroed array element');

  // 去除保护 (SE_ZERO_ELEM)
NoExcept:
  asm
    POP  FS:[0]                 // TEB.ExceptionList := TEstablisherFrame.Prev;
    ADD  ESP, TYPE DWORD * 4    // 恢复栈顶
  end;
  nFilterResult := EXCEPTION_CONTINUE_EXECUTION;

  // 去除保护 (LeaveException)
FinallyDo:
  asm
    POP  FS:[0]               // TEB.ExceptionList := TEstablisherFrame.Prev;
    ADD  ESP, TYPE DWORD * 3  // 恢复栈顶
  end;

  Result := nFilterResult;
end;

  // 访问保留内存
procedure Dlg_ReserveArrayAndAccessIt(hWndLog: HWND; nNumAccesses: Integer);
var
  lpArray: PArray;
  Element: TElement;
  szBuf: array[0..100] of Char;
  nElementNum: Integer;
begin
  // 开始执行
  ListBox_ResetContent(hWndLog);
  ListBox_AddString(hWndLog, 'Execution started');

  // 保留内存
  lpArray := VirtualAlloc(nil, NUMBYTESINARRAY, MEM_RESERVE, PAGE_NOACCESS);

  // 异常保护 (EXCEPTION_ACCESS_VIOLATION)
  asm
    PUSH hWndLog              // TEstablisherFrame.hWndLog := hWndLog
    PUSH lpArray              // TEstablisherFrame.lpbArray := lpbArray
    PUSH OFFSET ExceptHandler // TEstablisherFrame.Handler := @ExceptHandler
    PUSH FS:[0]               // TEstablisherFrame.Prev := TEB.ExceptionList
    MOV  FS:[0], ESP          // TEB.ExceptionList := @TEstablisherFrame
  end;

  // 随机访问
  while (nNumAccesses > 0) do
  begin
    Dec(nNumAccesses);
    nElementNum := Random(NUMELEMENTS);

    // 读或者写
    if (Random(2) = 0) then
    begin
      _wvsprintf(szBuf, 'Reading index: %d', [nElementNum]);
      ListBox_AddString(hWndLog, szBuf);

      Element := lpArray[nElementNum];
    end else
    begin
      _wvsprintf(szBuf, 'Writing index: %d', [nElementNum]);
      ListBox_AddString(hWndLog, szBuf);

      lpArray[nElementNum] := Element;
    end;
  end; // while

  // 去除保护 (EXCEPTION_ACCESS_VIOLATION)
  asm
    POP  FS:[0]               // TEB.ExceptionList := TEstablisherFrame.Prev;
    ADD  ESP, TYPE DWORD * 3  // 恢复栈顶
  end;

  // 释放内存
  VirtualFree(lpArray, 0, MEM_RELEASE);

  // 执行完毕
  ListBox_AddString(hWndLog, 'Execution ended');
end;

  // WM_INITDIALOG
function Dlg_OnInitDialog(hWnd, hWndFocus: HWND; lParam: LPARAM): BOOL;
begin
  chSETDLGICONS(hWnd, IDI_SEHSOFT, IDI_SEHSOFT);
  SetDlgItemInt(hWnd, IDC_NUMACCESSES, 100, FALSE);
  Result := TRUE;
end;

  // WM_COMMAND
procedure Dlg_OnCommand(hWnd: HWND; id: Integer; hWndCtl: HWND; codeNotify: UINT);
var
  nNumAccesses: Integer;
  fTranslated: BOOL;
begin
  case (id) of
    IDOK:
      begin
        nNumAccesses := GetDlgItemInt(hWnd, IDC_NUMACCESSES, fTranslated, FALSE);

        if (fTranslated) then
          Dlg_ReserveArrayAndAccessIt(GetDlgItem(hWnd, IDC_LOG), nNumAccesses)
        else
          chMB('Invalid number of accesses.', g_szModName);
      end;

    IDCANCEL:
      begin
        EndDialog(hWnd, id);
      end;
  end;
end;

  // 对话框回调
function Dlg_Proc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;
begin
  case (uMsg) of
    WM_INITDIALOG:
      begin
        Result := SetDlgMsgResult(hWnd, LRESULT(Dlg_OnInitDialog(hWnd, wParam, lParam)));
      end;

    WM_COMMAND:
      begin
        Dlg_OnCommand(hWnd, LOWORD(wParam), lParam, HIWORD(wParam));
        Result := TRUE;
      end;

    else Result := FALSE;
  end;
end;

  // 程序入口
begin
  chWARNIFUNICODEUNDERWIN95();
  DialogBox(HInstance, MakeIntResource(IDD_SEHSOFT), 0, @Dlg_Proc);
end.

⌨️ 快捷键说明

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