• 全部
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

请问如何获得硬盘的序列号?

hz1101 2001-07-17 09:47:22
我不懂汇编语言,请问在不用汇编语言的情况下用VC如何获得CPU或硬盘的序列号(能提供获得CPU的序列号或硬盘的序列号的函数名更好!)
...全文
369 点赞 收藏 18
写回复
18 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
xiaoboey 2001-08-07
up
回复
hz1101 2001-07-17
哦,对了,_inpw只能在windows 95操作系统中使用,wistaria(听风听雨),在NT4.0系统中如何读取硬盘序列号?
to YBYT2000(Bobo):你提供的例子很好,只不过头文件内也有汇编,难道不经过汇编就无法读取吗?
回复
Behard 2001-07-17
http://www.csdn.net/develop/article/8/8870.shtm
不过那是 Delphi
回复
hz1101 2001-07-17
<conio.h>已经加入,否则不会报error LNK2001: unresolved external symbol _inpw ,而会报_inpw : undeclared identifier
回复
wistaria 2001-07-17
需要加入相关的头文件
回复
hz1101 2001-07-17
谢谢wistaria(听风听雨):用ReadIDE()时编译出错(4个错误,NT4.0操作系统下)
列举其一:unresolved external symbol _inpw
回复
YBYT2000 2001-07-17
http://www.qinjun.com/vcclub/code.htm
不过里面有一段汇编程序。
回复
wistaria 2001-07-17
这篇文章也许对你有用

硬盘的序列号只能采用对硬盘控制器直接操作的方式进行读取,也就是说只能采用CPU的I/O指令操作硬盘控制器,读取的方法如下面的C语言程序所示:
static int WaitIde()
{
int al;
while ((al=inp(0x1F7)) >=0x80) ;
return al;
}
static void ReadIDE()
{
int al;
int i;
WORD pw[256];
WaitIde();
outp(0x1F6,0xA0);
al = WaitIde();
if ((al&0x50)!=0x50) return;
outp(0x1F6,0xA0);
outp(0x1F7,0xEC);
al = WaitIde();
if ((al&0x58)!=0x58) return;
for (i=0;i< 256;i++)
pw[i] = inpw(0x1F0);
}
---- 上面的程序实际上读取了保存在硬盘控制器内的全部信息,而序列号只是其中的一部分,位于上面提到的 pw[] 数组的 10 至 20 元素内,即从 &pw[10] 开始的10个WORD内,每个WORD占两个字节,共占用了20个字节。由于该序列号保存时每个WORD的高、低字节是非Intel顺序,也就是说它的高字节在前,低字节在后,所以在使用时需要将高、低字节颠倒一下,这样就能得到完整的序列号。
不过要在ring0下,在98下可以通过以下方法得到ring0
令Win32应用程序跳入系统零层
---- 众所周知,在Windows95/98的Win32 on Intel x86体系中利用了处理器的三环保护模型中的零环(Ring0,最高权限级别)和三环(Ring3,最低权限级别)。一般应用程序都运行在Ring3下, 受到严格的"保护",只能规矩地使用Win32API。 如果我们想进行一些系统级的操作,例如在嵌入汇编中使用诸如"Mov EAX,CR0",或像在DOS 下那样调用一些必不可少的系统服务(如BIOS,DPMI 服 务)而用"Int xx",都会导致"非法操作"。但这种能力有时是必不可少的,一到这种时候Microsoft 就"建议编写一个VxD"。VxD大家早有所闻了,在VxD 里,不但可以执行CPU的所有指令,而且可以调用VMM(虚拟机管理器)和其他VxD提供的上千个系统级服务。获得这一能力的最本质原因在于它运行在Ring0,与系统内核同一级别。但是它体系的复杂性、开发工具的不易获得、帮助文档的不完备,使Microsoft排除了一大批程序员和竞争对手。而将在Windows2000(Windows98也开始支持)中取代VxD的WDM 对Win95程序员也是个噩梦,它需要了解Windows NT核心驱动模型。
----有没有简单一些的办法呢?我们可以令一个普通Win32应用程序运行在Ring0 下,从而获得VxD的能力吗?答案是肯定的。下面我们就简述一下这一技巧,有关Intel x86保护模式的基础知识请大家看有关书籍。
----首先此技巧基于以下理论根据:
----一、SIDT指令(将中断描述符表寄存器IDTR- -64位宽,16 ~47Bit存有中断描述符表IDT基地址--的内容存入指定地址单元)不是特权指令,就是说我们可以在Ring3下执行该指令,获得IDT的基地址,从而修改IDT,增加一个中断门安置我们的中断服务,一旦Ring3 程序中产生此中断,VMM就会调用此中断服务程序,而此中断服务程序就运行在Ring0下了这一点与在DOS下非常相似。
----二、Windows95 Win32 应用程序运行一个映射到全部4G内存的段中,选择子为0137h,Ring0中的VxD运行在另一个映射到全部4G内存的段中,选择子028h,这两个段除了选择子决定的访问权限不同外,没什么不同,各自段中相同的偏移量对应了相同的线性地址。所以我们放在Win32应用程序中的中断服务程序可以以Ring3的段偏移量被Ring0中的VMM寻址。

