如何在dos下读取硬盘id,主板id,(100分)

我猜是某个端口
 
如果只是读c盘逻辑分区的序列号,参考一下文本:
文件系统
磁盘
获得分区信息并判断是否有CD
声明:
Declare Function GetVolumeInformation Lib _
"kernel32" Alias "GetVolumeInformationA" _
(ByVal lpRootPathName As String, _
ByVal lpVolumeNameBuffer As String, _
ByVal nVolumeNameSize As Long, _
lpVolumeSerialNumber As Long, _
lpMaximumComponentLength As Long, _
lpFileSystemFlags As Long, _
ByVal lpFileSystemNameBuffer As String, _
ByVal nFileSystemNameSize As Long) As Long

Declare Function GetDriveType Lib "kernel32" _
Alias "GetDriveTypeA" (ByVal nDrive As String) As Long

Public Const DRIVE_CDROM = 5
使用:
Dim VolName As String, FSys As String, erg As Long
Dim VolNumber As Long, MCM As Long, FSF As Long
Dim Drive As String, DriveType As Long
VolName = Space(127)
FSys = Space(127)
Drive = "F:/" 'Enter the driverletter you want
DriveType& = GetDriveType(Drive$)
erg& = GetVolumeInformation(Drive$, VolName$, 127&, _
VolNumber&, MCM&, FSF&, FSys$, 127&)
Print "分区名称:" & vbTab & VolName$
Print "序列号:" & vbTab & VolNumber&
Print "最大文件名称长:" & vbTab & vbTab & MCM&
Print "文件系统标志:" & vbTab & vbTab & FSF&
Print "文件系统名称:" & vbTab & FSys$
Print "类型:" & vbTab & DriveType&;
'Is the drive a CDROM, if so, check for a CD
If DriveType& = DRIVE_CDROM Then
Print " (CDROM, ";
If erg& = 0 Then
Print "没有 CD )"
Else
Print "有 CD )"
End If
Else
Print " (非 CDROM)" '
End If

打开和关闭CD-ROM 驱动器
声明:
Declare Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As String, ByVal uReturnLength As Long, _
ByVal hwndCallback As Long) As Long
使用:
'打开
retvalue = mcisendstring("set CDAudio door open", returnstring, 127, 0)
'关闭
retvalue = mcisendstring("set CDAudio door closed", returnstring, 127, 0)

判断驱动器类型
利用 API 可以判断一个驱动器的类型。
声明:
Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
调用:
ret = GetDriveType ( "D:/")
如果 ret =2 软盘,=3 硬盘,=4 网络映射盘,=5 光驱,=6 RAM DISK

取得磁盘序列号、卷标和文件系统类型
磁盘序列号在每次软盘或硬盘格式化后都重新生成,并且不回重复。许多程序员用此加密。其实也可以修改该函数,可以得到磁盘卷标和文件系统类型信息。

声明:
Private Declare Function GetVolumeInformation Lib "kernel32.dll" Alias "GetVolumeInformationA" (ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal nVolumeNameSize As Integer, lpVolumeSerialNumber As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As Long) As Long

代码:

Function GetSerialNumber(sRoot As String) As Long
Dim lSerialNum As Long
Dim R As Long
Dim sTemp1 As String, sTemp2 As String
strLabel = String$(255, Chr$(0))
' 磁盘卷标
strType = String$(255, Chr$(0))
' 文件系统类型 一般为 FAT
R = GetVolumeInformation(sRoot, strLabel, Len(strLabel), lSerialNum, 0, 0, strType, Len(strType))
GetSerialNumber = lSerialNum
'在 strLabel 中为 磁盘卷标
'在 strType 中为 文件系统类型
End Function

用法:

当驱动器不存在时,函数返回 0。如果是个非根目录,也将返回 0:

lSerial = GetSerialNumber("c:/")

格式化磁盘
在Drive的参数中 "A:" = 0,类推。

Private Const SHFMT_ID_DEFAULT = &HFFFF&
'Currently the only fmtID supported.

Private Declare Function SHFormatDrive Lib "shell32.dll" (ByVal hWnd As Long, ByVal Drive As Long, fmtID As Long, Options As Long) As Long

Private Sub Command1_Click()
Dim lret As Long
lret = SHFormatDrive(Me.hWnd, 0, SHFMT_ID_DEFAULT, 0)
Select Case lret
Case -2
MsgBox "OK !"
Case -3
MsgBox "Cannot format a read only drive !"
End Select
End Sub

 
 
herald:我是很想给分给你,但我是要dos下的程序.不好意思了.*_*
 
转登一文:
如何从Ring 3读取硬盘序列号
作者:丁凯

硬盘的序列号是厂家设定的,且只能用I/O指令读取,所以,这在以前的DOS时代
根本不是什么问题.方法非常简单,如下面的代码所示:
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 = inpw(0x1F0);
}
}

