Quote
Steve Parus wrote:
> I'm looking for a routine to obtain the hard drive serial number that
> will work in protected mode. The following routine works in real
> mode, but crashes the computer in protected mode:
You can't call a real mode interrupt directly from protected mode. You
need to call via the DPMI server. Also, real mode interrupts and
protected mode memory aren't directly addressable, so you need to use
DPMI server to allocate memory below 1MB (at least the WinAPI unit
provides a function to do this).
Here's the source reworked to run under protected mode (yes, I tested it
to make sure it works):
uses
WinAPI;
const
hexdigits : array[0..15] of char = '0123456789ABCDEF';
type
infobuffer = record
infolevel : word; { should be zero }
serial : longint;
vollabel : array[0..10] of char;
filesystem : array[0..7] of char;
end;
serstring = string[9];
{types added -- SFE}
type
PRealModeRegs = ^TRealModeRegs;
TRealModeRegs = record
case integer of
0 : (edi, esi, ebp, rsvd, ebx, edx, ecx, eax : longint);
1 : (di, dih, si, sih, bp, bph, rs, rsh,
bx, bxh, dx, dxh, cx, cxh, ax, axh,
Flags, es, ds, fs, gs, ip, cs, sp, ss : word);
2 : (dill, dilh, dihl, dihh, sill, silh, sihl, sihh,
bpll, bplh, bphl, bphh, rsll, rslh, rshl, rshh,
bl, bh, bxhl, bxhh, dl, dh, dxhl, dxhh,
cl, ch, cxhl, cxhh, al, ah, axhl, axhh : byte);
end;
type
DosAllocInfo = record
case index : byte of
0 : (l : longint);
1 : (selector, segment : word);
end;
{}
var
ib : infobuffer;
n : word;
let : char;
param : string[10];
isset : boolean;
newserial : longint;
code : integer;
function serialstr(l : longint) : serstring;
var temp : serstring;
begin
temp[0] := #9;
temp[1] := hexdigits[(l shr 28) and $f];
temp[2] := hexdigits[(l shr 24) and $f];
temp[3] := hexdigits[(l shr 20) and $f];
temp[4] := hexdigits[(l shr 16) and $f];
temp[5] := '-';
temp[6] := hexdigits[(l shr 12) and $f];
temp[7] := hexdigits[(l shr 8) and $f];
temp[8] := hexdigits[(l shr 4) and $f];
temp[9] := hexdigits[l and $f];
serialstr := temp;
end;
{function added -- SFE}
function realint (vect : byte; var RMregs : TRealModeRegs) : word;
assembler;
{
Used by the ROM-character related code to call the real-mode BIOS.
Returns the error code reported by the DPMI server (0 means no error).
asm
mov ax,0300h {function 0300h = simulate real mode
interrupt }
xor bx,bx {BH should be
cleared }
mov bl,[vect] {set the interrupt vector to
call }
xor cx,cx {do not transfer any data from RM stack -> PM
stack }
les di,[RMregs] {get pointer to pseudoregister
structure }
int 31h {call DPMI
server }
end;
{}
{heavily modified -- SFE}
function getserial( disknum : byte; var i : infobuffer) : word ;
var
regs : TRealModeRegs;
info : DosAllocInfo;
begin
info.l := GlobalDosAlloc(sizeof(infobuffer));
if info.l=0 then
begin
getserial := $ffff;
exit;
end;
move (i,mem[info.selector:0],sizeof(infobuffer));
fillchar (regs,sizeof(regs),0);
with regs do
begin
ah := $69;
al := $00;
bl := disknum;
ds := info.segment;
dx := $0000;
end;
realint ($21,regs);
move (mem[info.selector:0],i,sizeof(infobuffer));
if (regs.flags and $01)>0 then
getserial := regs.ax
else
getserial := 0;
end;
{}
begin
let := 'C';
n := getserial(ord(let)-ord('@'), ib);
if n = 0 then with ib do writeln('Serial # = ',serialstr(serial));
end.
--
Scott Earnest | We now return you to our regularly |
set...@ix.netcom.com | scheduled chaos and mayhem. . . . |