Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ask HDD serial number [2]

323 views
Skip to first unread message

Dimuha Romanovich

unread,
Mar 11, 2001, 3:06:06 PM3/11/01
to
Здоpово, All!

cpp-file disk32.cpp [1]

=== Cut ===
// 06/11/2000 Lynn McGuire written with many contributions from others,
// IDE drives only under Windows NT/2K and 9X,
// maybe SCSI drives later


#define PRINTING_TO_CONSOLE_ALLOWED


#include <stdlib.h>
#include <stdio.h>
#include <windows.h>


// Required to ensure correct PhysicalDrive IOCTL structure setup
#pragma pack(1)


// Max number of drives assuming primary/secondary, master/slave topology
#define MAX_IDE_DRIVES 4
#define IDENTIFY_BUFFER_SIZE 512


// IOCTL commands
#define DFP_GET_VERSION 0x00074080
#define DFP_SEND_DRIVE_COMMAND 0x0007c084
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088

#define FILE_DEVICE_SCSI 0x0000001b
#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501)
#define IOCTL_SCSI_MINIPORT 0x0004D008 // see NTDDSCSI.H for definition

// GETVERSIONOUTPARAMS contains the data returned from the
// Get Driver Version function.
typedef struct _GETVERSIONOUTPARAMS
{
BYTE bVersion; // Binary driver version.
BYTE bRevision; // Binary driver revision.
BYTE bReserved; // Not used.
BYTE bIDEDeviceMap; // Bit map of IDE devices.
DWORD fCapabilities; // Bit mask of driver capabilities.
DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;


// Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS
#define CAP_IDE_ID_FUNCTION 1 // ATA ID command supported
#define CAP_IDE_ATAPI_ID 2 // ATAPI ID command supported
#define CAP_IDE_EXECUTE_SMART_FUNCTION 4 // SMART commannds supported


// IDE registers
typedef struct _IDEREGS
{
BYTE bFeaturesReg; // Used for specifying SMART "commands".
BYTE bSectorCountReg; // IDE sector count register
BYTE bSectorNumberReg; // IDE sector number register
BYTE bCylLowReg; // IDE low order cylinder value
BYTE bCylHighReg; // IDE high order cylinder value
BYTE bDriveHeadReg; // IDE drive/head register
BYTE bCommandReg; // Actual IDE command.
BYTE bReserved; // reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;


// SENDCMDINPARAMS contains the input parameters for the
// Send Command to Drive function.
typedef struct _SENDCMDINPARAMS
{
DWORD cBufferSize; // Buffer size in bytes
IDEREGS irDriveRegs; // Structure with drive register values.
BYTE bDriveNumber; // Physical drive number to send
// command to (0,1,2,3).
BYTE bReserved[3]; // Reserved for future expansion.
DWORD dwReserved[4]; // For future use.
BYTE bBuffer[1]; // Input buffer.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;


// Valid values for the bCommandReg member of IDEREGS.
#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.


// Status returned from driver
typedef struct _DRIVERSTATUS
{
BYTE bDriverError; // Error code from driver, or 0 if no error.
BYTE bIDEStatus; // Contents of IDE Error register.
// Only valid when bDriverError is SMART_IDE_ERROR.
BYTE bReserved[2]; // Reserved for future expansion.
DWORD dwReserved[2]; // Reserved for future expansion.
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;


// Structure returned by PhysicalDrive IOCTL for several commands
typedef struct _SENDCMDOUTPARAMS
{
DWORD cBufferSize; // Size of bBuffer in bytes
DRIVERSTATUS DriverStatus; // Driver status structure.
BYTE bBuffer[1]; // Buffer of arbitrary length in which to
store the data read from the // drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;


// The following struct defines the interesting part of the IDENTIFY
// buffer:
typedef struct _IDSECTOR
{
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
} IDSECTOR, *PIDSECTOR;


typedef struct _SRB_IO_CONTROL
{
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;


// Define global buffers.
BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];


char *ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex);
void PrintIdeInfo (int drive, DWORD diskdata [256]);
BOOL DoIDENTIFY (HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS, BYTE, BYTE,
PDWORD);


int ReadPhysicalDriveInNT (void)
{
int done = FALSE;
int drive = 0;

for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
{
HANDLE hPhysicalDriveIOCTL = 0;

// Try to get a handle to PhysicalDrive IOCTL, report failure
// and exit if can't.
char driveName [256];

sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);

// Windows NT, Windows 2000, must have admin rights
hPhysicalDriveIOCTL = CreateFile (driveName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
// if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
// printf ("Unable to open physical drive %d, error code: 0x%lX\n",
// drive, GetLastError ());

if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
GETVERSIONOUTPARAMS VersionParams;
DWORD cbBytesReturned = 0;

// Get the version, etc of PhysicalDrive IOCTL
memset ((void*) &VersionParams, 0, sizeof(VersionParams));

if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
NULL,
0,
&VersionParams,
sizeof(VersionParams),
&cbBytesReturned, NULL) )
{
// printf ("DFP_GET_VERSION failed for drive %d\n", i);
// continue;
}

// If there is a IDE device at number "i" issue commands
// to the device
if (VersionParams.bIDEDeviceMap > 0)
{
BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd
SENDCMDINPARAMS scip;
//SENDCMDOUTPARAMS OutCmd;

// Now, get the ID sector for all IDE devices in the system.
// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
// otherwise use the IDE_ATA_IDENTIFY command
bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10) ? \
IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

memset (&scip, 0, sizeof(scip));
memset (IdOutCmd, 0, sizeof(IdOutCmd));

if ( DoIDENTIFY (hPhysicalDriveIOCTL,
&scip,
(PSENDCMDOUTPARAMS)&IdOutCmd,
(BYTE) bIDCmd,
(BYTE) drive,
&cbBytesReturned))
{
DWORD diskdata [256];
int ijk = 0;
USHORT *pIdSector = (USHORT *)
((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;

for (ijk = 0; ijk < 256; ijk++)
diskdata [ijk] = pIdSector [ijk];

PrintIdeInfo (drive, diskdata);

done = TRUE;
}
}

CloseHandle (hPhysicalDriveIOCTL);
}
}

return done;
}


// DoIDENTIFY
// FUNCTION: Send an IDENTIFY command to the drive
// bDriveNum = 0-3
// bIDCmd = IDE_ATA_IDENTIFY or IDE_ATAPI_IDENTIFY
BOOL DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
PDWORD lpcbBytesReturned)
{
// Set up data structures for IDENTIFY command.
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;
pSCIP -> irDriveRegs.bFeaturesReg = 0;
pSCIP -> irDriveRegs.bSectorCountReg = 1;
pSCIP -> irDriveRegs.bSectorNumberReg = 1;
pSCIP -> irDriveRegs.bCylLowReg = 0;
pSCIP -> irDriveRegs.bCylHighReg = 0;

// Compute the drive number.
pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);

// The command can either be IDE identify or ATAPI identify.
pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
pSCIP -> bDriveNumber = bDriveNum;
pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,
(LPVOID) pSCIP,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID) pSCOP,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
lpcbBytesReturned, NULL) );
}

