首先附上DLL的源代码library diskdll;uses
  Windows,
  Messages,
  SysUtils,
  Classes;const
  METHOD_BUFFERED = 0;  FILE_DEVICE_BEEP = $00000001;
  FILE_DEVICE_CD_ROM = $00000002;
  FILE_DEVICE_CD_ROM_FILE_SYSTEM = $00000003;
  FILE_DEVICE_CONTROLLER = $00000004;
  FILE_DEVICE_DATALINK = $00000005;
  FILE_DEVICE_DFS = $00000006;
  FILE_DEVICE_DISK = $00000007;
  FILE_DEVICE_DISK_FILE_SYSTEM = $00000008;
  FILE_DEVICE_FILE_SYSTEM = $00000009;
  FILE_DEVICE_INPORT_PORT = $0000000A;
  FILE_DEVICE_KEYBOARD = $0000000B;
  FILE_DEVICE_MAILSLOT = $0000000C;
  FILE_DEVICE_MIDI_IN = $0000000D;
  FILE_DEVICE_MIDI_OUT = $0000000E;
  FILE_DEVICE_MOUSE = $0000000F;
  FILE_DEVICE_MULTI_UNC_PROVIDER = $00000010;
  FILE_DEVICE_NAMED_PIPE = $00000011;
  FILE_DEVICE_NETWORK = $00000012;
  FILE_DEVICE_NETWORK_BROWSER = $00000013;
  FILE_DEVICE_NETWORK_FILE_SYSTEM = $00000014;
  FILE_DEVICE_NULL = $00000015;
  FILE_DEVICE_PARALLEL_PORT = $00000016;
  FILE_DEVICE_PHYSICAL_NETCARD = $00000017;
  FILE_DEVICE_PRINTER = $00000018;
  FILE_DEVICE_SCANNER = $00000019;
  FILE_DEVICE_SERIAL_MOUSE_PORT = $0000001A;
  FILE_DEVICE_SERIAL_PORT = $0000001B;
  FILE_DEVICE_SCREEN = $0000001C;
  FILE_DEVICE_SOUND = $0000001D;
  FILE_DEVICE_STREAMS = $0000001E;
  FILE_DEVICE_TAPE = $0000001F;
  FILE_DEVICE_TAPE_FILE_SYSTEM = $00000020;
  FILE_DEVICE_TRANSPORT = $00000021;
  FILE_DEVICE_UNKNOWN = $00000022;
  FILE_DEVICE_VIDEO = $00000023;
  FILE_DEVICE_VIRTUAL_DISK = $00000024;
  FILE_DEVICE_WAVE_IN = $00000025;
  FILE_DEVICE_WAVE_OUT = $00000026;
  FILE_DEVICE_8042_PORT = $00000027;
  FILE_DEVICE_NETWORK_REDIRECTOR = $00000028;
  FILE_DEVICE_BATTERY = $00000029;
  FILE_DEVICE_BUS_EXTENDER = $0000002A;
  FILE_DEVICE_MODEM = $0000002B;
  FILE_DEVICE_VDM = $0000002C;
  FILE_DEVICE_MASS_STORAGE = $0000002D;
  FILE_DEVICE_SMB = $0000002E;
  FILE_DEVICE_KS = $0000002F;
  FILE_DEVICE_CHANGER = $00000030;
  FILE_DEVICE_SMARTCARD = $00000031;
  FILE_DEVICE_ACPI = $00000032;
  FILE_DEVICE_DVD = $00000033;
  FILE_DEVICE_FULLSCREEN_VIDEO = $00000034;
  FILE_DEVICE_DFS_FILE_SYSTEM = $00000035;
  FILE_DEVICE_DFS_VOLUME = $00000036;
  FILE_DEVICE_SERENUM = $00000037;
  FILE_DEVICE_TERMSRV = $00000038;
  FILE_DEVICE_KSEC = $00000039;
  FILE_DEVICE_FIPS = $0000003A;
  FILE_DEVICE_INFINIBAND = $0000003B;  FILE_ANY_ACCESS = 0;
  FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS;
  FILE_READ_ACCESS = $0001; // file & pipe
  FILE_WRITE_ACCESS = $0002; // file & pipe  SCSI_IOCTL_DATA_OUT = 0;
  SCSI_IOCTL_DATA_IN = 1;
  SCSI_IOCTL_DATA_UNSPECIFIED = 2;  CDB_INQUIRY_EVPD = 1;  SCSIOP_INQUIRY = $12;
  SCSIOP_MODE_SENSE = $1A;  MODE_PAGE_CAPABILITIES = $2A;  CDB6GENERIC_LENGTH = 6;  IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER;
  IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
  IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SERIAL_PORT shl 16) + $0501); //$001b0501
  IOCTL_SCSI_MINIPORT = ((IOCTL_SCSI_BASE shl 16) or ($0402 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14)); //$0004D008
  IOCTL_SCSI_PASS_THROUGH = ((IOCTL_SCSI_BASE shl 16) or ($0401 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14));
  IOCTL_SCSI_GET_INQUIRY_DATA = ((IOCTL_SCSI_BASE shl 16) or ($0403 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
  IOCTL_SCSI_GET_CAPABILITIES = ((IOCTL_SCSI_BASE shl 16) or ($0404 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
  IOCTL_SCSI_PASS_THROUGH_DIRECT = ((IOCTL_SCSI_BASE shl 16) or ($0405 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14));
  IOCTL_SCSI_GET_ADDRESS = ((IOCTL_SCSI_BASE shl 16) or ($0406 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
  IOCTL_SCSI_RESCAN_BUS = ((IOCTL_SCSI_BASE shl 16) or ($0407 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
  IOCTL_SCSI_GET_DUMP_POINTERS = ((IOCTL_SCSI_BASE shl 16) or ($0408 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));  IOCTL_DISK_BASE = FILE_DEVICE_DISK;
  IOCTL_DISK_GET_DRIVE_GEOMETRY = (
    (IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    ($0000 shl 2) or METHOD_BUFFERED);
  IOCTL_DISK_GET_PARTITION_INFO = (
    (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
    ($0001 shl 2) or METHOD_BUFFERED);
  IOCTL_DISK_GET_DRIVE_LAYOUT = (
    (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
    ($0003 shl 2) or METHOD_BUFFERED);  IOCTL_VOLUME_BASE = Cardinal('V');
  IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = (
    (IOCTL_VOLUME_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    (0 shl 2) or METHOD_BUFFERED);
  IOCTL_DISK_CONTROLLER_NUMBER = (
    (IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    ($0011 shl 2) or METHOD_BUFFERED);
  IOCTL_STORAGE_GET_MEDIA_TYPES_EX = (
    (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    ($0301 shl 2) or METHOD_BUFFERED);
  IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER = (
    (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    ($0304 shl 2) or METHOD_BUFFERED);  IOCTL_STORAGE_QUERY_PROPERTY = (
    (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
    ($0500 shl 2) or METHOD_BUFFERED);type
  TDiskExtent = record
    DiskNumber: Cardinal;
    StartingOffset: LARGE_INTEGER;
    ExtentLength: LARGE_INTEGER;
  end;
  DISK_EXTENT = TDiskExtent;
  PDiskExtent = ^TDiskExtent;  TVolumeDiskExtents = record
    NumberOfDiskExtents: Cardinal;
    Extents: array[0..0] of TDiskExtent;
  end;
  VOLUME_DISK_EXTENTS = TVolumeDiskExtents;
  PVolumeDiskExtents = ^TVolumeDiskExtents;
function GetVolumeInfo(DriverLetter: Char):TDiskExtent; stdcall;
var
  hVolume: THandle;
  DiskExtents: PVolumeDiskExtents;
  dwOutBytes: Cardinal;
begin
  with Result do
  begin
    DiskNumber := 0;
    StartingOffset.QuadPart := 0;
    ExtentLength.QuadPart := 0;
  end;
  hVolume := CreateFile(PChar('\\.\' + DriverLetter + ':'), GENERIC_READ or GENERIC_WRITE,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if hVolume < 1 then Exit;
  DiskExtents := AllocMem(Max_Path);
  if DeviceIoControl(hVolume,
    IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
    nil, 0,
    DiskExtents, Max_Path,
    dwOutBytes, nil) then
  begin
    if DiskExtents^.NumberOfDiskExtents > 0 then
      Result := DiskExtents^.Extents[0];
  end;
  FreeMem(DiskExtents);
  CloseHandle(hVolume);
end;exports
  GetVolumeInfo;end.下面是调用代码function GetVolumeInfo(DriverLetter:Char):TDiskExtent;external'diskdll.dll';{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text:=IntToStr(GetVolumeInfo('C').DiskNumber);
end;
返回的结果正确的应该是 0 ,因为我只有一个硬盘,可为什么总是返回 2 ;

解决方案 »

  1.   

    那为什么GetVolumeInfo('H').DiskNumber,返回也是 2 呢 ? 其中H为可移动磁盘
      

  2.   

    在哪里加 ?如何过把下面代码保存成.pas,在工程里引用就可以成功调用
    unit SkyHard;interfaceuses
      Windows, Messages, SysUtils, Classes;const
      METHOD_BUFFERED = 0;  FILE_DEVICE_BEEP = $00000001;
      FILE_DEVICE_CD_ROM = $00000002;
      FILE_DEVICE_CD_ROM_FILE_SYSTEM = $00000003;
      FILE_DEVICE_CONTROLLER = $00000004;
      FILE_DEVICE_DATALINK = $00000005;
      FILE_DEVICE_DFS = $00000006;
      FILE_DEVICE_DISK = $00000007;
      FILE_DEVICE_DISK_FILE_SYSTEM = $00000008;
      FILE_DEVICE_FILE_SYSTEM = $00000009;
      FILE_DEVICE_INPORT_PORT = $0000000A;
      FILE_DEVICE_KEYBOARD = $0000000B;
      FILE_DEVICE_MAILSLOT = $0000000C;
      FILE_DEVICE_MIDI_IN = $0000000D;
      FILE_DEVICE_MIDI_OUT = $0000000E;
      FILE_DEVICE_MOUSE = $0000000F;
      FILE_DEVICE_MULTI_UNC_PROVIDER = $00000010;
      FILE_DEVICE_NAMED_PIPE = $00000011;
      FILE_DEVICE_NETWORK = $00000012;
      FILE_DEVICE_NETWORK_BROWSER = $00000013;
      FILE_DEVICE_NETWORK_FILE_SYSTEM = $00000014;
      FILE_DEVICE_NULL = $00000015;
      FILE_DEVICE_PARALLEL_PORT = $00000016;
      FILE_DEVICE_PHYSICAL_NETCARD = $00000017;
      FILE_DEVICE_PRINTER = $00000018;
      FILE_DEVICE_SCANNER = $00000019;
      FILE_DEVICE_SERIAL_MOUSE_PORT = $0000001A;
      FILE_DEVICE_SERIAL_PORT = $0000001B;
      FILE_DEVICE_SCREEN = $0000001C;
      FILE_DEVICE_SOUND = $0000001D;
      FILE_DEVICE_STREAMS = $0000001E;
      FILE_DEVICE_TAPE = $0000001F;
      FILE_DEVICE_TAPE_FILE_SYSTEM = $00000020;
      FILE_DEVICE_TRANSPORT = $00000021;
      FILE_DEVICE_UNKNOWN = $00000022;
      FILE_DEVICE_VIDEO = $00000023;
      FILE_DEVICE_VIRTUAL_DISK = $00000024;
      FILE_DEVICE_WAVE_IN = $00000025;
      FILE_DEVICE_WAVE_OUT = $00000026;
      FILE_DEVICE_8042_PORT = $00000027;
      FILE_DEVICE_NETWORK_REDIRECTOR = $00000028;
      FILE_DEVICE_BATTERY = $00000029;
      FILE_DEVICE_BUS_EXTENDER = $0000002A;
      FILE_DEVICE_MODEM = $0000002B;
      FILE_DEVICE_VDM = $0000002C;
      FILE_DEVICE_MASS_STORAGE = $0000002D;
      FILE_DEVICE_SMB = $0000002E;
      FILE_DEVICE_KS = $0000002F;
      FILE_DEVICE_CHANGER = $00000030;
      FILE_DEVICE_SMARTCARD = $00000031;
      FILE_DEVICE_ACPI = $00000032;
      FILE_DEVICE_DVD = $00000033;
      FILE_DEVICE_FULLSCREEN_VIDEO = $00000034;
      FILE_DEVICE_DFS_FILE_SYSTEM = $00000035;
      FILE_DEVICE_DFS_VOLUME = $00000036;
      FILE_DEVICE_SERENUM = $00000037;
      FILE_DEVICE_TERMSRV = $00000038;
      FILE_DEVICE_KSEC = $00000039;
      FILE_DEVICE_FIPS = $0000003A;
      FILE_DEVICE_INFINIBAND = $0000003B;  FILE_ANY_ACCESS = 0;
      FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS;
      FILE_READ_ACCESS = $0001; // file & pipe
      FILE_WRITE_ACCESS = $0002; // file & pipe  SCSI_IOCTL_DATA_OUT = 0;
      SCSI_IOCTL_DATA_IN = 1;
      SCSI_IOCTL_DATA_UNSPECIFIED = 2;  CDB_INQUIRY_EVPD = 1;  SCSIOP_INQUIRY = $12;
      SCSIOP_MODE_SENSE = $1A;  MODE_PAGE_CAPABILITIES = $2A;  CDB6GENERIC_LENGTH = 6;  IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER;
      IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
      IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SERIAL_PORT shl 16) + $0501); //$001b0501
      IOCTL_SCSI_MINIPORT = ((IOCTL_SCSI_BASE shl 16) or ($0402 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14)); //$0004D008
      IOCTL_SCSI_PASS_THROUGH = ((IOCTL_SCSI_BASE shl 16) or ($0401 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14));
      IOCTL_SCSI_GET_INQUIRY_DATA = ((IOCTL_SCSI_BASE shl 16) or ($0403 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
      IOCTL_SCSI_GET_CAPABILITIES = ((IOCTL_SCSI_BASE shl 16) or ($0404 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
      IOCTL_SCSI_PASS_THROUGH_DIRECT = ((IOCTL_SCSI_BASE shl 16) or ($0405 shl 2) or METHOD_BUFFERED or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14));
      IOCTL_SCSI_GET_ADDRESS = ((IOCTL_SCSI_BASE shl 16) or ($0406 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
      IOCTL_SCSI_RESCAN_BUS = ((IOCTL_SCSI_BASE shl 16) or ($0407 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));
      IOCTL_SCSI_GET_DUMP_POINTERS = ((IOCTL_SCSI_BASE shl 16) or ($0408 shl 2) or METHOD_BUFFERED or (FILE_ANY_ACCESS shl 14));  IOCTL_DISK_BASE = FILE_DEVICE_DISK;
      IOCTL_DISK_GET_DRIVE_GEOMETRY = (
        (IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        ($0000 shl 2) or METHOD_BUFFERED);
      IOCTL_DISK_GET_PARTITION_INFO = (
        (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
        ($0001 shl 2) or METHOD_BUFFERED);
      IOCTL_DISK_GET_DRIVE_LAYOUT = (
        (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
        ($0003 shl 2) or METHOD_BUFFERED);  IOCTL_VOLUME_BASE = Cardinal('V');
      IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = (
        (IOCTL_VOLUME_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        (0 shl 2) or METHOD_BUFFERED);
      IOCTL_DISK_CONTROLLER_NUMBER = (
        (IOCTL_DISK_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        ($0011 shl 2) or METHOD_BUFFERED);
      IOCTL_STORAGE_GET_MEDIA_TYPES_EX = (
        (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        ($0301 shl 2) or METHOD_BUFFERED);
      IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER = (
        (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        ($0304 shl 2) or METHOD_BUFFERED);  IOCTL_STORAGE_QUERY_PROPERTY = (
        (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or
        ($0500 shl 2) or METHOD_BUFFERED);type
      TDiskExtent = record
        DiskNumber: Cardinal;
        StartingOffset: LARGE_INTEGER;
        ExtentLength: LARGE_INTEGER;
      end;
      DISK_EXTENT = TDiskExtent;
      PDiskExtent = ^TDiskExtent;  TVolumeDiskExtents = record
        NumberOfDiskExtents: Cardinal;
        Extents: array[0..0] of TDiskExtent;
      end;
      VOLUME_DISK_EXTENTS = TVolumeDiskExtents;
      PVolumeDiskExtents = ^TVolumeDiskExtents;
    function GetVolumeInfo(DriverLetter: Char): TDiskExtent;implementationfunction GetVolumeInfo(DriverLetter: Char): TDiskExtent;
    var
      hVolume: THandle;
      DiskExtents: PVolumeDiskExtents;
      dwOutBytes: Cardinal;
    begin
      with Result do
      begin
        DiskNumber := 0;
        StartingOffset.QuadPart := 0;
        ExtentLength.QuadPart := 0;
      end;
      hVolume := CreateFile(PChar('\\.\' + DriverLetter + ':'), GENERIC_READ or GENERIC_WRITE,
        FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
      if hVolume < 1 then Exit;
      DiskExtents := AllocMem(Max_Path);
      if DeviceIoControl(hVolume,
        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
        nil, 0,
        DiskExtents, Max_Path,
        dwOutBytes, nil) then
      begin
        if DiskExtents^.NumberOfDiskExtents > 0 then
          Result := DiskExtents^.Extents[0];
      end;
      FreeMem(DiskExtents);
      CloseHandle(hVolume);
    end;end.
    uses SkyHard;procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Text:=IntToStr(GetVolumeInfo('C').DiskNumber);
    end;但我想把那.pas编译成DLL,然后在程序里调用,该怎样办 ?
      

  3.   

    在你引入导出函数的那里加,也就是external的前面。同一进程内,调用协定不起作用。