至此,关于IDE硬盘的信息已经在 pw 数组中了,需要注意的是该数组是一个 WORD
类型,硬盘的序列号存放于 pw[10] 开始的10个WORD中,使用时需要将每个WORD的
高低字节颠倒一下。

真正有点麻烦的是在Windows 95/98下,I/O指令作为特权指令在应用程序级别,即
Ring 3是不可使用的,所以上面的代码在执行到 WaitIde()时会陷到死循环中,原
因就是 IN 0x1F7 总是返回 0xFF

容易想到的解决办法是写一个VxD,因为VxD运行Ring 0级别上,即最高特权级上,所以
所有的指令都是可用的。当然,这没有任何问题,事实上我已经写了这样的 VxD,效果
是明显的,如果哪位有兴趣,可与我联系。

如果你是一个编程高手,这没有什么难度,所以不必看下去。
如果你连VxD也不会写,请参阅拙作"VxD入门教程"。

当然,如果连象读取硬盘序列号这样小的问题都要写个VxD,确实是一件令人生厌的事,
且不说既要额外装个Win 95 DDK,又要防止VxD出现错误使系统崩溃这种多余的工作
和担心,旦旦是发行程序时带个这么小的东东就让人看着扎眼(读硬盘序列号无非是为了
防止拷贝,这个小东东明显会提示别人应该如何破解)。

所以我推荐的方法是真接从 Ring 3 完成该功能,即在你的EXE文件中处理这件事,这
样一方面减小了编程难度,另一方面有利于实现防止拷贝的目的。

实现的方法出人意料的简单,不过,也还是需要 100 行左右的代码。

唯一的一个技术难点就是利用 CPU 的异常从 Ring 3 直接切换到 Ring 0。如果解决了
这个问题,那么整个程序就非常简单了,值得一提的是,由于该技术将代码切换到
Ring 0 运行,所以,....., 不用我多说了吧?

不象在实模式下,中断向量表位于内存地址的0:0处,每当中断发生时,无论是硬中断还
是软中断,CPU都会从该表中查找中断的入口位置,并执行相应的中断程序。在保护模式
下(包括V86方式),物理内存0:0处不再有中断向量表,甚至"0:0"这种表示方式也发生了
变化,原来的段址不复存在,代之以段选择器,中断向量也用中断描述符表(IDT)取代了,
这意味着当发生中断或异常时(异常只在保护模式下存在,可以把它当作中断看待),CPU
查找的是IDT,然后再根据查到的入口地址执行相应的中断处理程序。

关于这部分内容请参阅80386 (或以上) CPU的技术手册。

从上面可以看出,虽然查找的内容及方法发生了变化,但原理并没有变,如果要修改中
断入口,所需要修改的地方无非是变成了IDT而已。更妙的是,中断处理程序是运行在
CPU最高特权级Ring 0上,这就使得我们从Ring 3进行Ring 0级别的操作成为可能。

具体方法可以归结如下:
首先,取得系统 IDT,这可用 SIDT 指令一步到位,且不受特权级限制;
然后,修改 IDT 中某一中断的入口,使其指向我们自己的处理程序;虽然理论上IDT表
中的所有中断都可以使用,但我建议使用中断 3, 这个中断是给调试器用的,平常没啥
用(修改的方法请参阅IDT的格)。
最后,执行该中断。可以直接执行代码 INT 3,当然,在 Ring 3 上执行该指令必然会导
致CPU异常,于是,我们的处理程序就这样轻易而举地得到了控制权。

一旦得到CPU最高特权级的控制权,中断处理程序就可以进行任何平常在 Ring 3 级别上
不能够进行的操作了,当然也包括本文的主题:读取硬盘序列号。
说得再具体一些,就是将本文前面提到的代码放到中断处理程序中即可全部搞定了。

至于用 C 语言或是汇编语言,那就完全视个人情况了。

我采用的方法是用 C 语言加上内嵌的汇编,完整的程序代码不列在此处了,需要的话请
直接与本人联系(也省得有人未经允许抄俺的程序 :Q)

最后,需要说明的是,这种方法不可以在 Windows NT 下使用。是什么原因我就不多说
了。



一些题外话,实际上我写这篇文章的目的并不完全是为了读取硬盘的序列号(这东东毕竟
没多大用途,有些硬盘,如三星的 32543A 根本就没有序列号),主要的目的是想在从
Ring 3 获取 Ring 0 特权这个问题上做些尝试,希望有兴趣的朋友能够参予进来,公开
你所掌握的技术,大家共同提高编程水平。
还有一句话不能不说:本文写得较为匆忙,如有错误,敬请指正。


本人对上面的文章及代码保留所有权利.需要引用的请告之本人
 
接受答案了.
 

Similar threads

顶部