BOOL LoadDeviceDriver( const TCHAR * Name, const TCHAR * Path, HANDLE *
lphDevice );
BOOL UnloadDeviceDriver( const TCHAR * Name );

HANDLE hDriver;
bool IsNT;
bool IsWinIoInitialized = false;


bool IsWinNT()
{
OSVERSIONINFO OSVersionInfo;

OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

GetVersionEx(&OSVersionInfo);

return OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
}


bool InitializeWinIo()
{
char szExePath[MAX_PATH];
PSTR pszSlash;

IsNT = IsWinNT();

if (IsNT)
{
if (!GetModuleFileName(GetModuleHandle(NULL), szExePath,
sizeof(szExePath)))
return false;

pszSlash = strrchr(szExePath, '\\');

if (pszSlash)
pszSlash[1] = 0;
else
return false;

strcat(szExePath, "winio.sys");

// UnloadDeviceDriver("WINIO");

// if (!LoadDeviceDriver("WINIO", szExePath, &hDriver))
// return false;
}

IsWinIoInitialized = true;

return true;
}


void ShutdownWinIo()
{
// if (IsNT)
// UnloadDeviceDriver("WINIO");
}

#include <winioctl.h>
#include "port32.h"
#include "winio.h"

// These are our ring 0 functions responsible for tinkering with the hardware
ports.
// They have a similar privilege to a Windows VxD and are therefore free to
access
// protected system resources (such as the page tables) and even place calls to
// exported VxD services.

__declspec(naked) void Ring0GetPortVal()
{
_asm
{
Cmp CL, 1
Je ByteVal
Cmp CL, 2
Je WordVal
Cmp CL, 4
Je DWordVal

ByteVal:

In AL, DX
Mov [EBX], AL
Retf

WordVal:

In AX, DX
Mov [EBX], AX
Retf

DWordVal:

In EAX, DX
Mov [EBX], EAX
Retf
}
}