----下面我们以具体例子进一步说明,程序中有详细注释。

----这是一个Win32ConsoleProgram(控制台应用程序),虽然运行中看起来很像DOS筐中运行的实模式DOS程序,但它是货真价实的运行在Ring3下的Win32程序。用VisualC++5.0AppWizard创建一个Win32ConsoleProgram项目,添加以下.CPP文件,编译即可。

#include
#include
#include
#include
//若无DDK带下划线的可略去,
这些语句演示了调用VMM/VXD服务
DWORDLONGIDTR,SavedGate;
WORDOurGate[4]={0,0x0028,0xee00,0x0000};
//中断门描述符格式如下:

DWORD _eax,_ecx,_cr0;
WORD vmmver;
HVM sysvm;

void nothing()
{
//Used to test call in Ring0
sysvm=Get_Sys_VM_Handle();
}

void __declspec( naked ) Ring0Proc(void)
//中断例程,运行在Ring0
{
_asm{
mov _eax,eax //
mov _ecx,ecx //
mov eax, CR0
//测试Ring3中不能执行的特权指令
mov _cr0,eax //
}
VMMCall(Get_VMM_Version);
// 调 用VMM 服 务
_asm{
mov vmmver,ax
}
nothing();
//测试在运行于Ring0的
中断例程中调用子
_asm iretd
//中断返回,与在实模式
编程无本质区别
}
void main() //主程序
{
_asm{
mov eax, offset Ring0Proc
mov [OurGate], ax // 将中断函数的地址
shr eax, 16 // 填 入新造的中断门
mov [OurGate +6], ax //描述符

sidt fword ptr IDTR
// 将 中断描述符表寄存器(IDTR)
的内容取出
mov ebx, dword ptr [IDTR +2]
// 取出中断描述符表(IDT)基地址
add ebx, 8 *9
//计算Int9的描述符应放置的地址选用
Int9是因为它在Win32保护模式下未占用

mov edi, offset SavedGate
mov esi, ebx
movsd // 保存原来的Int9描述符到
movsd //SavedGate 以 便 恢 复

mov edi, ebx
mov esi, offset OurGate
movsd //替换原来的中断门描述符
movsd // 以安装中断服务例程

mov eax,0x6200
// 用以测试放在EAX中的数据
能否正确传到Ring0中断
mov ecx,0
//用以测试放在ECX中的数据
能否正确传到Ring0中断
mov ecx,0
//用以测试放在ECX中的数据
能否正确传到Ring0中断
// 因为很多VxD服务都用
此二寄存器传递参数
int 9h
// 人为触发中断,平时会出现
保护错误蓝屏或非法操
//作对话框,现在安装了
//中断服务例程后,就会通过
//VMM 在Ring0 调 用中断服务例程
- -Ring0Proc

mov edi, ebx
mov esi, offset SavedGate
movsd //恢复原来的中断门描述符
movsd
}
cout<<"CR0="<<_cr0<
回复
nustchen 2001-07-17
http://www.vchelp.net/source/source_sys.htm
回复
hz1101 2001-07-17
多谢cuick2000(比尔该死):你这是C盘卷标的信息,如果硬盘重新进行了分区,此信息就发生了改变,我想要的是取出硬盘内固定不变的序列号。
回复
cuick2000 2001-07-17
LPCTSTR lpRootPathName="c:\\"; //取C盘的序列号
LPTSTR lpVolumeNameBuffer=new char[12];//磁盘卷标
DWORD nVolumeNameSize=12;
DWORD VolumeSerialNumber;//磁盘序列号
DWORD MaximumComponentLength;
LPTSTR lpFileSystemNameBuffer=new char[10];
DWORD nFileSystemNameSize=10;
DWORD FileSystemFlags;

GetVolumeInformation(lpRootPathName,lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);
VolumeSerialNumber^=*********;//做一转换,别让人一眼就看出是磁盘序列号
呵呵?
回复
hz1101 2001-07-17
我不希望取出的序列号象网上流行的CPUID程序那样的序列号!
回复
prettywolf 2001-07-17
在那里搜索?
回复
whiskers 2001-07-17
请搜索"序列号"
回复
hz1101 2001-07-17
但那篇文章中也没有什么内容,其提供的链接根本没有用!
回复
ahphone 2001-07-17
在精华区有这样关于取CPU序列号的文章,我前段整理精华区时看到过,这篇文章也在其中。
回复
YBYT2000 2001-07-17
如果不需要使用汇编程序,我想那个程序员也不会用。要是微软把这个功能封装成API就好了。嘻嘻
回复
hz1101 2001-07-17
没有人知道如何获取CPU的序列号吗?(CPU有没有序列号?在我映象中应该有序列号,而且不同的CPU其序列号相同的概率非常非常小!)
回复
相关推荐
发帖
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
帖子事件
创建了帖子
2001-07-17 09:47
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……