Archive: Get hard disk number from drive letter


Get hard disk number from drive letter
  Hello, i am trying to work out the disk number (if you look in computer management > disk management each disk has a number 0 ,1 ,etc assigned) from a drive letter. Is this possible in any way?

This sample script gets the volume number (\Device\HarddiskVolume1) but its the disk number i need.

Any suggestions would be great.


!define name test
!define version 1.0

#Install Options
Name "${Name}"
OutFile "${Name}_${Version}.exe"
RequestExecutionLevel Admin
InstallDir "$TEMP\${Name}"
XPStyle on


Function QueryDosDevice
!define QueryDosDevice "Kernel32::QueryDosDevice(t,t,i) i"
System::Call '${QueryDosDevice}("$0",.r1,${NSIS_MAX_STRLEN})'
FunctionEnd

Section ""
StrCpy $0 "C:"
call QueryDosDevice
detailprint "disk= $1"
SectionEnd


Retrieve serial number from hard disk


>; Read/write access to I/O control handle of hard disk requires admin rights
RequestExecutionLevel admin

OutFile "HDDSerial.exe"
>Name "HDDSerial"

>!include "LogicLib.nsh"

>; File Access Modes
>!define GENERIC_READ 0x80000000
>!define GENERIC_WRITE 0x40000000

>; File Sharing Modes
>!define FILE_SHARE_READ 0x00000001
>!define FILE_SHARE_WRITE 0x00000002

>; File Creation Flags
>!define OPEN_EXISTING 3

>!define INVALID_HANDLE_VALUE -1

>; ATA identity command
>!define IDE_ATA_IDENTIFY 0xEC

>; ATA Register values
>!define IDE_DEVICE_MASTER 0xA0
>!define IDE_DEVICE_SLAVE 0xB0

>; I/O control command
>!define DFP_RECEIVE_DRIVE_DATA 0x0007c088

>!define IDENTITY_BUFFER_SIZE 512

>; Size of SENDCMDINPARAMS and SENDCMDOUTPARAMS structure
>!define SIZEOF_CMD_IN 0x20
>!define SIZEOF_CMD_OUT 0x10

>; HDD Serial number offset and length in ATA IDENTIFY structure
>!define HDD_SERIAL_OFFSET 0x14
>!define HDD_SERIAL_LENGTH 20


>; Get hard disk serial number from drive number
>; (starting with 0) provided as a parameter to
>; this function.
;The hard disk serial number is returned in $0.
>Function HDDSerial
; Save registers
Exch$1
Push$2
Push$3
Push$4
Push$5
Push$6
Push$7

; Get handle of physical drive
StrCpy$3 "\\\\.\\PhysicalDrive$1"
System::Call "kernel32::CreateFile(t r3, \\
i ${GENERIC_READ}|${GENERIC_WRITE}, \\
i ${FILE_SHARE_READ}|${FILE_SHARE_WRITE}, \\
i 0, i ${OPEN_EXISTING}, i 0, i 0) i.r2"
${If} $2 != ${INVALID_HANDLE_VALUE}
;Set the bCommandReg and bDriveHeadReg IDE Registers
IntOp$5 ${IDE_ATA_IDENTIFY} + 0
IntOp$5 $5 << 8
IntOp$7 $1 & 1
${If} $7 == 0
IntOp$5 $5 | ${IDE_DEVICE_MASTER}
${Else}
IntOp $5 $5 | ${IDE_DEVICE_SLAVE}
${EndIf}
IntOp $5 $5 << 8
; Allocate and fill SENDCMDINPARAMS structure
; cBufferSize, bSectorCountReg=1, bCommandReg/bDriveHeadReg, bDriveNumber
System
::Call "*(i ${IDENTITY_BUFFER_SIZE}, i 0x100, i r5, i r1, \\
i 0, i 0, i 0, i 0) i.r4"
; Allocate output buffer
IntOp$5 ${SIZEOF_CMD_OUT} + ${IDENTITY_BUFFER_SIZE}
System::Alloc $5
Pop$6
IntOp$7 0 + 0
; Send IDENTITY command
System::Call "kernel32::DeviceIoControl(i r2, \\
i ${DFP_RECEIVE_DRIVE_DATA}, \\
i r4, i ${SIZEOF_CMD_IN}, \\
i r6, i r5, \\
*i r7r7, i 0) i.r3"
${If} $3 != 0
; Extract HDD serial number
IntOp$5 ${SIZEOF_CMD_OUT} + ${HDD_SERIAL_OFFSET}
System::Call "*$6(&m$5, &m${HDD_SERIAL_LENGTH} .r0)"
${Else}
StrCpy $0 "Error: DeviceIoControl failed"
${EndIf}
System::Free $6
System::Free $4
System::Call "kernel32::CloseHandle(i r2) i.r3"
${Else}
StrCpy $0 "Error: CreateFile failed for \\\\.\\PhysicalDrive$1"
${EndIf}

; Restore registers
Pop$7
Pop$6
Pop$5
Pop$4
Pop$3
Pop$2
Pop$1
FunctionEnd

>Function .onInit
InitPluginsDir
Push 0
Call HDDSerial
MessageBox MB_OK "HDD Serial Number=$0"
Quit
FunctionEnd

Section
SectionEnd
>

The previous posted code served as a basis for this one.

GetVolumeNameForVolumeMountPoint returns the volume name
and the IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS command is used to get the hard disk number associated with the drive letter.


Get hard disk number from drive letter 


>; Read/write access to I/O control handle of hard disk requires admin rights
RequestExecutionLevel admin

OutFile "HDDNumber.exe"
>Name "HDDNumber"

>!include "LogicLib.nsh"