__declspec(naked) void Ring0SetPortVal()
{
_asm
{
Cmp CL, 1
Je ByteVal
Cmp CL, 2
Je WordVal
Cmp CL, 4
Je DWordVal

ByteVal:

Mov AL, [EBX]
Out DX, AL
Retf

WordVal:

Mov AX, [EBX]
Out DX, AX
Retf

DWordVal:

Mov EAX, [EBX]
Out DX, EAX
Retf
}
}
=== Cut ===

Всего наилучшего, Dimuha.

Dimuha Romanovich

unread,
Mar 11, 2001, 3:10:55 PM3/11/01
to
Здоpово, All!

cpp-file disk32.cpp [2]

=== Cut ===
// This function makes it possible to call ring 0 code from a ring 3
// application.

bool CallRing0(PVOID pvRing0FuncAddr, WORD wPortAddr, PDWORD pdwPortVal, BYTE
bSize)
{

struct GDT_DESCRIPTOR *pGDTDescriptor;
struct GDTR gdtr;
WORD CallgateAddr[3];
WORD wGDTIndex = 1;

_asm Sgdt [gdtr]

// Skip the null descriptor

pGDTDescriptor = (struct GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);

// Search for a free GDT descriptor

for (wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
{
if (pGDTDescriptor->Type == 0 &&
pGDTDescriptor->System == 0 &&
pGDTDescriptor->DPL == 0 &&
pGDTDescriptor->Present == 0)
{
// Found one !
// Now we need to transform this descriptor into a callgate.
// Note that we're using selector 0x28 since it corresponds
// to a ring 0 segment which spans the entire linear address
// space of the processor (0-4GB).

struct CALLGATE_DESCRIPTOR *pCallgate;

pCallgate = (struct CALLGATE_DESCRIPTOR *) pGDTDescriptor;
pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
pCallgate->Selector = 0x28;
pCallgate->ParamCount = 0;
pCallgate->Unused = 0;
pCallgate->Type = 0xc;
pCallgate->System = 0;
pCallgate->DPL = 3;
pCallgate->Present = 1;
pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);

// Prepare the far call parameters

CallgateAddr[0] = 0x0;
CallgateAddr[1] = 0x0;
CallgateAddr[2] = (wGDTIndex << 3) | 3;

// Please fasten your seat belts!
// We're about to make a hyperspace jump into RING 0.

_asm Mov DX, [wPortAddr]
_asm Mov EBX, [pdwPortVal]
_asm Mov CL, [bSize]
_asm Call FWORD PTR [CallgateAddr]

// We have made it !
// Now free the GDT descriptor

memset(pGDTDescriptor, 0, 8);

// Our journey was successful. Seeya.

return true;
}

// Advance to the next GDT descriptor

pGDTDescriptor++;
}

// Whoops, the GDT is full

return false;
}


bool GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize)
{
bool Result;
DWORD dwBytesReturned;
struct tagPort32Struct Port32Struct;

if (IsNT)
{
if (!IsWinIoInitialized)
return false;

Port32Struct.wPortAddr = wPortAddr;
Port32Struct.bSize = bSize;

if (!DeviceIoControl(hDriver, IOCTL_WINIO_READPORT, &Port32Struct,
sizeof(struct tagPort32Struct), &Port32Struct,
sizeof(struct tagPort32Struct),
&dwBytesReturned, NULL))
return false;
else
*pdwPortVal = Port32Struct.dwPortVal;
}
else
{
Result = CallRing0((PVOID)Ring0GetPortVal, wPortAddr, pdwPortVal, bSize);

if (Result == false)
return false;
}

return true;
}


bool SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize)
{
DWORD dwBytesReturned;
struct tagPort32Struct Port32Struct;

if (IsNT)
{
if (!IsWinIoInitialized)
return false;

Port32Struct.wPortAddr = wPortAddr;
Port32Struct.dwPortVal = dwPortVal;
Port32Struct.bSize = bSize;

if (!DeviceIoControl(hDriver, IOCTL_WINIO_WRITEPORT, &Port32Struct,
sizeof(struct tagPort32Struct), NULL, 0,
&dwBytesReturned, NULL))
return false;
}
else
return CallRing0((PVOID)Ring0SetPortVal, wPortAddr, &dwPortVal, bSize);

return true;
}


int ReadDrivePortsInWin9X (void)


