Link to home
Start Free TrialLog in
Avatar of undefinity
undefinity

asked on

how can i find Partition/disk letter ?

ex : i want know harddisk drive letter(ex : C:,D:) or its partition's drive letters using its windows device name like  "\\.\PHYSICALDRIVE1".  And i don't know how partitions are naming by windows. is it like "\\.\PHYSICALDRIVE1\PARTITION1" ?
ASKER CERTIFIED SOLUTION
Avatar of joepezt
joepezt

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of joepezt
joepezt

sorry..
here is it all

type TDriveType = (dtUnknown, dtDoesNotExist, dtRemovable, dtFixed,
dtNetwork, dtCDROM, dtRAMDisk);

type TDriveInfo = record
   DriveLetter: string;
   DriveType: TDriveType;
   TypeDescrip: string;
   DriveSize: single;  //size in Kilobytes
   DriveFreeSpace: single; //free space in Kilobytes
end;

type TDriveInfoArray = array of TDriveInfo;


//pass a single character string as the 'DriveLetter' param
function DriveType(DriveLetter: string): TDriveType;
var
  x,
  DrvType   : Integer;
  DrvLetter,
  DrvString : String;
begin

    result := dtUnknown;
    DriveLetter := DriveLetter + ':\';

    // get the drive type
    DrvType := GetDriveType(pChar(DriveLetter));

    // set our drive type string accordingly
    case DrvType of
      0                 : result := dtUnknown;
      1                 : result := dtDoesNotExist;
      DRIVE_REMOVABLE  : result := dtRemovable;
      DRIVE_FIXED : result := dtFixed;
      DRIVE_REMOTE : result := dtNetwork;
      DRIVE_CDROM : result := dtCDROM;
      DRIVE_RAMDISK : result := dtRAMDisk;
    end;


end;


//returns a listing of all drives and types on the system
procedure GetAllDriveTypes(var DriveInfoArray: TDriveInfoArray);
var
  x: integer;

begin

DriveInfoArray := nil;
SetLength(DriveInfoArray, 0);

//25 possible drives ... a-z
for x := Ord('A') to Ord('Z') do
begin
   if not ( DriveType(Chr(x)) = dtDoesNotExist) then
   begin
      SetLength(DriveInfoArray, Length(DriveInfoArray) + 1);
      DriveInfoArray[Length(DriveInfoArray) - 1].DriveLetter := Chr(x);
      DriveInfoArray[Length(DriveInfoArray) - 1].DriveType :=
DriveType(Chr(x));
      DriveInfoArray[Length(DriveInfoArray) - 1].TypeDescrip :=
DriveTypeToString(DriveInfoArray[Length(DriveInfoArray) - 1].DriveType);
      DriveInfoArray[Length(DriveInfoArray) - 1].DriveSize := DiskSize(x -
64) / 1024;  //size in KB
      DriveInfoArray[Length(DriveInfoArray) - 1].DriveFreeSpace :=
DiskFree(x - 64) / 1024;  //size in KB
   end;


end;


end;


function DriveTypeToString(DriveType: TDriveType): string;
begin

case DriveType of
   dtUnknown: result := 'Unknown Drive Type';
   dtDoesNotExist: result := 'Drive Does Not Exist';
   dtRemovable: result := 'Removable Drive';
   dtFixed: result := 'Fixed Drive';
   dtNetwork: result := 'Network Drive';
   dtCDROM: result := 'CD-ROM Drive';
   dtRAMDisk: result := 'RAM Disk Drive';

end;

end;



//Returns true if the drive is ready (useful for removable drives)
function DriveReady(DriveLetter: string): boolean;
var
  code: Integer;
  rec: TSearchRec;
  EMode: Word;

begin

 EMode := SetErrorMode(SEM_FAILCRITICALERRORS);

 DriveLetter := AnsiLowerCase(DriveLetter);

 //FYI,  ord('a') = 97

 try
   result := (DiskSize( Ord(DriveLetter[1]) - 96 ) <> -1)
  finally
   SetErrorMode(EMode);
 end;




end;

another example

procedure Tform1.GetCDInformation;
var
  DriveInfo   : integer;
  Letter      : integer;
  DriveID     : shortstring;
  DriveChar   : Char;
  DriveLetter : string;
  begin
  Application.ProcessMessages;
  Letter := 64;
  Repeat
    Inc(Letter);
    DriveChar := Chr(Letter);
    DriveLetter := DriveChar+':\';
    DriveInfo := GetDriveType(Pchar(DriveLetter));
    Application.ProcessMessages;
  Until DriveInfo = DRIVE_CDROM;

  // DriveLetter is the CD-ROM