>; File Access Modes
>!define GENERIC_READ 0x80000000
>!define GENERIC_WRITE 0x40000000

>; File Sharing Modes
>!define FILE_SHARE_READ 0x00000001
>!define FILE_SHARE_WRITE 0x00000002

>; File Creation Flags
>!define OPEN_EXISTING 3

>!define INVALID_HANDLE_VALUE -1

>; Maximum length of volume GUID (including terminating zero)
!define MAXLEN_VOLUME_GUID 51

>; I/O control command
>!define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 0x00560000

>!define EXTENTS_BUFFER_SIZE 512

>; Get hard disk number from drive letter
>; provided as a parameter to this function.
;The hard disk number is returned in $0.
>Function HDDNumber
; Save registers
Exch$1
Push$2
Push$3
Push$4
Push$5
Push$6
Push$7

; Get volume name associated with drive letter
System
::Call "kernel32::GetVolumeNameForVolumeMountPoint(t r1, t r3r3, i ${MAXLEN_VOLUME_GUID}) i.r2"
${If} $2 != 0
; Get handle of volume
StrCpy$3 $3 -1
System::Call "kernel32::CreateFile(t r3, \\
i ${GENERIC_READ}|${GENERIC_WRITE}, \\
i ${FILE_SHARE_READ}|${FILE_SHARE_WRITE}, \\
i 0, i ${OPEN_EXISTING}, i 0, i 0) i.r2"
${If} $2 != ${INVALID_HANDLE_VALUE}
; Allocate output buffer
System::Alloc ${EXTENTS_BUFFER_SIZE}
Pop $4
IntOp$5 0 + 0
; Send IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS command
System::Call "kernel32::DeviceIoControl(i r2, \\
i ${IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS}, \\
i 0, i 0, \\
i r4, i ${EXTENTS_BUFFER_SIZE}, \\
*i r5r5, i 0) i.r3"
${If} $3 != 0
; Extract HDD number
System::Call "*$4(i .r5, i, i .r0)"
${If} $5 == 0
StrCpy$0 "Error: Invalid DISK_EXTENT data"
${EndIf}
${Else}
StrCpy $0 "Error: DeviceIoControl failed"
${EndIf}
System::Free $4
System::Call "kernel32::CloseHandle(i r2) i.r3"
${Else}
StrCpy $0 "Error: CreateFile failed for $3"
${EndIf}
${Else}
StrCpy $0 "Error: GetVolumeNameForVolumeMountPoint failed for $1"
${EndIf}

; Restore registers
Pop$7
Pop$6
Pop$5
Pop$4
Pop$3
Pop$2
Pop$1
FunctionEnd

>Function .onInit
InitPluginsDir
StrCpy$1 "C:\\"
Push $1
Call HDDNumber
MessageBox MB_OK "HDD Number for $1=$0"
Quit
FunctionEnd

Section
SectionEnd
>

thank u works just as i wanted it to.

would have never figured all that out :eek:


Batch file for showing Disk Number, Partition Number, Drive Letter, Drive Label
  @ECHO OFF
SETLOCAL
SETLOCAL ENABLEDELAYEDEXPANSION

REM This Batch file Finds, Displays and Saves the Following for each Drive on the Cmputer.
REM
REM Disk Number Partition Number Drive Letter Drive Label
REM
REM It was tested usng the "XP Home Edition" and will not work on versions prior to 2000
REM

REM ------------- Alphabet, Diskpart Script File Commands and File Names ----------------

REM L1, L3 ,L3 are commands for use in Diskpart.exe
REM S1 is the Location of the DiskPart.exe script file
REM S3 is the location of the resultant "Drive Disk Partition" Table

Set Alphabet=C D E F G H I J K L M N O P Q R S T U V W X Y Z
Set L1=Select Volume
set L2=List Volume
Set L3=List Disk
Set L4=List Partition
Set S1=DiskPartScript.txt
Set S2=DiskPart.txt
Set S3=DriveInfo.txt

Rem ---------------------------- Delete Existing Files -----------------------------------

If Exist %S1% Del %S1%
If Exist %S2% Del %S2%
If Exist %S3% Del %S3%
If Exist Vol.txt Del Vol.txt

REM ---------------------Build the "DiskPart.exe" Script File ----------------------------

For %%1 in (%Alphabet%) DO if Exist %%1:\Nul (Echo %L1% %%1>>%S1%)^
&(Echo %L2%>>%S1%)&(ECHO %L3%>>%S1%)^
&(ECHO %L4%>>%S1%)

Rem ----------------- Execute DiskPart Using the Above Script File------------------------

Diskpart /s %S1%>>%S2%

REM ------------------ Set the Drive Labels in "LBL*" Using "VOL"-------------------------

For %%1 in (%Alphabet%) DO if Exist %%1:\Nul Vol %%1:>>Vol.txt
For /f "Tokens=1-5* delims= " %%1 in (Vol.txt) DO If "%%2"=="in" Set LBL%%4=%%4 %%6

REM ------- Extract the Disk Number, Partition Number, Drive Letter & Volume Label -------

For /f "Tokens=1-5" %%1 in (%S2%) DO (If "%%1 %%2"=="* Volume" Set LBL=!LBL%%4!)^
&(If "%%1 %%2"=="* Disk" Set Line=%%3)^
&(If "%%1 %%2"=="* Partition" (Set Line=!Line! %%3)^
&(Set Line=!Line! !LBL!)&(ECHO !Line!>>%S3%))

REM -------------------------- Display the Results ---------------------------------------

ECHO.
ECHO.
Type %S3%
ECHO.
ECHO.

Rem --------------------------------- EXIT -----------------------------------------------

ECHO When Ready to Exit
Pause