//HDSerialNumRead.cpp//PS:支持WIN 9X/NT/2K/XP及SCSI硬盘,在WIN NT/2K/XP(需admin)。 // 作者: 张阳 [email protected] 2002/2/7//功能实现不错,代码编写较差,更正两处严重缺陷 // 一处返回了局部对像的引用、一处函数调用书写错误(变成了函数指针) // 函数的参数传递不好、对失败情况也没有办法准确获知 // hss 2003.8.19#include <stdafx.h> #include <windows.h> #include <dos.h> #include "HDSerialNumRead.h" #define SENDIDLENGTH sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE #define IDENTIFY_BUFFER_SIZE 512 #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 #define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI. #define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA. #define DFP_RECEIVE_DRIVE_DATA 0x0007c088 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 _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; 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; typedef struct _SRB_IO_CONTROL { ULONG HeaderLength; UCHAR Signature[8]; ULONG Timeout; ULONG ControlCode; ULONG ReturnCode; ULONG Length; } SRB_IO_CONTROL, *PSRB_IO_CONTROL; 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;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; 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;WORD serial[256]; DWORD OldInterruptAddress; DWORDLONG IDTR; void _stdcall ReadIdeSerialNumber(); static unsigned int WaitHardDiskIde() { BYTE xx;Waiting: __asm{ mov dx, 0x1f7 in al, dx cmp al, 0x80 jb Endwaiting jmp Waiting } Endwaiting: __asm{ mov xx, al } return xx; } void __declspec( naked ) InterruptProcess(void)//中断服务程序 { int xx; int i; WORD temp; //保存寄存器值 __asm { push eax push ebx push ecx push edx push esi }
WaitHardDiskIde();//等待硬盘空闲状态 __asm{ mov dx, 0x1f6 mov al, 0xa0 out dx, al } xx = WaitHardDiskIde(); //若直接在Ring3级执行等待命令,会进入死循环 if ((xx&0x50)!=0x50) { __asm{ pop esi pop edx pop ecx pop ebx pop eax iretd } }
__asm{ mov dx, 0x1f6 //命令端口1f6,选择驱动器0 mov al, 0xa0 out dx, al inc dx mov al, 0xec out dx, al //发送读驱动器参数命令 }
xx = WaitHardDiskIde(); if ((xx&0x58)!=0x58) { __asm{ pop esi pop edx pop ecx pop ebx pop eax iretd } } //读取硬盘控制器的全部信息 for (i=0;i<256;i++) { __asm{ mov dx, 0x1f0 in ax, dx mov temp, ax } serial[i] = temp; }
__asm{ pop esi pop edx pop ecx pop ebx pop eax iretd }
//_asm iretd }
int Win9xHDSerialNumRead(WORD * buffer) { int i; for(i=0;i<256;i++) buffer[i]=0; ReadIdeSerialNumber(); for(i=0;i<256;i++) buffer[i]=serial[i]; return 1; } void _stdcall ReadIdeSerialNumber() { _asm { push eax //获取修改的中断的中断描述符(中断门)地址 sidt IDTR mov eax,dword ptr [IDTR+02h] add eax,3*08h+04h cli //保存原先的中断入口地址 push ecx mov ecx,dword ptr [eax] mov cx,word ptr [eax-04h] mov dword ptr OldInterruptAddress,ecx pop ecx //设置修改的中断入口地址为新的中断处理程序入口地址 push ebx lea ebx,InterruptProcess mov word ptr [eax-04h],bx shr ebx,10h mov word ptr [eax+02h],bx pop ebx //执行中断,转到Ring 0(类似CIH病毒原理) int 3h //恢复原先的中断入口地址 push ecx mov ecx,dword ptr OldInterruptAddress mov word ptr [eax-04h],cx shr ecx,10h mov word ptr [eax+02h],cx pop ecx sti pop eax } }
char *ConvertToString (WORD 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; }char *ConvertToString2 (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; }int WinNTHDSerialNumAsScsiRead (DWORD * buffer) {
buffer[0]='\n'; 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); // driveName="\\\\.\\Scsi0"; // 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);
{
CComboBox* Driver=(CComboBox*)GetDlgItem(IDC_DRIVER);
DWORD dwNumBytesForDriveStrings;//实际存储驱动器号的字符串长度
HANDLE hHeap;
LPSTR lp;
CString strLogdrive; //获得实际存储驱动器号的字符串长度
dwNumBytesForDriveStrings=GetLogicalDriveStrings(0,NULL)*sizeof(TCHAR); //如果字符串不为空,则表示有正常的驱动器存在
if (dwNumBytesForDriveStrings!=0) {
//分配字符串空间
hHeap=GetProcessHeap();
lp=(LPSTR)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,
dwNumBytesForDriveStrings); //获得标明所有驱动器的字符串
GetLogicalDriveStrings(HeapSize(hHeap,0,lp),lp); //将驱动器一个个放到下拉框中
while (*lp!=0) {
Driver->AddString(lp);
lp=_tcschr(lp,0)+1;
}
}
else
AfxMessageBox("Can't Use The Function GetLogicalDriveStrings!");
}
获得序列号
{
CDialog::OnInitDialog();
CString DisplayString;
SYSTEM_INFO SystemInfo;
//检测CPU的类型
::GetSystemInfo(&SystemInfo); //WinAPI函数,用以取得系统信息
if(SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
switch (SystemInfo.wProcessorLevel)
{
//本程序只演示取得Intel系列CPU的方法 // ……
//省略对386及486机器的检测
case 5:
DisplayString = "Pentium";
break;
case 6:
DisplayString = "Pentium (II/Pro)";
break;
case 7:
DisplayString = "Pentium (III/Pro)";
break;
case 15:
DisplayString = "Pentium IV";
break;
}
}
m_CpuType.SetWindowText(DisplayString); //变量m_CpuType是一个CStatic框 //检测内存状态
MEMORYSTATUS MemoryStatus; //内存的现行状态结构
MemoryStatus.dwLength = sizeof(MEMORYSTATUS); //填充结构的大小
::GlobalMemoryStatus(&MemoryStatus); //取得内存的状态
char buffer[20];
wsprintf(buffer,"%d M",MemoryStatus.dwTotalPhys/1024/1024);//dwTotalPhys指示物理内存字节 m_Memory.SetWindowText(buffer); //变量m_Memory是一个CStatic框
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
// 侯思松 2003.8.14//-------------------------------------------------------------------------------------
// 更新:侯思松 2003.09.05#include <algorithm>//CPU信息
namespace CPUInfo
{
// 测试CPU是否支持CPUID指令
// 从586起CPU开始支持CPUID指令,该指令可以用来获取CPU的很多信息
inline bool CPUSupportCPUID()
{
static bool IsCPUSupportCPUID=false;
static bool IsTest=false;
if (IsTest)
return IsCPUSupportCPUID;
else
{
UINT CPUIDInfOld ;
UINT CPUIDInfNew ;
__asm
{
pushfd // 保存原 EFLAGS
pop eax
mov edx,eax
mov CPUIDInfOld,eax // xor eax,00200000h // 改写 第21位
push eax
popfd // 改写 EFLAGS pushfd // 保存新 EFLAGS
pop eax
mov CPUIDInfNew,eax push edx // 恢复原 EFLAGS
popfd
}
IsCPUSupportCPUID=(CPUIDInfOld!=CPUIDInfNew);// EFLAGS 第21位 是否可以改写
IsTest=true;
return (IsCPUSupportCPUID);
}
}
//判断CPU是否有FPU(数学协处理器)
inline bool CPUSupportFPU()
{
if (!CPUSupportCPUID()) return false;
int FPUInf;
__asm{
push ebx
mov eax,1
cpuid
mov FPUInf,edx
pop ebx
}
FPUInf=FPUInf & (1<<0); //检测edx第0位
return FPUInf==(1<<0);
}
// 获取CPU家族号
inline int GetCPUFamily() //获得CPU Family (?86)
{
//3 - 386 4 - i486 5 - Pentium ... 6 - Pentium Pro or Pentium II ... 2 - Dual Processors
if (!CPUSupportCPUID()) return 0;
int CPUFamily;
__asm
{
push ebx
mov eax,1
cpuid
mov CPUFamily,eax
pop ebx
}
CPUFamily=(CPUFamily & 0xf00) >> 8 ;
return CPUFamily ;
} //取得CPU OEM字符串,判断CPU厂商
inline const char* GetCPUOEMString()
{
static char OEMString[13]={0,0,0,0,0,0,0,0,0,0,0,0,0};
char* p=&OEMString[0];
if (!CPUSupportCPUID()) return p;
__asm
{
push ebx xor eax,eax
cpuid
mov eax,p
mov [eax],ebx
mov [eax+4],edx
mov [eax+8],ecx
pop ebx
}
return p;
} //取得CPU序列号 96bit,有可能处于关闭状态
inline const unsigned char* GetCPUSerialNumber()
{
static unsigned char SerialNumber[13]={0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned char* p=&SerialNumber[0];
if (!CPUSupportCPUID()) return p;
__asm
{
push ebx mov eax,1
cpuid
mov ebx,p
mov [ebx],eax mov eax,3
cpuid
mov ebx,p
mov [ebx+4],edx
mov [ebx+8],ecx pop ebx
}
return p;
} //判断CPU是否支持MMX指令
inline bool CPUSupportMMX()
{
if (!CPUSupportCPUID()) return false;
int MMXInf;
__asm{
push ebx
mov eax,1
cpuid
mov MMXInf,edx
pop ebx
}
MMXInf=MMXInf & (1 << 23); //检测edx第23位
return (MMXInf==0x800000);
} //判断CPU是否支持SSE指令
inline bool CPUSupportSSE()
{
if (!CPUSupportCPUID()) return false;
int SSEInf;
__asm{
push ebx
mov eax,1
cpuid
mov SSEInf,edx
pop ebx
}
SSEInf=SSEInf & (1 << 25); //检测edx第25位
return SSEInf==(1 << 25);
} //判断CPU是否支持SSE2指令
inline bool CPUSupportSSE2()
{
if (!CPUSupportCPUID()) return false;
int SSE2Inf;
__asm{
push ebx
mov eax,1
cpuid
mov SSE2Inf,edx
pop ebx
}
SSE2Inf =SSE2Inf & (1 << 26); //检测edx第26位
return SSE2Inf==(1 << 26);
} //判断SYS是否支持SSE指令
// (SSE指令还需要操作系统配合支持才能使用,这是由于SSE指令使用了新的寄存器)
inline bool SYSSupportSSE()
{
//用触发异常的方式来检测
try
{
__asm
{
//0F10C0 movups xmm0,xmm0
_emit 0x0F
_emit 0x10
_emit 0xC0
}
return true;
}
catch(...)
{
return false;
}
} //判断CPU是否支持MMX2指令
inline bool CPUSupportMMX2()
{
if (!CPUSupportCPUID()) return false;
UINT MMX2Inf;
__asm{
push ebx
mov eax,0x80000000
cpuid
mov MMX2Inf,eax
pop ebx
}
if (MMX2Inf>0x80000000)
{
__asm{
push ebx
mov eax,0x80000001
cpuid
mov MMX2Inf,edx
pop ebx
}
MMX2Inf =MMX2Inf & (1 << 22); //检测edx第22位
return (MMX2Inf==(1 << 22));
}
else
return false;
} //判断CPU是否支持3DNow!指令
inline bool CPUSupport3DNow()
{
if (!CPUSupportCPUID()) return false;
UINT M3DNowInf;
__asm{
push ebx
mov eax,0x80000000
cpuid
mov M3DNowInf,eax
pop ebx
}
if (M3DNowInf>0x80000000)
{
__asm{
push ebx
mov eax,0x80000001
cpuid
mov M3DNowInf,edx
pop ebx
}
M3DNowInf =M3DNowInf & (1 << 31); //检测edx第31位
return (M3DNowInf==(1 << 31));
}
else
return false;
}
//判断CPU是否支持3DNow2指令
inline bool CPUSupport3DNow2()
{
if (!CPUSupportCPUID()) return false;
UINT M3DNow2Inf;
__asm{
push ebx
mov eax,0x80000000
cpuid
mov M3DNow2Inf,eax
pop ebx
}
if (M3DNow2Inf>0x80000000)
{
__asm{
push ebx
mov eax,0x80000001
cpuid
mov M3DNow2Inf,edx
pop ebx
}
M3DNow2Inf =M3DNow2Inf & (1 << 30); //检测edx第30位
return (M3DNow2Inf==(1 << 30));
}
else
return false;
}
}
struct CCPUInfo
{
DWORD CPUID;
DWORD FPU;
INT Family;
DWORD MMX;
DWORD MMX2;
DWORD SSE;
DWORD SSE2;
DWORD _3DNow;
DWORD _3DNow2;
BYTE SerialNumber[12];
char OEMString[13];
CCPUInfo()
{
using namespace CPUInfo;
CPUID=CPUSupportCPUID();
FPU=CPUSupportFPU();
Family=GetCPUFamily();
MMX=CPUSupportMMX();
MMX2=CPUSupportMMX2();
SSE=CPUSupportSSE();
SSE2=CPUSupportSSE2();
_3DNow=CPUSupport3DNow();
_3DNow2=CPUSupport3DNow2(); const char * pc=GetCPUOEMString();
std::copy(pc,pc+13,OEMString);
const BYTE * pb=GetCPUSerialNumber();
std::copy(pb,pb+12,SerialNumber);
}
};
// 作者: 张阳 [email protected] 2002/2/7//功能实现不错,代码编写较差,更正两处严重缺陷
// 一处返回了局部对像的引用、一处函数调用书写错误(变成了函数指针)
// 函数的参数传递不好、对失败情况也没有办法准确获知
// hss 2003.8.19#include <stdafx.h>
#include <windows.h>
#include <dos.h>
#include "HDSerialNumRead.h"
#define SENDIDLENGTH sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
#define IDENTIFY_BUFFER_SIZE 512
#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
#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088 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 _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; 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;
typedef struct _SRB_IO_CONTROL
{
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;
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;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;
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;WORD serial[256];
DWORD OldInterruptAddress;
DWORDLONG IDTR;
void _stdcall ReadIdeSerialNumber();
static unsigned int WaitHardDiskIde()
{
BYTE xx;Waiting:
__asm{
mov dx, 0x1f7
in al, dx
cmp al, 0x80
jb Endwaiting
jmp Waiting
}
Endwaiting:
__asm{
mov xx, al
} return xx;
}
void __declspec( naked ) InterruptProcess(void)//中断服务程序
{
int xx;
int i;
WORD temp;
//保存寄存器值
__asm
{
push eax
push ebx
push ecx
push edx
push esi
}
WaitHardDiskIde();//等待硬盘空闲状态
__asm{
mov dx, 0x1f6
mov al, 0xa0
out dx, al
}
xx = WaitHardDiskIde(); //若直接在Ring3级执行等待命令,会进入死循环
if ((xx&0x50)!=0x50)
{
__asm{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
__asm{
mov dx, 0x1f6 //命令端口1f6,选择驱动器0
mov al, 0xa0
out dx, al
inc dx
mov al, 0xec
out dx, al //发送读驱动器参数命令
}
xx = WaitHardDiskIde();
if ((xx&0x58)!=0x58)
{
__asm{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
}
//读取硬盘控制器的全部信息
for (i=0;i<256;i++) {
__asm{
mov dx, 0x1f0
in ax, dx
mov temp, ax
}
serial[i] = temp;
}
__asm{
pop esi
pop edx
pop ecx
pop ebx
pop eax
iretd
}
//_asm iretd
}
int Win9xHDSerialNumRead(WORD * buffer)
{
int i;
for(i=0;i<256;i++)
buffer[i]=0;
ReadIdeSerialNumber();
for(i=0;i<256;i++)
buffer[i]=serial[i];
return 1;
}
void _stdcall ReadIdeSerialNumber()
{
_asm
{
push eax
//获取修改的中断的中断描述符(中断门)地址
sidt IDTR
mov eax,dword ptr [IDTR+02h]
add eax,3*08h+04h
cli
//保存原先的中断入口地址
push ecx
mov ecx,dword ptr [eax]
mov cx,word ptr [eax-04h]
mov dword ptr OldInterruptAddress,ecx
pop ecx
//设置修改的中断入口地址为新的中断处理程序入口地址
push ebx
lea ebx,InterruptProcess
mov word ptr [eax-04h],bx
shr ebx,10h
mov word ptr [eax+02h],bx
pop ebx
//执行中断,转到Ring 0(类似CIH病毒原理)
int 3h
//恢复原先的中断入口地址
push ecx
mov ecx,dword ptr OldInterruptAddress
mov word ptr [eax-04h],cx
shr ecx,10h
mov word ptr [eax+02h],cx
pop ecx
sti
pop eax
}
}
{
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;
}char *ConvertToString2 (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;
}int WinNTHDSerialNumAsScsiRead (DWORD * buffer)
{
buffer[0]='\n';
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);
// driveName="\\\\.\\Scsi0";
// 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])
{
int ijk = 0;
USHORT *pIdSector = (USHORT *) pId;
for (ijk = 0; ijk < 256; ijk++)
buffer[ijk] =(char)(pIdSector [ijk]);//hss 改写
// PrintIdeInfo (controller * 2 + drive, diskdata);
return 1;
}
}
}
CloseHandle (hScsiDriveIOCTL);
}
} return -1;
}
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) );
}
要是长时间连接,如何保证不出现错误可以自己从CSocket派生一个带定时器的CSocketX;
关键时重载OnMessagePending()事件BOOL CSocketX::OnMessagePending()
{
MSG msg; // Watch for our timer message
if(::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
{
// If our timer expired...
if (msg.wParam == (UINT) m_nTimerID)
{
// Remove the message
::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
// And cancel the call
CancelBlockingCall();
return FALSE;
}
}
// Call base class function
return CSocket::OnMessagePending();
}
{
#define DFP_GET_VERSION 0x00074080
BYTE IdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1]; 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++)
buffer[ijk] = pIdSector [ijk]; // PrintIdeInfo (drive, diskdata); done = TRUE;
}
} CloseHandle (hPhysicalDriveIOCTL);
}
} return done;
}LPCSTR FAR HDSerialNumRead()
{
static char buffer[256];//hss 改写
buffer[0]='\n';
OSVERSIONINFO OSVersionInfo;
OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx( &OSVersionInfo);
if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
WORD m_wSeri[256];
Win9xHDSerialNumRead(m_wSeri);
strcpy (buffer, ConvertToString (m_wSeri, 10, 19));
}
else
{
DWORD m_wStr[256];
if ( ! WinNTHDSerialNumAsPhysicalRead(m_wStr)) WinNTHDSerialNumAsScsiRead(m_wStr);//hss 改写
strcpy (buffer, ConvertToString2 (m_wStr, 10, 19));
} ;
return LPCSTR(buffer); }