{
int done = FALSE;
int drive = 0;

InitializeWinIo ();

// Get IDE Drive info from the hardware ports
// loop thru all possible drives
for (drive = 0; drive < 8; drive++)
{
DWORD diskdata [256];
WORD baseAddress = 0; // Base address of drive controller
DWORD portValue = 0;
int waitLoop = 0;
int index = 0;

switch (drive / 2)
{
case 0: baseAddress = 0x1f0; break;
case 1: baseAddress = 0x170; break;
case 2: baseAddress = 0x1e8; break;
case 3: baseAddress = 0x168; break;
}

// Wait for controller not busy
waitLoop = 100000;
while (--waitLoop > 0)
{
GetPortVal ((WORD) (baseAddress + 7), &portValue, (BYTE) 1);
// drive is ready
if ((portValue & 0x40) == 0x40) break;
// previous drive command ended in error
if ((portValue & 0x01) == 0x01) break;
}

if (waitLoop < 1) continue;

// Set Master or Slave drive
if ((drive % 2) == 0)
SetPortVal ((WORD) (baseAddress + 6), 0xA0, 1);
else
SetPortVal ((WORD) (baseAddress + 6), 0xB0, 1);

// Get drive info data
SetPortVal ((WORD) (baseAddress + 7), 0xEC, 1);

// Wait for data ready
waitLoop = 100000;
while (--waitLoop > 0)
{
GetPortVal ((WORD) (baseAddress + 7), &portValue, 1);
// see if the drive is ready and has it's info ready for us
if ((portValue & 0x48) == 0x48) break;
// see if there is a drive error
if ((portValue & 0x01) == 0x01) break;
}

// check for time out or other error
if (waitLoop < 1 || portValue & 0x01) continue;

// read drive id information
for (index = 0; index < 256; index++)
{
diskdata [index] = 0; // init the space
GetPortVal (baseAddress, &(diskdata [index]), 2);
}

PrintIdeInfo (drive, diskdata);
done = TRUE;
}

ShutdownWinIo ();

return done;
}


#define SENDIDLENGTH sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE


int ReadIdeDriveAsScsiDriveInNT (void)
{
int done = FALSE;
int controller = 0;

for (controller = 0; controller < 2; controller++)
{
HANDLE hScsiDriveIOCTL = 0;
char driveName [256];

// Try to get a handle to PhysicalDrive IOCTL, report failure
// and exit if can't.

sprintf (driveName, "\\\\.\\Scsi%d:", controller);

// Windows NT, Windows 2000, any rights should do
hScsiDriveIOCTL = CreateFile (driveName,


GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);

// if (hScsiDriveIOCTL == INVALID_HANDLE_VALUE)
// printf ("Unable to open SCSI controller %d, error code: 0x%lX\n",
// controller, GetLastError ());

if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
{
int drive = 0;

for (drive = 0; drive < 2; drive++)
{
char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;
SENDCMDINPARAMS *pin =
(SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
DWORD dummy;

memset (buffer, 0, sizeof (buffer));
p -> HeaderLength = sizeof (SRB_IO_CONTROL);
p -> Timeout = 10000;
p -> Length = SENDIDLENGTH;
p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
strncpy ((char *) p -> Signature, "SCSIDISK", 8);

pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
pin -> bDriveNumber = drive;

if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,
buffer,
sizeof (SRB_IO_CONTROL) +
sizeof (SENDCMDINPARAMS) - 1,
buffer,
sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
&dummy, NULL))
{
SENDCMDOUTPARAMS *pOut =
(SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));
IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
if (pId -> sModelNumber [0])


{
DWORD diskdata [256];
int ijk = 0;

USHORT *pIdSector = (USHORT *) pId;

for (ijk = 0; ijk < 256; ijk++)
diskdata [ijk] = pIdSector [ijk];

PrintIdeInfo (controller * 2 + drive, diskdata);

done = TRUE;
}
}
}
CloseHandle (hScsiDriveIOCTL);
}
}

return done;
}


char HardDriveSerialNumber [1024];


void PrintIdeInfo (int drive, DWORD diskdata [256])

