Delphi - объектно-ориентированный язык программирования, разработанный компанией Borland в 1995 году. Он основан на языке программирования Pascal, но имеет более расширенные возможности и добавлены новые функции.
Delphi является интегрированной средой разработки (IDE), которая позволяет разрабатывать программное обеспечение для различных платформ, включая Windows, macOS, Android и iOS. Delphi достигает многоплатформенности с помощью...
// An Example of this unit is availabe as Demo Download. // Ein Beispiel zur Anwendung dieser Unit kann als Demo heruntergeladen werden. //////////////////////////////////////////////////////////////////////////////// // // BIOS Helper for Delphi // // BIOS related utilities for Win9x and WinNT(i386) // //////////////////////////////////////////////////////////////////////////////// // // The Original Code is: // BiosHelp.pas, released 2001-09-02. // // The Initial Developer of the Original Code is Nico Bendlin. // // Portions created by Nico Bendlin are // Copyright (C) 2001-2003 Nico Bendlin. All Rights Reserved. // // Contributor(s): // Nico Bendlin<nicode@gmx.net> // // 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. // // Alternatively, the contents of this file may be used under the terms of // either the GNU General Public License Version 2 or later (the "GPL"), or // the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), // in which case the provisions of the GPL or the LGPL are applicable instead // of those above. If you wish to allow use of your version of this file only // under the terms of either the GPL or the LGPL, and not to allow others to // use your version of this file under the terms of the MPL, indicate your // decision by deleting the provisions above and replace them with the notice // and other provisions required by the GPL or the LGPL. If you do not delete // the provisions above, a recipient may use your version of this file under // the terms of any one of the MPL, the GPL or the LGPL. // //////////////////////////////////////////////////////////////////////////////// // // Revision: // // 2003-02-15 2.00 [NicoDE] // - generic dump method completely rewritten // - default range is now E000:0000-F000:FFFF // //////////////////////////////////////////////////////////////////////////////// {$IFDEF CONDITIONALEXPRESSIONS} {$DEFINE DELPHI6UP} {$IF NOT DEFINED(VER140)} {$DEFINE DELPHI7UP} {$IFEND} {$ENDIF} unitBiosHelp {$IFDEF DELPHI6UP} platform {$ENDIF}; {$MINENUMSIZE 4} {$WEAKPACKAGEUNIT} {$IFDEF DELPHI7UP} {$WARN UNSAFE_TYPE OFF} {$WARN UNSAFE_CODE OFF} {$ENDIF} interface
uses
Windows; const
RomBiosDumpBase = $000E0000; RomBiosDumpEnd = $000FFFFF; RomBiosDumpSize = RomBiosDumpEnd - RomBiosDumpBase + 1; type
PRomBiosDump = ^TRomBiosDump; TRomBiosDump = array
[RomBiosDumpBase..RomBiosDumpEnd] of
Byte; type
TRomDumpMethod = (rdmAutomatic, // Autodetect OS type and use proper method rdmGeneric, // Use 16-bit EXE program to dump the BIOS rdmMemory, // Dump from process's address space (Win9x) rdmPhysical // Dump from physical memory object (WinNT) ); function
DumpRomBios(out Dump: TRomBiosDump; Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean; function
DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump; Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean; procedure
ReadRomDumpBuffer(const
Dump: TRomBiosDump; Addr: Pointer; var
Buffer; Size: Cardinal); procedure
ReadRomDumpBufferEx(const
Dump; Base, Addr: Pointer; var
Buffer; Size: Cardinal); function
GetRomDumpAddr(const
Dump: TRomBiosDump; Addr: Pointer): Pointer; function
GetRomDumpAddrEx(const
Dump; Base, Addr: Pointer): Pointer; implementation
//////////////////////////////////////////////////////////////////////////////// // // DumpRomBios16 (rdmGeneric) // // Creates an 16-bit EXE program in TEMP and runs it redirected to an file. // // WARNING: One day 16-bit code will not run on future Windows. // WARNING: You are dumping the BIOS inside the MS-DOS 'emulator'. // function
_RomDumpCode(RomBase: Pointer; RomSize: Cardinal; out Code: Pointer; out Size: Cardinal): Boolean; const
BlockSize = $1000; type
// ; RomDump (dumps mem to STDOUT) PRomDumpCode = ^TRomDumpCode; // ; BlockSize MUST be multiple of 10h. TRomDumpCode = packed
record
// _header: TImageDosHeader; // _notice: array
[0..$4F] of
AnsiChar; // @@note: db 'RomDump 2.0', ... init: packed
record
// @@init: _mov_44: array
[0..2] of
Byte; // mov ax, 4400h _mov_bx: array
[0..2] of
Byte; // mov bx, 0001h _dos_21: array
[0..1] of
Byte; // int 21h _jcf_18: array
[0..1] of
Byte; // jc @@code _and_dx: array
[0..3] of
Byte; // and dx, 0082h _cmp_dx: array
[0..3] of
Byte; // cmp dx, 0082h _jne_0E: array
[0..1] of
Byte; // jne @@code _psh_cs: Byte; // push cs _pop_ds: Byte; // push ds _mov_dx: array
[0..2] of
Byte; // mov dx, offset @@note _mov_09: array
[0..1] of
Byte; // mov ah, 09h _int_21: array
[0..1] of
Byte; // int 21h _mov_4C: array
[0..2] of
Byte; // mov ax, 4C01h _int_20: array
[0..1] of
Byte; // int 21h end
; // code: packed
record
// @@code: _mov_cx: Byte; BlockCount: Word; // mov cx, <BlockCount> _mov_dx: Byte; DatSegment: Word; // mov dx, <DatSegment> _jcx_1C: array
[0..1] of
Byte; // jcxz @@rest end
; // loop: packed
record
// @@loop: _psh_cx: Byte; // push cx _psh_dx: Byte; // push dx _mov_ds: array
[0..1] of
Byte; // mov ds, dx _mov_dx: Byte; DatOffset: Word; // mov dx, <DatOffset> _mov_cx: array
[0..2] of
Byte; // mov cx, <BlockSize> _mov_bx: array
[0..2] of
Byte; // mov bx, 0001h _mov_ax: array
[0..2] of
Byte; // mov ax, 4000h _int_21: array
[0..1] of
Byte; // int 21h _pop_dx: Byte; // pop dx _pop_cx: Byte; // pop cx _jcf_1C: array
[0..1] of
Byte; // jc @@exit _add_dx: array
[0..3] of
Byte; // add dx, <BlockSize/10h> _lop_E4: array
[0..1] of
Byte; // loop @@loop end
; // rest: packed
record
// @@rest: _mov_ds: array
[0..1] of
Byte; // mov ds, dx _mov_dx: Byte; DatOffset: Word; // mov dx, <DatOffset> _mov_cx: Byte; LenghtMod: Word; // mov cx, <LenghtMod> _mov_bx: array
[0..2] of
Byte; // mov bx, 0001h _mov_ax: array
[0..2] of
Byte; // mov ax, 4000h _jcx_06: array
[0..1] of
Byte; // jcxz @@exit _int_21: array
[0..1] of
Byte; // int 21h _jcf_02: array
[0..1] of
Byte; // jc @@exit _mov_al: array
[0..1] of
Byte; // mov al, 00h end
; // Exit: packed
record
// @@exit: _mov_ah: array
[0..1] of
Byte; // mov ah, 4Ch _int_21: array
[0..1] of
Byte; // int 21h end
; // end
; const
RomDumpCodeSize = SizeOf(TRomDumpCode) - SizeOf(TImageDosHeader); RomDumpCode: TRomDumpCode = (_header: (e_magic: IMAGE_DOS_SIGNATURE; e_cblp: Word(RomDumpCodeSize) and
$1FF; e_cp: Word((RomDumpCodeSize - 1) shr
9) + 1; e_crlc: $0000; e_cparhdr: SizeOf(TImageDosHeader) shr
4; e_minalloc: $0000; e_maxalloc: $FFFF; e_ss: $0000; e_sp: $1000; e_csum: $0000; e_ip: SizeOf(RomDumpCode._notice); e_cs: $0000; e_lfarlc: SizeOf(TImageDosHeader); e_ovno: $0000; e_res: ($0000, $0000, $0000, $0000); e_oemid: $0000; e_oeminfo: $0000; e_res2: ($0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000, $0000); _lfanew: $00000000 ); _notice: #13#10+ 'RomDump 2.0'#13#10 + 'Copyright (c) 2003 Nico Bendlin'#13#10 + #13#10+ 'Usage: RomDump > filename'#13#10 + #13#10$'; init: (_mov_44: ($B8, $00, $44); _mov_bx: ($BB, $01, $00); _dos_21: ($CD, $21); _jcf_18: ($72, $18); _and_dx: ($81, $E2, $82, $00); _cmp_dx: ($81, $FA, $82, $00); _jne_0E: ($75, $0E); _psh_cs: $0E; _pop_ds: $1F; _mov_dx: ($BA, $00, $00); _mov_09: ($B4, $09); _int_21: ($CD, $21); _mov_4C: ($B8, $01, $4C); _int_20: ($CD, $21); ); code: (_mov_cx: $B9; BlockCount: $0010; _mov_dx: $BA; DatSegment: $F000; _jcx_1C: ($E3, $1C) ); loop: (_psh_cx: $51; _psh_dx: $52; _mov_ds: ($8E, $DA); _mov_dx: $BA; DatOffset: $0000; _mov_cx: ($B9, Lo(BlockSize), Hi(BlockSize)); _mov_bx: ($BB, $01, $00); _mov_ax: ($B8, $00, $40); _int_21: ($CD, $21); _pop_dx: $5A; _pop_cx: $59; _jcf_1C: ($72, $1C); _add_dx: ($81, $C2, Lo(BlockSize shr
4), Hi(BlockSize shr
4)); _lop_E4: ($E2, $E4) ); rest: (_mov_ds: ($8E, $DA); _mov_dx: $BA; DatOffset: $0000; _mov_cx: $B9; LenghtMod: $0000; _mov_bx: ($BB, $01, $00); _mov_ax: ($B8, $00, $40); _jcx_06: ($E3, $06); _int_21: ($CD, $21); _jcf_02: ($72, $02); _mov_al: ($B0, $00) ); Exit: (_mov_ah: ($B4, $4C); _int_21: ($CD, $21) ) ); begin
Result := False; if
(RomSize > 0) and
(RomSize <= $100000) and
(Cardinal(RomBase) < $100000) and
(Cardinal(RomBase) + RomSize <= $100000) then
begin
Size := SizeOf(TRomDumpCode); Code := Pointer(LocalAlloc(LPTR, Size)); if
Code <> nil
then
try
PRomDumpCode(Code)^ := RomDumpCode; with
PRomDumpCode(Code)^ do
begin
code.BlockCount := Word(RomSize div
BlockSize); code.DatSegment := Word(Cardinal(RomBase) shr
4); loop.DatOffset := Word(Cardinal(RomBase)) and
$000F; rest.DatOffset := loop.DatOffset; rest.LenghtMod := Word(RomSize mod
BlockSize); end
; Result := True; except
LocalFree(HLOCAL(Code)); Code := nil
; Size := 0; end
; end
; end
; function
_SaveRomDumpCodeToFile(RomBase: Pointer; RomSize: Cardinal; const
FileName: string
): Boolean; var
Code: Pointer; Size: Cardinal; Hand: THandle; Num: DWORD; begin
Result := False; if
_RomDumpCode(RomBase, RomSize, Code, Size) then
try
Hand := CreateFile(PChar(FileName), GENERIC_WRITE, FILE_SHARE_READ, nil
, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if
Hand <> INVALID_HANDLE_VALUE then
try
Result := WriteFile(Hand, Code^, Size, Num, nil
) and
(Num = Size); if
not
Result then
DeleteFile(PChar(FileName)); finally
CloseHandle(Hand); end
; finally
LocalFree(HLOCAL(Code)); end
; end
; function
_ExecuteRomDumpCode(const
Code, Dump: string
; Timeout: DWORD): Boolean; var
ComSpec: string
; StartInfo: TStartupInfo; ProcInfo: TProcessInformation; ErrorMode: Cardinal; begin
Result := False; SetLength(ComSpec, MAX_PATH + 1); SetLength(ComSpec, GetEnvironmentVariable('ComSpec', PChar(@ComSpec[1]), MAX_PATH)); if
Length(ComSpec) <= 0 then
Exit; FillChar(StartInfo, SizeOf(TStartupInfo), 0); StartInfo.cb := SizeOf(TStartupInfo); StartInfo.dwFlags := STARTF_USESHOWWINDOW; StartInfo.wShowWindow := SW_HIDE; ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS or
SEM_NOGPFAULTERRORBOX or
SEM_NOALIGNMENTFAULTEXCEPT or
SEM_NOOPENFILEERRORBOX); try
if
CreateProcess(nil
, PChar(ComSpec + ' /C ' + Code + ' > ' + Dump), nil
, nil
, False, HIGH_PRIORITY_CLASS, nil
, nil
, StartInfo, ProcInfo) then
try
Result := (WaitForSingleObject(ProcInfo.hProcess, Timeout) <> WAIT_TIMEOUT); if
not
Result then
TerminateProcess(ProcInfo.hProcess, STATUS_TIMEOUT); finally
CloseHandle(ProcInfo.hThread); CloseHandle(ProcInfo.hProcess); end
; finally
SetErrorMode(ErrorMode); end
; end
; function
DumpRomBios16(RomBase: Pointer; RomSize: Cardinal; var
Dump; Timeout: DWORD): Boolean; var
Tmp: array
[0..MAX_PATH] of
Char; Dmp: array
[0..MAX_PATH] of
Char; Exe: array
[0..MAX_PATH] of
Char; Hnd: THandle; Num: DWORD; begin
Result := False; if
GetTempPath(MAX_PATH, Tmp) > 0 then
GetShortPathName(Tmp, Tmp, MAX_PATH) else
lstrcpy(Tmp, '.'); if
GetTempFileName(Tmp, 'rom', 0, Dmp) > 0 then
try
lstrcpy(Exe, Dmp); lstrcat(Exe, '.exe'); // Win9x requires .EXE extention if
_SaveRomDumpCodeToFile(RomBase, RomSize, Exe) then
try
if
_ExecuteRomDumpCode(Exe, Dmp, Timeout) then
begin
Hnd := CreateFile(Dmp, GENERIC_READ, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil
, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if
Hnd <> INVALID_HANDLE_VALUE then
try
Result := ReadFile(Hnd, Dump, RomSize, Num, nil
) and
(Num = RomSize); finally
CloseHandle(Hnd); end
; end
; finally
DeleteFile(Exe); end
; finally
DeleteFile(Dmp); end
; end
; //////////////////////////////////////////////////////////////////////////////// // // DumpRomBios9x (rdmMemory) // // Win9x maps the BIOS into every process - therefore it's directly accessed. // function
DumpRomBios9x(RomBase: Pointer; RomSize: Cardinal; var
Dump): Boolean; begin
Result := False; try
Move(RomBase^, Dump, RomSize); Result := True; except
// ignore exeptions end
end
; //////////////////////////////////////////////////////////////////////////////// // // DumpRomBiosNt (rdmPhysical) // // On WinNT the BIOS is accessable through section 'DevicePhysicalMemory'. // This object can only be opened by members of local 'Adminstrators' group. // ZwOpenSection and RtlNtStatusToDosError are documented in newer MSDN/DDK. // type
NTSTATUS = Integer; PUnicodeString = ^TUnicodeString; TUnicodeString = packed
record
Length: Word; MaximumLength: Word; Buffer: PWideChar; end
; PObjectAttributes = ^TObjectAttributes; TObjectAttributes = record
Length: ULONG; RootDirectory: THandle; ObjectName: PUnicodeString; Attributes: ULONG; SecurityDescriptor: PSecurityDescriptor; SecurityQualityOfService: PSecurityQualityOfService; end
; TFNZwOpenSection = function
(out Section: THandle; Access: ACCESS_MASK; Attributes: PObjectAttributes): NTSTATUS; stdcall
; TFNRtlNtStatusToDosError = function
(Status: NTSTATUS): DWORD; stdcall
; const
PhysMemDevName = 'DevicePhysicalMemory'; PhysMemName: TUnicodeString = (Length: Length(PhysMemDevName) * SizeOf(WideChar); MaximumLength: Length(PhysMemDevName) * SizeOf(WideChar) + SizeOf(WideChar); Buffer: PhysMemDevName; ); PhysMemMask: ACCESS_MASK = SECTION_MAP_READ; PhysMemAttr: TObjectAttributes = (Length: SizeOf(TObjectAttributes); RootDirectory: 0; ObjectName: @PhysMemName; Attributes: $00000040; // OBJ_CASE_INSENSITIVE SecurityDescriptor: nil
; SecurityQualityOfService: nil
; ); var
ZwOpenSection: TFNZwOpenSection; RtlNtStatusToDosError: TFNRtlNtStatusToDosError; function
DumpRomBiosNt(RomBase: Pointer; RomSize: Cardinal; var
Dump): Boolean; var
HMod: HMODULE; Stat: NTSTATUS; Sect: THandle; View: Pointer; begin
Result := False; HMod := GetModuleHandle('ntdll.dll'); if
HMod = 0 then
SetLastError(ERROR_CALL_NOT_IMPLEMENTED) else
begin
if
not
Assigned(ZwOpenSection) then
ZwOpenSection := GetProcAddress(HMod, 'ZwOpenSection'); if
not
Assigned(RtlNtStatusToDosError) then
RtlNtStatusToDosError := GetProcAddress(HMod, 'RtlNtStatusToDosError'); if
not
Assigned(ZwOpenSection) or
not
Assigned(RtlNtStatusToDosError) then
SetLastError(ERROR_CALL_NOT_IMPLEMENTED) else
begin
Stat := ZwOpenSection(Sect, PhysMemMask, @PhysMemAttr); if
Stat >= 0 then
try
View := MapViewOfFile(Sect, PhysMemMask, 0, Cardinal(RomBase), RomSize); if
View <> nil
then
try
Move(View^, Dump, RomSize); Result := True; finally
UnmapViewOfFile(View); end
; finally
CloseHandle(Sect); end
else
SetLastError(RtlNtStatusToDosError(Stat)); end
; end
; end
; //////////////////////////////////////////////////////////////////////////////// // // DumpRomBios(Ex) // // Public functions to call OS-dependent implementations. // function
DumpRomBios(out Dump: TRomBiosDump; Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean; begin
Result := DumpRomBiosEx(Pointer(RomBiosDumpBase), RomBiosDumpSize, Dump, Method, Timeout); end
; function
DumpRomBiosEx(RomBase: Pointer; RomSize: Cardinal; out Dump; Method: TRomDumpMethod = rdmAutomatic; Timeout: DWORD = 5000): Boolean; begin
Result := False; case
Method of
rdmAutomatic: if
(GetVersion() and
$80000000) <> 0 then
Result := DumpRomBios9x(RomBase, RomSize, Dump) else
begin
Result := DumpRomBiosNt(RomBase, RomSize, Dump); if
not
Result then
DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout)); end
; rdmGeneric: Result := DumpRomBios16(RomBase, RomSize, Dump, DWORD(Timeout)); rdmMemory: Result := DumpRomBios9x(RomBase, RomSize, Dump); rdmPhysical: Result := DumpRomBiosNt(RomBase, RomSize, Dump); else
SetLastError(ERROR_INVALID_PARAMETER); end
; end
; //////////////////////////////////////////////////////////////////////////////// // // ReadRomDumpBuffer(Ex) / GetRomDumpAddr(Ex) // // Utilities to simplify the access to dumps. // procedure
ReadRomDumpBuffer(const
Dump: TRomBiosDump; Addr: Pointer; var
Buffer; Size: Cardinal); begin
Move(Dump[Cardinal(Addr)], Buffer, Size); end
; procedure
ReadRomDumpBufferEx(const
Dump; Base, Addr: Pointer; var
Buffer; Size: Cardinal); begin
Move(Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base))^, Buffer, Size); end
; function
GetRomDumpAddr(const
Dump: TRomBiosDump; Addr: Pointer): Pointer; begin
Result := @Dump[Cardinal(Addr)]; end
; function
GetRomDumpAddrEx(const
Dump; Base, Addr: Pointer): Pointer; begin
Result := Pointer(Cardinal(@Dump) + Cardinal(Addr) - Cardinal(Base)); end
; end
.