Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Прочитать ROM-BIOS

Оформил: DeeCo
Автор: http://www.swissdelphicenter.ch

// 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}

 unit BiosHelp {$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 '\Device\PhysicalMemory'. 
//    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 = '\Device\PhysicalMemory';
   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.
Проект Delphi World © Выпуск 2002 - 2024
Автор проекта: USU Software
Вы можете выкупить этот проект.