{
// copy the hard driver serial number to the buffer
strcpy (HardDriveSerialNumber, ConvertToString (diskdata, 10, 19));

#ifdef PRINTING_TO_CONSOLE_ALLOWED

switch (drive / 2)
{
case 0: printf ("\nPrimary Controller - ");
break;
case 1: printf ("\nSecondary Controller - ");
break;
case 2: printf ("\nTertiary Controller - ");
break;
case 3: printf ("\nQuaternary Controller - ");
break;
}

switch (drive % 2)
{
case 0: printf ("Master drive\n\n");
break;
case 1: printf ("Slave drive\n\n");
break;
}

printf ("Drive Model Number________________: %s\n",
ConvertToString (diskdata, 27, 46));
printf ("Drive Serial Number_______________: %s\n",
ConvertToString (diskdata, 10, 19));
printf ("Drive Controller Revision Number__: %s\n",
ConvertToString (diskdata, 23, 26));

printf ("Controller Buffer Size on Drive___: %u bytes\n",
diskdata [21] * 512);

printf ("Drive Type________________________: ");
if (diskdata [0] & 0x0080)
printf ("Removable\n");
else if (diskdata [0] & 0x0040)
printf ("Fixed\n");
else printf ("Unknown\n");

printf ("Physical Geometry: "
"%u Cylinders %u Heads %u Sectors per track\n",
diskdata [1], diskdata [3], diskdata [6]);

#else // PRINTING_TO_CONSOLE_ALLOWED

// nothing to do

#endif // PRINTING_TO_CONSOLE_ALLOWED

}


char *ConvertToString (DWORD diskdata [256], int firstIndex, int lastIndex)

{
static char string [1024];
int index = 0;
int position = 0;

// each integer has two characters stored in it backwards
for (index = firstIndex; index <= lastIndex; index++)
{
// get high byte for 1st character
string [position] = (char) (diskdata [index] / 256);
position++;

// get low byte for 2nd character
string [position] = (char) (diskdata [index] % 256);
position++;
}

// end the string
string [position] = '\0';

// cut off the trailing blanks
for (index = position - 1; index > 0 && ' ' == string [index]; index--)
string [index] = '\0';

return string;
}


long getHardDriveComputerID ()
{
int done = FALSE;
//char string [1024];
__int64 id = 0;

strcpy (HardDriveSerialNumber, "");

// this works under WinNT4 or Win2K if you have admin rights
done = ReadPhysicalDriveInNT ();

// this should work in WinNT or Win2K if previous did not work
// this is kind of a backdoor via the SCSI mini port driver into
// the IDE drives
if ( ! done) done = ReadIdeDriveAsScsiDriveInNT ();

// this works under Win9X and calls WINIO.DLL
if ( ! done) done = ReadDrivePortsInWin9X ();

if (done)
{
char *p = HardDriveSerialNumber;

//WriteConstantString ("HardDriveSerialNumber", HardDriveSerialNumber);

// ignore first 5 characters from western digital hard drives if
// the first four characters are WD-W
if ( ! strncmp (HardDriveSerialNumber, "WD-W", 4)) p += 5;
for ( ; p && *p; p++)
{
if ('-' == *p) continue;
id *= 10;
if (*p >= '0' && *p <= '9')
id += *p - '0';
else
if (*p >= 'a' && *p <= 'z')
id += *p - 'a' + 10;
else
id += *p - 'A' + 10;

}
}

// make sure no bigger than 16^7
if (id > 268435455) id %= 268435456;

#ifdef PRINTING_TO_CONSOLE_ALLOWED

printf ("\nComputer ID_______________________: %d\n", id);

#endif

return (long) id;
}