end;
procedure TForm1.Button1Click(Sender: TObject);
var
  i : Integer;
begin
  OpenDialog1.Execute;
  i := GetDriveType(pchar(OpenDialog1.FileName));
  case i of
    DRIVE_REMOVABLE: // floppy... iomega.. etc etc
    DRIVE_CDROM: // cdrom
    DRIVE_FIXED: //fixed disk
  end;
end;
Avatar of undefinity

ASKER

thanx but i don't want this.
i want that i give device name like "\\.\PHYSICALDRIVE1" to program and then program gives me it's letter. And i want to how paritions naming in windows.
you can use these functions to achieve this
you just name them whatever you need.

where you have seen \\.\physicaldrive1 I don't know, it is probably done the same way like this. just naming it like \\.\physicaldrive.. etc etc
i saw it in delphi project that we can acces linux files with.
tell again what you are looking for.. exactly
i am trying to make a program which give me list of disks and disks' partitions(any type) in my computer like partition magic. And i want to know which partitions have a which letter.
try this component

save as uidedriveinfo.pas under delphi lib folder
component -> install component -> recompiler and install

maybe this will work



unit uIdeDriveInfo;

interface

 uses
   Windows,
   SysUtils,
   Classes;

 const
   DFP_GET_VERSION        = $00074080;
   DFP_SEND_DRIVE_COMMAND = $0007C084;
   DFP_RECEIVE_DRIVE_DATA = $0007C088;
   IDE_IDENTIFY_DEVICE    = $EC;

 type
   {$Z1}
   TDevices = (dmIdePrimary0, dmIdePrimary1, dmIdeSecondary0,
     dmIdeSecondary1, dmAtapiPrimary0, dmAtapiPrimary1,
     dmAtapiSecondary0, dmAtapiSecondary1);

   TDeviceMap = set of TDevices;

   TCapability = (cpIdeIdentify, cpAtapiIdentify, cpSmart,
     cpReserved03, cpReserved04, cpReserved05, cpReserved06,
     cpReserved07, cpReserved08, cpReserved09, cpReserved10,
     cpReserved11, cpReserved12, cpReserved13, cpReserved14,
     cpReserved15, cpReserved16, cpReserved17, cpReserved18,
     cpReserved19, cpReserved20, cpReserved21, cpReserved22,
     cpReserved23, cpReserved24, cpReserved25, cpReserved26,
     cpReserved27, cpReserved28, cpReserved29, cpReserved30,
     cpReserved31);

   TCapabilities = set of TCapability;

   PGetVersionOutParams = ^TGetVersionOutParams;
   TGetVersionOutParams = packed record
     Version: Byte;
     Revision: Byte;
     Reserved1: Byte;
     IdeDeviceMap: TDeviceMap;
     Capabilities: TCapabilities;
     Reserved2: array[0..3] of DWord end;

   PIdeRegs = ^TIdeRegs;
   TIdeRegs = packed record
     FeaturesReg: Byte;
     SectorCount: Byte;
     SectorNumber: Byte;
     CylLow: Byte;
     CylHigh: Byte;
     DriveHead: Byte;
     Command: Byte;
     Reserved: Byte end;

   PSendCmdInParams = ^TSendCmdInParams;
   TSendCmdInParams = packed record
     BufferSize: DWord;
     DriveRegs: TIdeRegs;
     DriveNumber: Byte;
     Reserved1: array[1..3] of Byte;
     Reserved2: array[0..3] of DWord end;

   PDriverStatus = ^TDriverStatus;
   TDriverStatus = packed record
     DriverError: Byte;
     IdeStatus: Byte;
     Reserved1: array[2..3] of Byte;
     Reserved2: array[0..1] of DWord end;

   PSendCmdOutParams = ^TSendCmdOutParams;
   TSendCmdOutParams = packed record
     BufferSize: DWord;
     DriverStatus: TDriverStatus;
     Buffer: array[0..255] of Word end;

 const
   DriveNumberMin = 0;
   DriveNumberMax = 3;

 type
   TDriveNumber = DriveNumberMin..DriveNumberMax;

   TIdeDriveInfo = class(TComponent)
     private
       FCylinders: array[TDriveNumber] of Integer;
       FFirmwareRevision: array[TDriveNumber] of String;
       FHeads: array[TDriveNumber] of Integer;
       FModelNumber: array[TDriveNumber] of String;
       FRemovableMedia: array[TDriveNumber] of Boolean;
       FSectorsPerTrack: array[TDriveNumber] of Integer;
       FSerialNumber: array[TDriveNumber] of String;
     protected
       procedure CheckDriveNumber(Drive: TDriveNumber); virtual;
       function GetCylinders(Drive: TDriveNumber): Integer; virtual;
       function GetFirmwareRevision(Drive: TDriveNumber): String;
         virtual;
       function GetHeads(Drive: TDriveNumber): Integer; virtual;
       function GetModelNumber(Drive: TDriveNumber): String; virtual;
       function GetRemovableMedia(Drive: TDriveNumber): Boolean;
         virtual;
       function GetSectorsPerTrack(Drive: TDriveNumber): Integer;
         virtual;
       function GetSerialNumber(Drive: TDriveNumber): String; virtual;
       procedure QueryDrive(Drive: TDriveNumber); virtual;
     public
       constructor Create(AOwner: TComponent); override;
       property Cylinders[Drive: TDriveNumber]: Integer
         read GetCylinders;
       property FirmwareRevision[Drive: TDriveNumber]: String
         read GetFirmwareRevision;
       property Heads[Drive: TDriveNumber]: Integer read GetHeads;
       property ModelNumber[Drive: TDriveNumber]: String
         read GetModelNumber;
       property RemovableMedia[Drive: TDriveNumber]: Boolean
         read GetRemovableMedia;
       property SectorsPerTrack[Drive: TDriveNumber]: Integer
         read GetSectorsPerTrack;
       property SerialNumber[Drive: TDriveNumber]: String
         read GetSerialNumber; end;

   EIdeDriveInfo = class(Exception);

 procedure Register;

 implementation

 procedure Register;
   begin
   RegisterComponents('Samples', [TIdeDriveInfo]) end;

 constructor TIdeDriveInfo.Create(AOwner: TComponent);
   var
     I: TDriveNumber;
   begin
   inherited Create(AOwner);
   for I := DriveNumberMin to DriveNumberMax do
     QueryDrive(I) end;

 procedure TIdeDriveInfo.CheckDriveNumber(Drive: TDriveNumber);
   begin
   if (Drive < DriveNumberMin) or (Drive > DriveNumberMax) then
     raise EIdeDriveInfo.CreateFmt('The drive number (%d) is out ' +
       'of range; the allowable range is %d to %d',
       [Drive, DriveNumberMin, DriveNumberMax]) end;

 function TIdeDriveInfo.GetCylinders(Drive: TDriveNumber): Integer;
   begin
   CheckDriveNumber(Drive);
   Result := FCylinders[Drive] end;

 function TIdeDriveInfo.GetFirmwareRevision(Drive: TDriveNumber):
   String;
   begin
   CheckDriveNumber(Drive);
   Result := FFirmwareRevision[Drive] end;

 function TIdeDriveInfo.GetHeads(Drive: TDriveNumber): Integer;
   begin
   CheckDriveNumber(Drive);
   Result := FHeads[Drive] end;

 function TIdeDriveInfo.GetModelNumber(Drive: TDriveNumber): String;
   begin
   CheckDriveNumber(Drive);
   Result := FModelNumber[Drive] end;

 function TIdeDriveInfo.GetRemovableMedia(Drive: TDriveNumber):
   Boolean;
   begin
   CheckDriveNumber(Drive);
   Result := FRemovableMedia[Drive] end;

 function TIdeDriveInfo.GetSectorsPerTrack(Drive: TDriveNumber):
   Integer;
   begin
   CheckDriveNumber(Drive);
   Result := FSectorsPerTrack[Drive] end;

 function TIdeDriveInfo.GetSerialNumber(Drive: TDriveNumber): String;
   begin
   CheckDriveNumber(Drive);
   Result := FSerialNumber[Drive] end;

 procedure TIdeDriveInfo.QueryDrive(Drive: TDriveNumber);
   var
     BytesReturned: DWord;
     CmdIn: TSendCmdInParams;
     CmdOut: TSendCmdOutParams;
     DriveName: String;
     H: THandle;
     I: Integer;
     VersionInfo: TGetVersionOutParams;
   begin
   FCylinders[Drive] := 0;
   FFirmwareRevision[Drive] := '';
   FHeads[Drive] := 0;
   FModelNumber[Drive] := '';
   FRemovableMedia[Drive] := False;
   FSectorsPerTrack[Drive] := 0;
   FSerialNumber[Drive] := '';
   DriveName := Format('\\.\PHYSICALDRIVE%d', [Drive]);
   H := CreateFile(PChar(DriveName), GENERIC_READ or GENERIC_WRITE, 0,
     nil, OPEN_EXISTING, 0, 0);
   if H = INVALID_HANDLE_VALUE then
     Exit;
   try
     FillChar(VersionInfo, SizeOf(VersionInfo), 0);
     BytesReturned := 0;
     if not DeviceIoControl(H, DFP_GET_VERSION, nil, 0, @VersionInfo,
       SizeOf(VersionInfo), BytesReturned, nil) then
       Exit;
     if not (cpIdeIdentify in VersionInfo.Capabilities) then
       Exit;
     FillChar(CmdIn, SizeOf(CmdIn), 0);
     CmdIn.BufferSize := 0;
     CmdIn.DriveRegs.Command := IDE_IDENTIFY_DEVICE;
     CmdIn.DriveNumber := Drive;
     FillChar(CmdOut, SizeOf(CmdOut), 0);
     CmdOut.BufferSize := SizeOf(CmdOut.Buffer);
     BytesReturned := 0;
     if not DeviceIoControl(H, DFP_RECEIVE_DRIVE_DATA, @CmdIn,
       SizeOf(CmdIn), @CmdOut, SizeOf(CmdOut), BytesReturned,
       nil) then
       Exit;
     with CmdOut do begin
       for I := 10 to 19 do
         Buffer[I] := (Lo(Buffer[I]) shl 8) + Hi(Buffer[I]);
       for I := 23 to 46 do
         Buffer[I] := (Lo(Buffer[I]) shl 8) + Hi(Buffer[I]);
       FRemovableMedia[Drive] := (Buffer[0] and $80) <> 0;
       FCylinders[Drive] := Buffer[1];
       FHeads[Drive] := Buffer[3];
       FSectorsPerTrack[Drive] := Buffer[6];
       SetLength(FSerialNumber[Drive], 20);
       Move(Buffer[10], FSerialNumber[Drive][1],
         Length(FSerialNumber[Drive]));
       FSerialNumber[Drive] := Trim(FSerialNumber[Drive]);
       SetLength(FFirmwareRevision[Drive], 8);
       Move(Buffer[23], FFirmwareRevision[Drive][1],
         Length(FFirmwareRevision[Drive]));
       FFirmwareRevision[Drive] := Trim(FFirmwareRevision[Drive]);
       SetLength(FModelNumber[Drive], 40);
       Move(Buffer[27], FModelNumber[Drive][1],
         Length(FModelNumber[Drive]));
       FModelNumber[Drive] := Trim(FModelNumber[Drive]) end;
     finally
       CloseHandle(H) end end;

 end.

This component gives only drive geomery and serial number. i must increase points :)
hehe :)
I will try to find another one later today
If anyone does come up with the answer to this, I would appreciate it...  Another way to do this would be to get the Drive (NOT VOLUME) serial number via the drive letter and compare that with the Serial numbers returnd by the controller.

If I find the answer I'll return here with a result.
Avatar of Ark
Hi
Sorry, I don't speak Delphy, my native language is VB and second one is C++ :)
Here is how I did this:
1. Get HDD signature, using DeviceIoControl on \\.\PHYSICALDRIVE_X with IOCTL_DISK_GET_DRIVE_LAYOUT
2. Loop through HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices\DosDevices\XXX values - first 4 bytes are drive signature, next 8 bytes - volume offset. So, select all devices with signature == your \\.\PHYSICALDRIVE_X and compare offsets - lowest offset will be VOLUME1, next - VOLUME2 etc.

Thanks ARK and others...
Yes that is excellent info.  I'll supply my full Delphi code shortly.  I have lots of info to add but had not found a 100% accurate method till now.  It sounds like  ARK has provided one.
I can provide ether VB or C++ code if you need...
Another way is using QueryDosDevice