DiskInf 1.0
Leer el número serial de Fábrica y modelo del HDD
Fecha: 08/Oct/2001 (07/Oct/2001)
Autor: Miguelacho (
[email protected] )
Hola Guille, aquí te mando un ejemplo sencillo pero muy interesante, en especial para quienes quieran crear un sistema de seguridad para sus proyectos, se trata de una aplicación que permite leer el numero serial del disco duro, pero el numero REAL, el de fábrica. No el del Volumen, además de esto, lee el modelo y marca del disco, y el número de revisión, la idea de este código es brindar a los programadores la posibilidad de capturar estas informaciones, para crear un sistema de procesamiento bien sea de una licencia única, o la protección de un sistema para que solo pueda ser ejecutado en una máquina específica. Mucho te agradecería a ti y a los colegas que usen este código, me informen de las posibilidades que se puedan introducir, en especial porque lamentablemente, solo corre bajo Windows 95, 98, 98 SE, y Me, no he logrado que corra en NT, ni en 2000, y no lo he probado en XP, aunque estoy trabajando con un colega quien está haciendo modificaciones, así como introduciendo nuevas funciones de seguridad, posiblemente él o ambos, complementemos esta información.
Este es el código fuente de la DLL:
(La misma está escrita en Delphi, y es propiedad de Lucy o MAC ([email protected]), la verdad nunca pude contactarme con esta persona, los códigos los saqué de aquí: http://skyscraper.fortunecity.com/virtuosity/452/)
DSIdeInf.DPR:
{$A-} (* ¡¡¡ IMPORTANT: DON'T ALIGN REGISTER FIELDS !!! *)
// --------------------------------------------------------
LIBRARY DSIdeInf;
USES Windows,
SysUtils;
// ------------- DATA - handling of the VxD ----------------
(* VxD Functions *)
CONST
cVxDfunction_IdesDinfo = 1;
(* Output Bbuffer for the VxD (rt_IdeDinfo record) *)
TYPE
at_DRawInfo = array [0..255] of word;
rt_IdeDInfo = record
IdeExists: array [1..4] of byte;
DiskExists: array [1..8] of byte;
DisksRawInfo: array [1..8] of at_DRawInfo;
end; {rIdeDInfo}
pt_IdeDInfo = ^rt_IdeDInfo; // pointer for dynamic allocation
VAR
VxDHandle: THandle;
POutBufVxD: pt_IdeDInfo;
lpBytesReturned: DWord;
// ---------- DATA - Handling of IdeDinfo (DLL) ---------
CONST
bit00 = $00000001; bit01 = $00000002; bit02 = $00000004; bit03 = $00000008;
bit04 = $00000010; bit05 = $00000020; bit06 = $00000040; bit07 = $00000080;
bit08 = $00000100; bit09 = $00000200; bit10 = $00000400; bit11 = $00000800;
bit12 = $00001000; bit13 = $00002000; bit14 = $00004000; bit15 = $00008000;
(* IdeDinfo "data fields" *)
TYPE
rt_DiskInfo = record
DiskExists: boolean;
ATAdevice: boolean;
RemovableDevice: boolean;
TotLogCyl: word;
TotLogHeads: word;
TotLogSPT: word;
SerialNumber: string[20];
FirmwareRevision: string[8];
ModelNumber: string[40];
CurLogCyl: word;
CurLogHeads: word;
CurLogSPT: word;
end;
VAR
vp_Valid: boolean;
vp_IdeExists: array [1..4] of boolean;
vp_DisksInfo: array [1..8] of rt_DiskInfo;
// ----------- CODE - VxD function handling --------------
PROCEDURE IdeDInfo;
Var
Ide, MoS, Disk: byte;
fi, fj: byte; {FOR counters}
Begin
(* 1. Make an output buffer for the VxD *)
POutBufVxD:= AllocMem(SizeOf(rt_IdeDInfo));
(* 2. Run VxD function *)
DeviceIoControl
(VxDHandle, cVxDfunction_IdesDInfo,
NIL, 0, {In}
POutBufVxD, SizeOf(POutBufVxD^), lpBytesReturned, {Out}
NIL);
(* 3. Translate and store data *)
// Ide - Disk exists
for Ide:= 1 to 4 do
begin
vp_IdeExists[Ide]:= Odd(POutBufVxD^.IdeExists[Ide]);
for MoS:= 1 to 2 do
begin
Disk:= (Ide-1)*2 + MoS;
vp_DisksInfo[Disk].DiskExists:= Odd(POutBufVxD^.DiskExists[Disk])
end; // for MoS
end; // for Ide
for Ide:= 1 to 4 do
begin
if Not vp_IdeExists[Ide] then continue;
(* Ide Exists - Go on *)
for MoS:= 1 to 2 do
begin
Disk:= (Ide-1)*2 + MoS;
if Not vp_DisksInfo[Disk].DiskExists then continue;
(* Disk Exists - Go on *)
{ --- ATAdevice --- }
if (POutBufVxD^.DisksRawInfo[Disk][0] And bit15) = 0 then
vp_DisksInfo[Disk].ATAdevice:= True;
{ --- Removable Device --- }
if LongBool(POutBufVxD^.DisksRawInfo[Disk][0] And bit07) then
vp_DisksInfo[Disk].RemovableDevice:= True;
{ --- Total number of Logical Cylinders --- }
vp_DisksInfo[Disk].TotLogCyl:= POutBufVxD^.DisksRawInfo[Disk][1];
{ --- Total number of Logical Heads --- }
vp_DisksInfo[Disk].TotLogHeads:= POutBufVxD^.DisksRawInfo[Disk][3];
{ --- Total Logical Sectors per Logical Track --- }
vp_DisksInfo[Disk].TotLogSPT:= POutBufVxD^.DisksRawInfo[Disk][6];
{ -- Serial Number --- }
for fi:=10 to 19 do
begin
fj:= 1+ (fi-10)*2;
vp_DisksInfo[Disk].SerialNumber[fj]:=
Chr( Hi(POutBufVxD^.DisksRawInfo[Disk][fi]) );
vp_DisksInfo[Disk].SerialNumber[fj+1]:=
Chr( Lo(POutBufVxD^.DisksRawInfo[Disk][fi]) );
end; // for fi
// Let's adjust its length
for fi:=1 to 20 do
if vp_DisksInfo[Disk].SerialNumber[fi] = Chr(0) then
break
else
vp_DisksInfo[Disk].SerialNumber[0]:= Chr(fi);
{ -- Firmware Revision --- }
for fi:=23 to 26 do
begin
fj:= 1+ (fi-23)*2;
vp_DisksInfo[Disk].FirmwareRevision[fj]:=
Chr( Hi(POutBufVxD^.DisksRawInfo[Disk][fi]) );
vp_DisksInfo[Disk].FirmwareRevision[fj+1]:=
Chr( Lo(POutBufVxD^.DisksRawInfo[Disk][fi]) );
end; // for fi
// Let's adjust its length
for fi:=1 to 8 do
if vp_DisksInfo[Disk].FirmwareRevision[fi] = Chr(0) then
break
else
vp_DisksInfo[Disk].FirmwareRevision[0]:= Chr(fi);
{ -- Model Number --- }
for fi:=27 to 46 do
begin
fj:= 1+ (fi-27)*2;
vp_DisksInfo[Disk].ModelNumber[fj]:=
Chr( Hi(POutBufVxD^.DisksRawInfo[Disk][fi]) );
vp_DisksInfo[Disk].ModelNumber[fj+1]:=
Chr( Lo(POutBufVxD^.DisksRawInfo[Disk][fi]) );
end; // for fi
// Let's adjust its length
for fi:=1 to 40 do
if vp_DisksInfo[Disk].ModelNumber[fi] = Chr(0) then
break
else
vp_DisksInfo[Disk].ModelNumber[0]:= Chr(fi);
{ --- Current Logical Cylinders --- }
vp_DisksInfo[Disk].CurLogCyl:= POutBufVxD^.DisksRawInfo[Disk][54];
{ --- Current Logical Heads --- }
vp_DisksInfo[Disk].CurLogHeads:= POutBufVxD^.DisksRawInfo[Disk][55];
{ --- Current Logical Sectors per Logical Track --- }
vp_DisksInfo[Disk].CurLogSPT:= POutBufVxD^.DisksRawInfo[Disk][56];
end; // NEXT MoS
end; // NEXT Ide
(* 4. Free the VxD output buffer memory *)
ReallocMem (POutBufVxD, 0);
End; {IdeDInfo}
// --------- CODE - DSIdeInf exported functions/procedures -----
FUNCTION Valid : byte; Stdcall;
Begin
If vp_Valid then
Valid:= 1
else
Valid:= 0;
End; {Valid}
FUNCTION IdeExists (a_Ide: byte) : byte; Stdcall;
Begin
if (a_Ide < 1) or (a_Ide > 4) then // If Invalid Ide Argument
begin
IdeExists:= 0;
Exit;
end;
If vp_IdeExists[a_Ide] then
IdeExists:= 1
else
IdeExists:= 0;
End; {IdeExists}
{ Not exported Function. Handles data as boolean type.
Exported value is byte type}
FUNCTION bool_DiskExists (a_Disk: byte) : boolean;
Begin
if (a_Disk < 1) or (a_Disk > 8) then
bool_DiskExists:= False // If Invalid Disk Argument
else
bool_DiskExists:= vp_DisksInfo[a_Disk].DiskExists;
End; {bool_DiskExists}
FUNCTION DiskExists(a_Disk: byte) : byte; Stdcall;
Begin
if bool_DiskExists (a_Disk) then
DiskExists:= 1
else
DiskExists:= 0;
End; {DiskExists}
FUNCTION ATAdevice(a_Disk: byte) : byte; Stdcall;
Begin
if NOT bool_DiskExists(a_Disk) then
begin
ATAdevice:= 0;
Exit;
end;
if vp_DisksInfo[a_Disk].ATAdevice then
ATAdevice:= 1
else
ATAdevice:= 0;
End; {ATAdevice}
FUNCTION RemovableDevice (a_Disk: byte): byte; Stdcall;
Begin
if NOT bool_DiskExists (a_Disk) then
begin
RemovableDevice:= 0;
Exit;
end;
if vp_DisksInfo[a_Disk].RemovableDevice then
RemovableDevice:= 1
else
RemovableDevice:= 0;
End; {RemovableDevice}
FUNCTION TotLogCyl (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
TotLogCyl:= vp_DisksInfo[a_Disk].TotLogCyl
else
TotLogCyl:= 0;
End; {TotLogCyl}
FUNCTION TotLogHeads (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
TotLogHeads:= vp_DisksInfo[a_Disk].TotLogHeads
else
TotLogHeads:= 0;
End; {TotLogHeads}
FUNCTION TotLogSPT (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
TotLogSPT:= vp_DisksInfo[a_Disk].TotLogSPT
else
TotLogSPT:= 0;
End; {TotLogSPT}
PROCEDURE SerialNumber(a_Disk: byte; aP_SerialNumber: PChar); Stdcall;
Begin
if bool_DiskExists(a_Disk) then
StrPCopy (aP_SerialNumber, vp_DisksInfo[a_Disk].SerialNumber)
else
aP_SerialNumber:= '';
End; {SerialNumber}
PROCEDURE FirmwareRevision(a_Disk: byte; aP_FirmwareRevision: PChar); Stdcall;
Begin
if bool_DiskExists(a_Disk) then
StrPCopy (aP_FirmwareRevision, vp_DisksInfo[a_Disk].FirmwareRevision)
else
aP_FirmwareRevision:= '';
End; {FirmwareRevision}
PROCEDURE ModelNumber(a_Disk: byte; aP_ModelNumber: Pchar); Stdcall;
Begin
if bool_DiskExists(a_Disk) then
StrPCopy (aP_ModelNumber, vp_DisksInfo[a_Disk].ModelNumber)
else
aP_ModelNumber:= '';
End; {ModelNumber}
FUNCTION CurLogCyl (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
CurLogCyl:= vp_DisksInfo[a_Disk].CurLogCyl
else
CurLogCyl:= 0;
End; {CurLogCyl}
FUNCTION CurLogHeads (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
CurLogHeads:= vp_DisksInfo[a_Disk].CurLogHeads
else
CurLogHeads:= 0;
End; {CurLogHeads}
FUNCTION CurLogSPT (a_Disk: byte): word; Stdcall;
Begin
if bool_DiskExists(a_Disk) then
CurLogSPT:= vp_DisksInfo[a_Disk].CurLogSPT
else
CurLogSPT:= 0;
End; {CurLogSPT}
// -----------------------------------------------------------
EXPORTS
Valid,
IdeExists,
DiskExists,
ATAdevice,
RemovableDevice,
TotLogCyl,
TotLogHeads,
TotLogSPT,
SerialNumber,
FirmwareRevision,
ModelNumber,
CurLogCyl,
CurLogHeads,
CurLogSPT;
// --------------- CODE - DLL Initialization ----------------
BEGIN
(* 1. Try to load the VxD *)
VxDHandle:= CreateFile
(PChar('\\.\DSIdeInf.VXD'), 0, 0, NIL, 0, FILE_FLAG_DELETE_ON_CLOSE, 0);
(* 2. If loading was succesful, run its function,
interpret and store the info, and then unload the VxD *)
If VxDHandle <> INVALID_HANDLE_VALUE then
begin
vp_Valid:= True;
IdeDInfo; // Call VxD function, interpret and store info
(* Unload VxD *)
CloseHandle (VxDHandle);
end; // If valid
END.
DSIdeinf Import Unit:
UNIT DSIdeInf_DLL_Import_Unit;
INTERFACE
FUNCTION Valid : byte;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION IdeExists (a_Ide: byte) : byte;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION DiskExists(a_Disk: byte) : byte;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION ATAdevice(a_Disk: byte) : byte;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION RemovableDevice (a_Disk: byte): byte;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION TotLogCyl (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION TotLogHeads (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION TotLogSPT (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
PROCEDURE SerialNumber(a_Disk: byte; aP_SerialNumber: PChar);
Stdcall; external 'DSIdeInf.DLL';
PROCEDURE FirmwareRevision(a_Disk: byte; aP_FirmwareRevision: PChar);
Stdcall; external 'DSIdeInf.DLL';
PROCEDURE ModelNumber(a_Disk: byte; aP_ModelNumber: PChar);
Stdcall; external 'DSIdeInf.DLL';
FUNCTION CurLogCyl (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION CurLogHeads (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
FUNCTION CurLogSPT (a_Disk: byte): word;
Stdcall; external 'DSIdeInf.DLL';
IMPLEMENTATION
END.
Y este es el fuente del archivo VXD que está en ASSEMBLER: DSIdeInf.ASM:
TITLE DSIdeInf.asm - VxD retrieves information from IDEs
.386P
.NOLIST
Include Vmm.inc
Include VWin32.inc
Include Shell.inc
.LIST
; ***** EQUATES *****
; --- Bits ---
cBit00 EQU 0000000000000001b
cBit02 EQU 0000000000000100b
cBit07 EQU 0000000010000000b
; --- Tests ---
cERR EQU cBit00
cBusy EQU cBit07
; --- Area offsets in buffer ---
cDisk0_Exists = 4
cDisk0_RawInfo =12
; --- GDI commands ---
cATA_GDIcmd EQU 0ECh ; GDI command for ATA
cATAPI_GDIcmd EQU 0A1h ; GDI command for ATAPI
; **** MACROS *****
; wPort0 has to be initialized according to IDE
WaitWhileBusy MACRO
LOCAL LoopWhileBusy
MOV DX, [wPort0]
ADD DX, 7 ; DX = Port0 +7
LoopWhileBusy:
IN AL, DX
TEST AX, cBusy
JNZ LoopWhileBusy
ENDM ; (WaitWhileBusy)
; wPort0 has to be initialized according to IDE
; bDevSelCmd has to be initialized according to MoS
SelectDevice MACRO
MOV DX, [wPort0]
ADD DX, 6 ; DX = Port0 +6
MOV AL, [bDevSelCmd] ; AL = DevSelCmd
OUT DX, AL
ENDM ; (SelectDevice)
; wPort0 has to be initialized according to IDE
; Parameter 'GDIcmd' is GDI command (ATA or ATAPI)
SendGDIcmd MACRO GDIcmd
MOV DX, [wPort0]
ADD DX, 7 ; DX = Port0 +7
MOV AL, GDIcmd
OUT DX, AL
ENDM ; (SendGDIcmd)
; -------------------------------
; --- Device Descriptor Block ---
; -------------------------------
DECLARE_VIRTUAL_DEVICE \
DSIDEINF, 1, 0, DSIDEINF_Control,\
UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER
; ----------------------------------------
; --- Prepare Device Control Procedure ---
; ----------------------------------------
Begin_control_dispatch DSIDEINF
Control_Dispatch w32_DeviceIoControl, On_DeviceIoControl
End_control_dispatch DSIDEINF
; ************
; ** CODE **
; ************
VxD_LOCKED_CODE_SEG
; === DEVICE CONTROL PROCEDURE ===
BeginProc On_DeviceIoControl
ASSUME ESI:PTR DIOCParams
.if [esi].dwIoControlCode==DIOC_Open
xor eax,eax
.elseif [esi].dwIoControlCode==1
CALL IdesInfo
xor eax, eax
.endif
RET
EndProc On_DeviceIoControl
; Meaning of registers:
; ESI: pointer to output buffer
; EDI: pointer to section of 1 disk info, in output buffer
; EBX: IDE (0..3)
; ECX: MasterOrSlave (0..1)
; IDE controllers:
; Range: 0..3
; Address of IdeExists(n) byte in output buffer
; = ESI + Ide = ESI + EBX
; DISCs:
; Range: 0..7
; Disk = Ide*2 + MoS = EBX*2 + ECX
; Address of DiskExists(n) byte in output buffer
; = ESI + cDisk0_Exists + Disk
; Address of Disc raw info first byte in output buffer
; = ESI + cDisk0_RawInfo + Disk*512
BeginProc IdesInfo
ASSUME ESI:PTR DIOCParams
; --- Preserve registers and flags ---
PUSHAD
PUSHFD
; --- Initialize ESI as pointer to output buffer ---
MOV ESI, [ESI.lpvOutBuffer]
; --------------------------------------
; --- Process to get the information ---
; --------------------------------------
; Initialize FOR_Ide counter
MOV EBX, 3 ; EBX = Ide no 3
FOR_Ide: ; FOR EBX=3 DOWNTO 0
; --- Initialize wPort0 for this IDE ---
MOV DX, [wPorts_table + EBX*2]
MOV wPort0, DX
; --- Check if IDE exists ---
;MOV DX, [wPort0]
ADD DX, 7 ; DX = Port0 +7
IN AL, DX
;Test0FFh
CMP AL, 0FFh
JNE Test07Fh
JMP NEXT_Ide ; If AL = 0FFh, IDE not present
; -> NEXT_Ide
Test07Fh:
CMP AL, 07Fh
JNE IdeExists
JMP NEXT_Ide ; If AL = 07Fh, IDE not present
; -> NEXT_Ide
IdeExists:
; --- Set value at the IdeExists area in output buffer ---
MOV BYTE PTR [ESI + EBX], 1 ; Ide_Exists = True
; --- Prepare MoS (Master or Slave) loop ---
; Initialize FOR_MoS counter
MOV ECX, 1 ; ECX = Slave
FOR_MoS: ; FOR MoS=1 DOWNTO 0
; --- Get bDevSelCmd for this disc ---
MOV DL, [bDevSelCmd_table + ECX] ; DL = DevSelCmd
MOV bDevSelCmd, DL
; --- Check if Disc exists ---
WaitWhileBusy
SelectDevice
WaitWhileBusy
CMP AL, 0
JNZ DiskExists
JMP NEXT_MoS ; If AL = 0, Disc not present
; -> NEXT_MoS
DiskExists:
; Compute Disk (= Ide*2 + MoS = EBX*2 + ECX)
MOV EAX, EBX ; EAX = Ide
SHL EAX, 1 ; EAX = Ide*2
ADD EAX, ECX ; EAX = Disk
; --- Set value at the DiscExists area in output buffer ---
MOV BYTE PTR [ESI + cDisk0_Exists + EAX], 1 ; Disk_Exists = True
; --- Prepare EDI as pointer
; to the area where info is to be stored --
; Compute Disk*512 (knowing that 512 = 2 ^9)
XCHG AH, AL ; Was: AL = Disk , Now: AH = Disk
; -> EAX = Disk* 2^8
SHL EAX, 1 ; EAX = Disk* 2^9
MOV EDI, ESI ; EDI = @Output buffer
ADD EDI, cDisk0_RawInfo ; EDI = @beginning of raw info area in output buffer
ADD EDI, EAX ; EDI = @raw info section for this Disc
; ----------------- Retrieve ---------
WaitWhileBusy
SelectDevice
SendGDIcmd cATA_GDIcmd
WaitWhileBusy
; check error status
MOV DX, [wPort0]
ADD DX, 7 ; DX = Port0 +7
IN AL, DX
TEST AL, cBit00
JZ RetrieveInfo
; ERR=1 -> try ATAPI GDI command
WaitWhileBusy
SelectDevice
SendGDIcmd cATAPI_GDIcmd
WaitWhileBusy
RetrieveInfo:
PUSH ECX ; keep MoS value
MOV ECX, 256
MOV DX, [wPort0]
CLD
REP INSW ; Retrieve (finally!)
POP ECX ; restore MoS value
NEXT_Mos:
;LOOP FOR_MoS
CMP ECX, 0
JE NEXT_Ide
DEC ECX
JMP FOR_MoS
NEXT_Ide:
;LOOP FOR_Ide
CMP EBX, 0
JE Exit_IdeLoop
DEC EBX
JMP FOR_Ide
Exit_IdeLoop:
; --- Restore flags and registers ---
POPFD
POPAD
RET
EndProc IdesInfo
VxD_LOCKED_CODE_ENDS
; ************
; ** DATA **
; ************
VxD_LOCKED_DATA_SEG
; --- Tables ---
wPorts_table WORD 1F0h, 170h, 1E8h, 168h ; IDE 1 - 4
bDevSelCmd_table BYTE 0A0h, 0B0h ; Master - Slave
; --- Variables ---
wPort0 WORD ? ; Port 0
bDevSelCmd BYTE ?
VxD_LOCKED_DATA_ENDS
END
DSIdeInf.DEF:
VXD DSIDEINF DYNAMIC
SEGMENTS
_LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
_LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
EXPORTS DSIDEINF_DDB @1
Y Finalmente, el Código en VB:
Private Declare Function Valid Lib "DSIdeInf.DLL" _
() As Byte
Private Declare Function IdeExists Lib "DSIdeInf.DLL" _
(ByVal a_Ide As Byte) As Byte
Private Declare Function DiskExists Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte) As Byte
Private Declare Function ATAdevice Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte) As Byte
Private Declare Function RemovableDevice Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte) As Byte
Private Declare Sub SerialNumber Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte, ByVal aP_SerialNumber As String)
Private Declare Sub FirmwareRevision Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte, ByVal aP_FirmwareRevision As String)
Private Declare Sub ModelNumber Lib "DSIdeInf.DLL" _
(ByVal a_Disk As Byte, ByVal aP_ModelNumber As String)
Private Sub btn_End_Click()
End
End Sub
Private Sub Form_Load()
Dim Ide, Disk As Byte
Dim sSerialNumber As String * 21
Dim sFirmwareRevision As String * 9
Dim sModelNumber As String * 41
Dim sCurLogCyl As String
If Valid = 0 Then
Mensaje = MsgBox("No se puede cargar el Archivo DSIdeInf.VXD, este archivo es necesario para la ejecución del programa, verifique que existe en la misma carpeta de el ejecutable. El programa se cerrará", vbExclamation + vbOKOnly + vbDefaultButton1 + vbApplicationModal, "No se Encuentra el archivo VXD")
End
End If
Disk = 1
' == Serial Number ===
Call SerialNumber(Disk, sSerialNumber)
Text1(0).Text = sSerialNumber
' == Firmware Revision ===
Call FirmwareRevision(Disk, sFirmwareRevision)
Text1(1).Text = sFirmwareRevision
' == Model ===
Call ModelNumber(Disk, sModelNumber)
Text1(2).Text = sModelNumber
End Sub
Fichero con el código en Delphi, Assambler y VB (DiskInf1.zip - 42.1 KB)