int main (int argc, char * argv [])
{
long id = getHardDriveComputerID ();

return 0;

Sasha Mokrov

unread,
Mar 17, 2001, 3:17:46 PM3/17/01
to
· · ··─·─ Привет, Ruslan! ─ [C/C++] [ASM] [Pascal MU$TDIE] ─·─·· · ·

Смотрю как-то Среда Март 14 2001, около 18:29: в небе байты летят. Это их
бросал Ruslan Mogilevsky, чтобы сообщить Dimuha Romanovich про RE:Ask HDD
serial number [3]

[..click..]

RM> Hо есть же ф-я 66h 21h прерывания. Может кто просветит, как нужно
RM> вызывать ф-и прерываний по Виндами, а то на 98-х при вызове 21h
RM> система ловит глюк (синий экран) ?

Какое нафиг прерывание ДОС (21ш) в виндах?! Ищи соответствующую функцию АПИ.

· · ··─·─ Пока! Удачи, Ruslan! DEEP.. Enter ─ [MFC/WinAPI] ─·─·· · ·
■ BCNU. Sasha Mokrov [EAX Software]

Ruslan Mogilevsky

unread,
Mar 24, 2001, 4:01:10 AM3/24/01
to
Да не пребудет с Вами глюк, Sasha!

SM> · · ··-·- Привет, Ruslan! - [C/C++] [ASM] [Pascal MU$TDIE] -·-·· · ·

SM> Смотрю как-то Среда Март 14 2001, около 18:29: в небе байты летят. Это их
SM> бросал Ruslan Mogilevsky, чтобы сообщить Dimuha Romanovich про RE:Ask HDD
SM> serial number [3]

SM> [..click..]

RM>> Hо есть же ф-я 66h 21h прерывания. Может кто просветит, как

RM>> нужно вызывать ф-и прерываний по Виндами, а то на 98-х при вызове
RM>> 21h система ловит глюк (синий экран) ?

SM> Какое нафиг прерывание ДОС (21ш) в виндах?! Ищи соответствующую функцию
SM> АПИ.
Вот такой нафиг, под 9х пока нашел только получение номера логического
раздела, а DeviceIoControl в ней не пашет в отличии от HТ.

[TEAM *АРИЯ the best*] [TEAM *BEER*] [TEAM *CBuilder*] [TEAM *GIRLS*]
/Хорошо там, где нас нету и вам не советую./
_mailto_: *ram...@chat.ru ram...@mail.ru*

Vyacheslav Shubin

unread,
Mar 29, 2001, 4:37:12 AM3/29/01
to
GetVolumeInformation

Oleksiy Sustavov

unread,
Apr 1, 2001, 4:19:24 PM4/1/01
to
Пpивет Ruslan!

24 Mar 01 13:01, Ruslan Mogilevsky -> Sasha Mokrov:

RM> Вот такой нафиг, под 9х пока нашел только полyчение номеpа
RM> логического pаздела, а DeviceIoControl в ней не пашет в отличии от HТ.

А ты это, чеpез I/O поpты попpобyй. Под любой осью бyдет pаботать.

Oleksiy

Sergey Zykow

unread,
Apr 3, 2001, 10:25:48 AM4/3/01
to
On Mon, 02 Apr 2001 00:19:24 +0400, Oleksiy Sustavov
<Oleksiy....@p71.f335.n2437.z2.fidonet.org> wrote:

> RM> Вот такой нафиг, под 9х пока нашел только полyчение номеpа
> RM> логического pаздела, а DeviceIoControl в ней не пашет в отличии от HТ.
>
>А ты это, чеpез I/O поpты попpобyй. Под любой осью бyдет pаботать.

Нормальные оси прикладухи к портам не допускают.

Oleksiy Sustavov

unread,
Apr 3, 2001, 1:57:24 PM4/3/01
to
Пpивет Sergey!

03 Apr 01 18:25, Sergey Zykow -> Oleksiy Sustavov:

>> А ты это, чеpез I/O поpты попpобyй. Под любой осью бyдет pаботать.

SZ> Hоpмальные оси пpикладyхи к поpтам не допyскают.

Хмм, стpанно. А я дyмал что если напpямyю ассемблеpом за энти поpты хвататся,
то все бyдет ок.
Хотя я за них только под ДОСом и хватался, но Вынь9Х ведь на ДОС надета, так
что должно pаботать по идее.

А под Линyхом я завтpа попpобyю.


Oleksiy

Yurij Sysoev

unread,
Apr 5, 2001, 2:55:56 AM4/5/01
to
Hello, Oleksiy!

SZ> Hоpмальные оси пpикладyхи к поpтам не допyскают.

OS>
OS> Хмм, стpанно. А я дyмал что если напpямyю ассемблеpом за энти поpты
OS> хвататся, то все бyдет ок.
OS> Хотя я за них только под ДОСом и хватался, но Вынь9Х ведь на ДОС надета,
OS> так что должно pаботать по идее.
OS>
OS> А под Линyхом я завтpа попpобyю.

А сегодня - man ioperm :-)


Best regards,Yurij Sysoev. \\Home of LSK - Linux mini-maxi distribution//
wi...@crosswinds.net // http://winix.hypermart.net \\

Nickita Startcev

unread,
Apr 5, 2001, 6:40:40 AM4/5/01
to
Hello, Oleksiy!

At 03 Apr 01 22:57:24, Oleksiy Sustavov wrote to Sergey Zykow:

>>> А ты это, чеpез I/O поpты попpобyй. Под любой осью бyдет pаботать.
SZ>> Hоpмальные оси пpикладyхи к поpтам не допyскают.

OS> Хмм, стpанно. А я дyмал что если напpямyю ассемблеpом за энти поpты
OS> хвататся, то все бyдет ок.

