以前收集的,但是没有测试
From: "Wang Xianbing" <[email protected]>
Subject: 关于硬盘序列号的探讨!
 近来在CFIDO和E-mail中一直有朋友询问关于如何能在Windows下用VB来获取硬盘序列号的问题, 因为在VB的for Windows中版本中没有了端口存取函数, 所以就写了一个HDIDE16.DLL的东东, 放在主页上免费发放, 并且HDIDE32版本的即将出台, 孰知却遭到 XXX 肆意践踏, 理由如下:---- CUT ---- WX> 好久一来, 一直未能发现有用VB来获取硬盘序列号的东东,WX> 以致于VB的程序 不能得到很好的保护, 所以昨天做了个HDIDE16.DLL, RT> 太烦了吧! RT> 不是我想给你泼冷水,你的WINAPI知识有点欠乏!
 RT> 取计算机硬盘序列号及卷名的函数是:  RT> 这个老早我就用了.RT> 加密方法很多种,也不一定用硬盘序列号.RT> 可惜不能说.  :)))--- CUT ---对此, 我表示强烈的抗议, 并且为避免由此引起的误导, 特将基本的常识区
分如下, 附有完整的对比源程序:关于盘序列号有两种:硬盘序列号: 英文名 Hard Disk Serial Number, 该号是出厂时生产厂家为区别产品而设置的, 是唯一的, 是只读的, 利用硬盘序列号的加密往往是利用其唯一和只读的特性, 大多是针对有序列号的IDE HDD而言, 对于没有序列号或SCSI HDD硬盘则无能为力,这也是利用它进行加密的局限性.卷的序列号: 英文名 Volume Serial Number, 该号既可指软磁盘要得, 如:A:盘和B:盘的, 又可以指硬盘的逻辑盘, 如: C:, D:...的,是高级格式化时随机产生的, 是可以修改的, 所以利用其进行加密, 其唯一性还可, 而其可修改性对于安全而言就大打折扣了.那么如何获得它们呢? 这要视不同的平台而论, 核心实现方法如下:DOS平台Windows 3.X    Windows 9.X硬盘序列号: 端口I/O 端口I/O Ring0级I/O卷的序列号: 中断调用WINAPIWINAPI为方便大家验证, 特贴如下两程序用TC或BC编译后运行在DOS下即可:
 /* 程序1: 获得IDE硬盘C的序列号 */
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <conio.h>
#include<string.h>
char *getascii (unsigned int in_data [], int off_start, int off_end);
void main (void)
{ unsigned int dd [256]; /* DiskData */
  unsigned int dd_off;   /* DiskData offset */
while (inp (0x1F7) != 0x50)  /* Wait for controller not busy */;
  outp (0x1F6,0xA0);          /* Get first/second drive */
  outp (0x1F7, 0xEC);          /* Get drive info data */
  while (inp (0x1F7) != 0x58)  /* Wait for data ready */;
  for (dd_off = 0; dd_off != 256; dd_off++) /* Read "sector" */
dd [dd_off] = inpw (0x1F0);
  printf ("The Serial Number Hard Disk [C] is %s", getascii (dd, 10, 19));}
char *getascii (unsigned int in_data [], int off_start, int off_end)
{ static char ret_val [255];
  int loop, loop1;  for (loop = off_start, loop1 = 0; loop <= off_end; loop++)
    {
      ret_val [loop1++] = (char) (in_data [loop] / 256);  /* Get High byte */      ret_val [loop1++] = (char) (in_data [loop] % 256);  /* Get Low byte */    }  ret_val [loop1] = '\0';  /* Make sure it ends in a NULL character */  return (ret_val);
}
 /* 程序2: 获得逻辑盘C的序列号 */ #include <stdio.h>#include <stdlib.h>#include <ctype.h>
#include <dos.h>
void main(void){
      char serial_no[10];      union REGS r;      struct SREGS s;      unsigned sno1, sno2;
      r.x.ax = 0x6900;      r.h.bl = 3;        /* A:=1, B:=2, C:=3 etc. */      segread(&s);      intdosx(&r, &r, &s);      if (r.x.cflag)     *serial_no = '\0';      else      {     sno2 = *((unsigned far *)MK_FP(s.ds, r.x.dx+2));     sno1 = *((unsigned far *)MK_FP(s.ds, r.x.dx+4));     sprintf(serial_no, "%04X-%04X\n", sno1, sno2);      }      printf("The Serial Number of Login Disk [C] is %s", serial_no );
}
在Windows 3.X中:硬盘序列号: 使用端口I/O即可, 将以上程序稍加修改并用VC或BC做成DLL
            即可在VB中调用, 本人就是这样做的.
卷的序列号: 用那位朋友所说的WINAPI函数GetVolumeInformation即可.在Windows 9.X中:硬盘序列号: 必须使用VxD技术, 即便不写VxD文件, 要获得Ring0级的访问权
            才能获得, 否则程序工作在Ring3级会死在以下语句处:
            while (inp (0x1F7) != 0x50)  /* Wait for controller not busy */
            详细技术请访问http://dingkai.sdxf.com卷的序列号: 用那位朋友所说的WINAPI函数GetVolumeInformation即可.
 URL: http://glowsoft.126.com E-mail: [email protected]