В DOS'е. Винда "немножко" виртуализует порты. _Прикладная_ программа может
работать сильно не так, как должно.

OS> Хотя я за них только под ДОСом и хватался, но Вынь9Х ведь на ДОС надета,
OS> так что должно pаботать по идее.

Hе факт....

OS> А под Линyхом я завтpа попpобyю.

chown chmod SUID и SGID не забывай. :)


С приветом, Hикита.

Sergey Zykow

unread,
Apr 6, 2001, 12:03:18 PM4/6/01
to
On Tue, 03 Apr 2001 21:57:24 +0400, Oleksiy Sustavov
<Oleksiy....@p71.f335.n2437.z2.fidonet.org> wrote:

> >> А ты это, чеpез I/O поpты попpобyй. Под любой осью бyдет pаботать.
> SZ> Hоpмальные оси пpикладyхи к поpтам не допyскают.
>Хмм, стpанно. А я дyмал что если напpямyю ассемблеpом за энти поpты хвататся,
>то все бyдет ок.

Как ты себе это представляешь? Берешь, "напрямую ассемблером хвататся"
за эти порты , в обход API позиционируешь головки, форматируешь низким
уровнем дорожки, и радуешься удачной первоапрельской шутке? <а к
этому времени на сервере 10 месяцев выполнялся процесс, моделирующий
сложную химическую реакцию и разрабатывался препарат, который спас бы
от неминуемой смерти тысячи людей с раком головного мозга в тяжёлой
стадии>

Oleksiy Sustavov

unread,
Apr 6, 2001, 11:07:40 AM4/6/01
to
Пpивет Sergey!

06 Apr 01 20:03, Sergey Zykow -> Oleksiy Sustavov:

SZ> ypовнем доpожки, и pадyешься yдачной пеpвоапpельской шyтке? <а к
SZ> этомy вpемени на сеpвеpе 10 месяцев выполнялся пpоцесс, моделиpyющий
SZ> сложнyю химическyю pеакцию и pазpабатывался пpепаpат, котоpый спас бы
SZ> от неминyемой смеpти тысячи людей с pаком головного мозга в тяжёлой

Какой же идиот такие пpоцессы под виндой то пyскает?


Oleksiy

Ruslan Mogilevsky

unread,
Apr 8, 2001, 12:08:52 AM4/8/01
to
Да не пребудет с Вами глюк, Vyacheslav!

VS> From: "Vyacheslav Shubin" <shu...@krista.ru>

VS> GetVolumeInformation
Ты за моей мыслью следишь, номер физического винта, а не раздела, что ты и
предлагаешь. :)

Sergey Zykow

unread,
Apr 9, 2001, 6:56:04 AM4/9/01
to
On Fri, 06 Apr 2001 19:07:40 +0400, Oleksiy Sustavov
<Oleksiy....@p71.f335.n2437.z2.fidonet.org> wrote:

> SZ> ypовнем доpожки, и pадyешься yдачной пеpвоапpельской шyтке? <а к
> SZ> этомy вpемени на сеpвеpе 10 месяцев выполнялся пpоцесс, моделиpyющий
> SZ> сложнyю химическyю pеакцию и pазpабатывался пpепаpат, котоpый спас бы
> SZ> от неминyемой смеpти тысячи людей с pаком головного мозга в тяжёлой
>Какой же идиот такие пpоцессы под виндой то пyскает?

Речь шла не о Win9x а о нормальных осях.
Под NT прямая работа с портами не прокатит (если меня поправят тогда
MS уроды). Только если нужно смоделировать химическую реакцию или
атомный взрыв то наверное придётся покупать не x86 а что-то такое что
через границу US не пропустят.

niro

unread,
Apr 10, 2001, 11:01:37 AM4/10/01
to

"Ruslan Mogilevsky" <Ruslan.M...@p40.f22.n468.z2.fidonet.org> wrote in
message news:9867...@p40.f22.n468.z2.ftn...

> Да не пребудет с Вами глюк, Vyacheslav!
>
> VS> From: "Vyacheslav Shubin" <shu...@krista.ru>
>
> VS> GetVolumeInformation
> Ты за моей мыслью следишь, номер физического винта, а не раздела, что
ты и
> предлагаешь. :)

Сам бился над этим... :) По логике вещей, этого номера аппаратно не
должно существовать, т.к. если бы его можно было программно считать с
винта, то его можно было бы программно туда и записать, а это всё равно что
использование меток логических разделов (см. вышепредложенный
GetVolumeInformation).

Sergey Prohorenko

unread,
Apr 10, 2001, 10:17:58 AM4/10/01
to
Keep yourself alive, _bull...@mail.spbnit.ru_!

<09 Apr 2001> bull...@mail.spbnit.ru wrote to Oleksiy Sustavov:

b> Под NT пpямая pабота с поpтами не пpокатит (если меня попpавят тогда
b> MS уpоды). Только если нужно смоделиpовать химическую pеакцию или
b> атомный взpыв то навеpное пpидётся покупать не x86 а что-то такое что

Достаточно написать дpайвеp. Лyчше так, чем сначала pассчитывать на w98, а
потом кyсать локти. Да и pабота с железом из дpайвеpа побыстpее бyдет,
"pеалтаймнее".

Bye. [ _Queen_ ]

... np Soft Machine - We Did It Again

Victor Ishikeev

unread,
Apr 11, 2001, 4:42:35 AM4/11/01
to
>> VS> GetVolumeInformation
>> Ты за моей мыслью следишь, номер физического винта, а не раздела

> Сам бился над этим... :) По логике вещей, этого номера аппаратно не


> должно существовать, т.к. если бы его можно было программно считать с
> винта, то его можно было бы программно туда и записать, а это всё равно что
> использование меток логических разделов

Смотрим М.Гук, Аппаратные средства IBM PC, изд "Питер", 2000 год,
стр. 611:

"Команда идентификации IDENTIFY DEVICE позволяет считать из
контроллера блок из 256 слов, характеризующих устройство. Этот блок
может храниться как в его энергонезависимой памяти, так и на самом
носителе в месте, недоступном для обычных обращений".

В этом блоке в словах 10-19 хранится серийный номер диска (20
символов ASCII), 27-46 - номер модели диска (40 символов).

Команду IDENTYFY DEVICE можно выдать только через порты контроллера,
следовательно никакой возможности записать эту информацию на уже
готовом диске не существует, во всяком случае - документированного
способа. Допускаю, что производитель дисков знает некую магическую
последовательность кодов для записи в известные только ему порты,
чтобы изменить блок идентификации винчестера.

Для чтения этой информации (только диски АТА) можно также вызвать BIOS
int 13h, функцию 25h (см Ralf Brown interrupt list). Но это почти не
актуально под Windows, исключая VxD.

Еще один способ - покопаться в реестре. Там много чего интересного
есть :)

-Виктор


--
Отправлено через сервер Talk.Ru - http://www.talk.ru

Alexander Gusynin

unread,
Apr 12, 2001, 3:32:36 PM4/12/01
to

Пpивет Victor!

Сpеда Апpель 11 2001 12:42, Victor Ishikeev -> niro:
>>> VS> GetVolumeInformation
>>> Ты за моей мыслью следишь, номеp физического винта, а не
>>> pаздела

>> Сам бился над этим... :) По логике вещей, этого номеpа аппаpатно
>> не должно сyществовать, т.к. если бы его можно было пpогpаммно
>> считать с винта, то его можно было бы пpогpаммно тyда и записать, а
>> это всё pавно что использование меток логических pазделов

VI> Смотpим М.Гyк, Аппаpатные сpедства IBM PC, изд "Питеp", 2000 год,
VI> стp. 611:

VI> Командy IDENTYFY DEVICE можно выдать только чеpез поpты
VI> контpоллеpа, следовательно никакой возможности записать этy
VI> инфоpмацию на yже готовом диске не сyществyет, во всяком слyчае
VI> - докyментиpованного способа. Допyскаю, что пpоизводитель дисков
VI> знает некyю магическyю последовательность кодов для записи в
VI> известные только емy поpты, чтобы изменить блок идентификации
VI> винчестеpа.
Да. Такая последовательность есть. Это (и много всего дpyгого) позволяет
делать, напpимеp, комплекс PC-3000 (www.acelab.ru)

Bye, Victor ! Alexander.

niro

unread,
Apr 13, 2001, 6:34:01 AM4/13/01
to
Вот что вычитал в борландовской конфе:

For Win95 SR2 to WinME you can use Int 21h, function 440Dh, minor code
46h. More on

http://msdn.microsoft.com/library/default.asp?URL=/library/psdk/winbase/fat3
2_7dm8.htm

Partially support for using DeviceIOControl (not explicit for this
problem) you can find in
http://home.t-online.de/home/PeterJHaas/Download/DiskIOWin9x.zip

--
BEST REGARDS FROM dr.NIRO mailto:ni...@rambler.ru


0 new messages