Get partition letter?

Just starting out? Need help? Post your questions and find answers here.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4622
Joined: Sun Apr 12, 2009 6:27 am

Re: Get partition letter?

Post by RASHAD »

Hi
I hope it will be OK this time

Code: Select all

Structure PARTITION_INFORMATION    
    StartingOffset.q
    PartitionLength.q   
    HiddenSectors.l
    PartitionNumber.l
    PartitionType.b
    BootIndicator.b
    RecognizedPartition.b
    RewritePartition.b
    dummy.l
EndStructure

Structure DRIVE_LAYOUT_INFORMATION
   PartitionCount.l
   Signature.l
   PartitionEntry.PARTITION_INFORMATION[50]
EndStructure

Procedure.s GetPartitionType(type.b)
Select type
   Case 0
      ProcedureReturn "Unused"
   Case 1
      ProcedureReturn "12-bit FAT"
   Case 2, 3
      ProcedureReturn "Xenix"
   Case 4
      ProcedureReturn "16-bit FAT"
   Case 5
      ProcedureReturn "Extended"
   Case 6
      ProcedureReturn "Huge partition MS-DOS V4"
   Case 7
      ProcedureReturn "Installable File System (NTFS/HPFS/FAT64)"
   Case 8
      ProcedureReturn "OS/2 (v1.0-1.3 only)/AIX boot partition/Commodore DOS/SplitDrive/DELL partition spanning multiple drives/QNX 1.x and 2.x (qny)"
   Case 9
      ProcedureReturn "AIX data partition/Coherent filesystem/QNX 1.x and 2.x (qnz)"
   Case $A
      ProcedureReturn "OS/2 Boot Manager/OPUS/Coherent swap"
   Case $B
      ProcedureReturn "FAT32"
   Case $C
      ProcedureReturn "FAT32 using extended int13 services"
   Case $E
      ProcedureReturn "Win95 partition using extended int13 services"
   Case $F
      ProcedureReturn "Extended using extended int13 services"
   Case $41
      ProcedureReturn "PowerPC Reference Platform (PReP) Boot Partition"
   Case $42
      ProcedureReturn "Logical Disk Manager partition"
   Case $63
      ProcedureReturn "Unix"
   Case $C0
      ProcedureReturn "NTFT uses high order bits"
   Case $80
      ProcedureReturn "NTFT"
EndSelect
EndProcedure

Procedure.s SpaceDivider(space.q)
tm.s:mt.d=space: GroupDemicals.s = ","
If mt>1000: mt / 1024:tm = " KB":EndIf
If mt>1000: mt / 1024:tm = " MB":EndIf
If mt>1000: mt / 1024:tm = " GB":EndIf
If mt>1000: mt / 1024:tm = " TB":EndIf
ProcedureReturn ReplaceString(StrD(mt,3), ".", GroupDemicals) + tm
EndProcedure

IOCTL_DISK_GET_DRIVE_LAYOUT.l = 475148
aa.DRIVE_LAYOUT_INFORMATION
IOCTL_DISK_GET_PARTITION_INFO.l = 475140
bb.PARTITION_INFORMATION

Dim Drv(0)
Dim Part.q(0)
mask = GetLogicalDrives_()
For HDSpace = 0 To 31
  If mask  & (1 << HDSpace )
      Drive$ = Chr(65+HDSpace)+":\"
      Result = GetDriveType_(@Drive$)
      If Result = 3
          Partition$ = "\\.\\.\"+ Chr(65+HDSpace)+":"
          hDrive = CreateFile_(Partition$,#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ + #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0,  0)
          Result = DeviceIoControl_(hDrive,IOCTL_DISK_GET_PARTITION_INFO, #Null,0,@bb, SizeOf(PARTITION_INFORMATION), @BytesRet,0)
          If Result = 1
               CloseHandle_(hDrive)
               ReDim Drv(x+1)
               ReDim Part(x+1)               
               Drv(x+1) = 65+HDSpace
               Part(x+1) = bb\PartitionLength
               x + 1
          EndIf
      EndIf
  EndIf
Next

For ii=0 To 49
   ; BytesRet = 0: tmp = 0
   hdh.l = CreateFile_("\\.\PhysicalDrive" + Str(ii),#GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE,0, #OPEN_EXISTING, 0, 0)
   Result = DeviceIoControl_(hdh,IOCTL_DISK_GET_DRIVE_LAYOUT, #Null,0,@aa, SizeOf(DRIVE_LAYOUT_INFORMATION), @BytesRet,0)   
   If Result = 1   
      For i=0 To aa\PartitionCount-1 
         If aa\PartitionEntry[i]\PartitionNumber > 0 And aa\PartitionEntry[i]\StartingOffset > 0
              For k = 1 To x              
                  If aa\PartitionEntry[i]\PartitionLength = part(k)
                      DriveLabel$ = Chr(Drv(k)) +":\"
                  EndIf
              Next
          Debug DriveLabel$ + "  Partition # " + Str(aa\PartitionEntry[i]\PartitionNumber) + "   "+GetPartitionType(aa\PartitionEntry[i]\PartitionType) + " , length  =  " + Str(aa\PartitionEntry[i]\PartitionLength) + " bytes (" + SpaceDivider(aa\PartitionEntry[i]\PartitionLength) + ")"
          Debug "Starting Offset = " + Str(aa\PartitionEntry[i]\StartingOffset)
          Debug "Partition Length = " + Str(aa\PartitionEntry[i]\PartitionLength)
          Debug "Hidden Sectors = " + Str(aa\PartitionEntry[i]\HiddenSectors)
          Debug "Partition Number = " + Str(aa\PartitionEntry[i]\PartitionNumber)
          Debug "Partition Type = " + Str(aa\PartitionEntry[i]\PartitionType)
          Debug "Boot Indicator = " + Str(aa\PartitionEntry[i]\BootIndicator)
          Debug "Recognized Partition = " + Str(aa\PartitionEntry[i]\RecognizedPartition)
          Debug "Rewrite Partition = " + Str(aa\PartitionEntry[i]\RewritePartition)
          Debug "dummy = " + Str(aa\PartitionEntry[i]\dummy)
          Debug "================"
        EndIf
      Next
      Debug ""
   EndIf
Next
Egypt my love
User avatar
doctorized
Addict
Addict
Posts: 854
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: Get partition letter?

Post by doctorized »

Now I get this:
Partition # 1 Installable File System (NTFS/HPFS/FAT64) , length = 104857600 bytes (100,000 MB)
Starting Offset = 1048576
Partition Length = 104857600
Hidden Sectors = 2048
Partition Number = 1
Partition Type = 7
Boot Indicator = 1
Recognized Partition = 1
Rewrite Partition = 0
dummy = -1408
================
C:\ Partition # 2 Installable File System (NTFS/HPFS/FAT64) , length = 127928369152 bytes (119,143 GB)
Starting Offset = 105906176
Partition Length = 127928369152
Hidden Sectors = 206848
Partition Number = 2
Partition Type = 7
Boot Indicator = 0
Recognized Partition = 1
Rewrite Partition = 0
dummy = 0
================

D:\ Partition # 1 Installable File System (NTFS/HPFS/FAT64) , length = 128848978944 bytes (120,000 GB)
Starting Offset = 32256
Partition Length = 128848978944
Hidden Sectors = 63
Partition Number = 1
Partition Type = 7
Boot Indicator = 1
Recognized Partition = 1
Rewrite Partition = 0
dummy = 0
================
F:\ Partition # 2 Installable File System (NTFS/HPFS/FAT64) , length = 128849011200 bytes (120,000 GB)
Starting Offset = 128849011200
Partition Length = 128849011200
Hidden Sectors = 251658225
Partition Number = 2
Partition Type = 7
Boot Indicator = 0
Recognized Partition = 1
Rewrite Partition = 0
dummy = 0
================
F:\ Partition # 3 Installable File System (NTFS/HPFS/FAT64) , length = 128849011200 bytes (120,000 GB)
Starting Offset = 257698022400
Partition Length = 128849011200
Hidden Sectors = 503316450
Partition Number = 3
Partition Type = 7
Boot Indicator = 0
Recognized Partition = 1
Rewrite Partition = 0
dummy = 131072
================
G:\ Partition # 4 Installable File System (NTFS/HPFS/FAT64) , length = 113558215680 bytes (105,759 GB)
Starting Offset = 386547033600
Partition Length = 113558215680
Hidden Sectors = 754974675
Partition Number = 4
Partition Type = 7
Boot Indicator = 0
Recognized Partition = 1
Rewrite Partition = 0
dummy = 0
================
Two F: and no E: partition. This is obvious as they have exactly the same size. So, I did a small change. I added a new array Offset.q() and changed

Code: Select all

If aa\PartitionEntry[i]\PartitionLength = part(k)
to

Code: Select all

If aa\PartitionEntry[i]\PartitionLength = part(k) And aa\PartitionEntry[i]\StartingOffset = Offset(k)
With this chages I get hte data correctly. Thanx a lot!!
hoangdiemtinh
User
User
Posts: 29
Joined: Wed Nov 16, 2022 1:51 pm

Re: Get partition letter?

Post by hoangdiemtinh »

I tested on Windows 10 x64 (PB 6 x64), run it as admin.

Result:
- DeviceIoControl return 0 for GPT Disks, so I can not get disk information
- Lettet D:\ duplicated
- Lettet F:\ duplicated
Please review and fix.

Code: Select all

[14:48:35] [Debug] C:\  Partition # 1   Installable File System (NTFS/HPFS/FAT64) , length  =  54761881600 bytes (51,001 GB)
[14:48:35] [Debug] Partition Number = 1
[14:48:35] [Debug] Partition Type = 7
[14:48:35] [Debug] Boot Indicator = 1
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] D:\  Partition # 2   Installable File System (NTFS/HPFS/FAT64) , length  =  73271345152 bytes (68,239 GB)
[14:48:35] [Debug] Partition Number = 2
[14:48:35] [Debug] Partition Type = 7
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] 
[14:48:35] [Debug] D:\  Partition # 1    , length  =  104857600 bytes (100,000 MB)
[14:48:35] [Debug] Partition Number = 1
[14:48:35] [Debug] Partition Type = 27
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] F:\  Partition # 2   Installable File System (NTFS/HPFS/FAT64) , length  =  63535316992 bytes (59,172 GB)
[14:48:35] [Debug] Partition Number = 2
[14:48:35] [Debug] Partition Type = 7
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] F:\  Partition # 3    , length  =  12967739392 bytes (12,077 GB)
[14:48:35] [Debug] Partition Number = 3
[14:48:35] [Debug] Partition Type = -125
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] G:\  Partition # 4   Installable File System (NTFS/HPFS/FAT64) , length  =  169000042496 bytes (157,394 GB)
[14:48:35] [Debug] Partition Number = 4
[14:48:35] [Debug] Partition Type = 7
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] 
[14:48:35] [Debug] H:\  Partition # 1   Installable File System (NTFS/HPFS/FAT64) , length  =  256025911296 bytes (238,443 GB)
[14:48:35] [Debug] Partition Number = 1
[14:48:35] [Debug] Partition Type = 7
[14:48:35] [Debug] Boot Indicator = 1
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] I:\  Partition # 2    , length  =  33554432 bytes (32,000 MB)
[14:48:35] [Debug] Partition Number = 2
[14:48:35] [Debug] Partition Type = -17
[14:48:35] [Debug] Boot Indicator = 0
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] 
[14:48:35] [Debug] I:\  Partition # 1   FAT32 using extended int13 services , length  =  8471431680 bytes (7,890 GB)
[14:48:35] [Debug] Partition Number = 1
[14:48:35] [Debug] Partition Type = 12
[14:48:35] [Debug] Boot Indicator = 1
[14:48:35] [Debug] Recognized Partition = 1
[14:48:35] [Debug] ================
[14:48:35] [Debug] 
Fred
Administrator
Administrator
Posts: 16581
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Get partition letter?

Post by Fred »

Did you apply the fix from doctorized in the post just above yours ?
hoangdiemtinh
User
User
Posts: 29
Joined: Wed Nov 16, 2022 1:51 pm

Re: Get partition letter?

Post by hoangdiemtinh »

@fred

Code: Select all

Offset() is not a function, array, macro, or linked list.
ZX80
Enthusiast
Enthusiast
Posts: 330
Joined: Mon Dec 12, 2016 1:37 pm

Re: Get partition letter?

Post by ZX80 »

hoangdiemtinh, please, try/check it & report.

Code: Select all

...   ; string 75 == "Empty"
Dim Drv(0)
Dim Part.q(0)
Dim Offset.q(0)  ; <---  this string was added
...              ; string 79 == "mask = GetLogicalDrives_()"
...              ; string 89 ==  "CloseHandle_(hDrive)"
ReDim Drv(x+1)
ReDim Part(x+1)
ReDim Offset(x+1)  ; <---  this string was added
Drv(x+1) = 65+HDSpace
Part(x+1) = bb\PartitionLength
Offset(x+1) = bb\StartingOffset  ; <---  this string was added
...              ; string 96 == "x + 1"
...              ; string 110 was changed and now it ==
If aa\PartitionEntry[i]\PartitionLength = part(k) And aa\PartitionEntry[i]\StartingOffset = Offset(k)
...  
After you make these changes in the original RASHAD's source code, everything should work.
Good luck!
hoangdiemtinh
User
User
Posts: 29
Joined: Wed Nov 16, 2022 1:51 pm

Re: Get partition letter?

Post by hoangdiemtinh »

@zx80

Error offset: ok, done. But it duplicate Letter (for my disk - Letter D) and ignore Letter (for my PC, letter E:\ - on GPT disk)

Code: Select all

[20:04:18] Đang chờ Tập tin thực thi bắt đầu...
[20:04:18] Kiểu thực thi: Windows - x64  (64bit, Unicode)
[20:04:18] Tập tin thực thi đã bắt đầu.
[20:04:18] [Debug] C:\  Partition # 1   Installable File System (NTFS/HPFS/FAT64) , length  =  54761881600 bytes (51,001 GB)
[20:04:18] [Debug] Starting Offset = 1048576
[20:04:18] [Debug] Partition Length = 54761881600
[20:04:18] [Debug] Hidden Sectors = 2048
[20:04:18] [Debug] Partition Number = 1
[20:04:18] [Debug] Partition Type = 7
[20:04:18] [Debug] Boot Indicator = 1
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] D:\  Partition # 2   Installable File System (NTFS/HPFS/FAT64) , length  =  73271345152 bytes (68,239 GB)
[20:04:18] [Debug] Starting Offset = 54763978752
[20:04:18] [Debug] Partition Length = 73271345152
[20:04:18] [Debug] Hidden Sectors = 2048
[20:04:18] [Debug] Partition Number = 2
[20:04:18] [Debug] Partition Type = 7
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] 
[20:04:18] [Debug] D:\  Partition # 1    , length  =  104857600 bytes (100,000 MB)
[20:04:18] [Debug] Starting Offset = 315621376
[20:04:18] [Debug] Partition Length = 104857600
[20:04:18] [Debug] Hidden Sectors = 616448
[20:04:18] [Debug] Partition Number = 1
[20:04:18] [Debug] Partition Type = 27
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] F:\  Partition # 2   Installable File System (NTFS/HPFS/FAT64) , length  =  63535316992 bytes (59,172 GB)
[20:04:18] [Debug] Starting Offset = 554696704
[20:04:18] [Debug] Partition Length = 63535316992
[20:04:18] [Debug] Hidden Sectors = 1083392
[20:04:18] [Debug] Partition Number = 2
[20:04:18] [Debug] Partition Type = 7
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] F:\  Partition # 3    , length  =  12967739392 bytes (12,077 GB)
[20:04:18] [Debug] Starting Offset = 64090013696
[20:04:18] [Debug] Partition Length = 12967739392
[20:04:18] [Debug] Hidden Sectors = 125175808
[20:04:18] [Debug] Partition Number = 3
[20:04:18] [Debug] Partition Type = -125
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] G:\  Partition # 4   Installable File System (NTFS/HPFS/FAT64) , length  =  169000042496 bytes (157,394 GB)
[20:04:18] [Debug] Starting Offset = 81059119104
[20:04:18] [Debug] Partition Length = 169000042496
[20:04:18] [Debug] Hidden Sectors = 63
[20:04:18] [Debug] Partition Number = 4
[20:04:18] [Debug] Partition Type = 7
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] 
[20:04:18] [Debug] H:\  Partition # 1   Installable File System (NTFS/HPFS/FAT64) , length  =  256025911296 bytes (238,443 GB)
[20:04:18] [Debug] Starting Offset = 1048576
[20:04:18] [Debug] Partition Length = 256025911296
[20:04:18] [Debug] Hidden Sectors = 2048
[20:04:18] [Debug] Partition Number = 1
[20:04:18] [Debug] Partition Type = 7
[20:04:18] [Debug] Boot Indicator = 1
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] I:\  Partition # 2    , length  =  33554432 bytes (32,000 MB)
[20:04:18] [Debug] Starting Offset = 256026959872
[20:04:18] [Debug] Partition Length = 33554432
[20:04:18] [Debug] Hidden Sectors = 500052656
[20:04:18] [Debug] Partition Number = 2
[20:04:18] [Debug] Partition Type = -17
[20:04:18] [Debug] Boot Indicator = 0
[20:04:18] [Debug] Recognized Partition = 1
[20:04:18] [Debug] Rewrite Partition = 0
[20:04:18] [Debug] dummy = 0
[20:04:18] [Debug] ================
[20:04:18] [Debug] 
[20:04:18] Việc thực thi chương trình đã kết thúc.

Last edited by hoangdiemtinh on Thu Dec 01, 2022 3:00 am, edited 2 times in total.
ZX80
Enthusiast
Enthusiast
Posts: 330
Joined: Mon Dec 12, 2016 1:37 pm

Re: Get partition letter?

Post by ZX80 »

2 hoangdiemtinh
Sorry. I can't reproduce your situation. I just did the changes that Fred pointed out.
Maybe someone else...
breeze4me
Enthusiast
Enthusiast
Posts: 500
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Get partition letter?

Post by breeze4me »

Tested on Windows 10 x64.

Code: Select all

Structure PARTITION_INFORMATION_MBR Align #PB_Structure_AlignC
  PartitionType.b
  BootIndicator.b
  RecognizedPartition.b
  HiddenSectors.l
  PartitionId.GUID
EndStructure

Structure PARTITION_INFORMATION_GPT Align #PB_Structure_AlignC
  PartitionType.GUID
  PartitionId.GUID
  Attributes.q
  Name.c[36]
EndStructure

Structure PARTITION_INFORMATION_EX Align #PB_Structure_AlignC
  PartitionStyle.l
  StartingOffset.q
  PartitionLength.q
  PartitionNumber.l
  RewritePartition.b
  IsServicePartition.b
  StructureUnion
    Mbr.PARTITION_INFORMATION_MBR
    Gpt.PARTITION_INFORMATION_GPT
  EndStructureUnion
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_MBR Align #PB_Structure_AlignC
  Signature.l
  CheckSum.l
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_GPT Align #PB_Structure_AlignC
  DiskId.GUID
  StartingUsableOffset.q
  UsableLength.q
  MaxPartitionCount.l
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_EX Align #PB_Structure_AlignC
  PartitionStyle.l
  PartitionCount.l
  StructureUnion
    Mbr.DRIVE_LAYOUT_INFORMATION_MBR
    Gpt.DRIVE_LAYOUT_INFORMATION_GPT
  EndStructureUnion
  PartitionEntry.PARTITION_INFORMATION_EX[50]
EndStructure

; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-drive_layout_information_ex
; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ne-winioctl-partition_style
#PARTITION_STYLE_MBR = 0 ;Master boot record (MBR) format.
#PARTITION_STYLE_GPT = 1 ;GUID Partition Table (GPT) format.
#PARTITION_STYLE_RAW = 2 ;Partition Not formatted in either of the recognized formats - MBR Or GPT.

Procedure.s GetPartitionStyle(Style)
  Select Style
    Case #PARTITION_STYLE_MBR
      ProcedureReturn "MBR"
    Case #PARTITION_STYLE_GPT
      ProcedureReturn "GPT"
    Case #PARTITION_STYLE_RAW
      ProcedureReturn "RAW"
  EndSelect
  
  ProcedureReturn ""
EndProcedure

Procedure.s GetGptPartitionType(*Type.GUID)
  Protected sResult.s, sGUID.s{64}
  If StringFromGUID2_(*Type, @sGUID, 63) > 0
    sGUID = RemoveString(sGUID, "{")
    sGUID = RemoveString(sGUID, "}")
    sGUID = LCase(sGUID)
    
    ; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-partition_information_gpt
    Select sGUID
      Case "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
        sResult = "PARTITION BASIC DATA"
        
      Case "00000000-0000-0000-0000-000000000000"
        sResult = "PARTITION ENTRY UNUSED"
        
      Case "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
        sResult = "PARTITION SYSTEM"
        
      Case "e3c9e316-0b5c-4db8-817d-f92df00215ae"
        sResult = "PARTITION MSFT RESERVED"
        
      Case "5808c8aa-7e8f-42e0-85d2-e1e90434cfb3"
        sResult = "PARTITION LDM METADATA"
        
      Case "af9b60a0-1431-4f62-bc68-3311714a69ad"
        sResult = "PARTITION LDM DATA"
        
      Case "de94bba4-06d1-4d40-a16a-bfd50179d6ac"
        sResult = "PARTITION MSFT RECOVERY"
        
    EndSelect
  EndIf
  ProcedureReturn sResult
EndProcedure

Procedure.s GetPartitionType(type.b)
  ; Disk Partition Types
  ; https://learn.microsoft.com/en-us/windows/win32/fileio/disk-partition-types
  
  Select type
    Case 0
      ProcedureReturn "Unused"
    Case 1
      ProcedureReturn "12-bit FAT"
    Case 2, 3
      ProcedureReturn "Xenix"
    Case 4
      ProcedureReturn "16-bit FAT"
    Case 5
      ProcedureReturn "Extended"
    Case 6
      ProcedureReturn "Huge partition MS-DOS V4"
    Case 7
      ProcedureReturn "Installable File System (NTFS/HPFS/FAT64)"
    Case 8
      ProcedureReturn "OS/2 (v1.0-1.3 only)/AIX boot partition/Commodore DOS/SplitDrive/DELL partition spanning multiple drives/QNX 1.x and 2.x (qny)"
    Case 9
      ProcedureReturn "AIX data partition/Coherent filesystem/QNX 1.x and 2.x (qnz)"
    Case $A
      ProcedureReturn "OS/2 Boot Manager/OPUS/Coherent swap"
    Case $B
      ProcedureReturn "FAT32"
    Case $C
      ProcedureReturn "FAT32 using extended int13 services"
    Case $E
      ProcedureReturn "Win95 partition using extended int13 services"
    Case $F
      ProcedureReturn "Extended using extended int13 services"
    Case $41
      ProcedureReturn "PowerPC Reference Platform (PReP) Boot Partition"
    Case $42
      ProcedureReturn "Logical Disk Manager partition"
    Case $63
      ProcedureReturn "Unix"
    Case $C0
      ProcedureReturn "NTFT uses high order bits"
    Case $80
      ProcedureReturn "NTFT"
  EndSelect
EndProcedure

Procedure.s SpaceDivider(space.q)
  Protected sGroupDemicals.s{4}
  tm.s : mt.d = space
  If mt>1000: mt / 1024:tm = " KB":EndIf
  If mt>1000: mt / 1024:tm = " MB":EndIf
  If mt>1000: mt / 1024:tm = " GB":EndIf
  If mt>1000: mt / 1024:tm = " TB":EndIf
  If GetLocaleInfo_(#LOCALE_USER_DEFAULT, #LOCALE_SDECIMAL, @sGroupDemicals, 4) > 0
    ProcedureReturn ReplaceString(StrD(mt,3), ".", sGroupDemicals) + tm
  EndIf
  ProcedureReturn StrD(mt,3) + tm
EndProcedure

; IOCTL_DISK_GET_PARTITION_INFO_EX IOCTL (winioctl.h)
; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-ioctl_disk_get_partition_info_ex

; The disk support can be summarized as follows. Currently, GPT is supported only on 64-bit systems.

; Disk type                         IOCTL_DISK_GET_PARTITION_INFO   IOCTL_DISK_GET_PARTITION_INFO_EX
; Basic master boot record (MBR)    Yes                             Yes
; Basic GUID partition table (GPT)  No                              Yes
; Dynamic MBR boot/system           Yes                             Yes
; Dynamic MBR data                  Yes                             No
; Dynamic GPT boot/system           No                              Yes
; Dynamic GPT data                  No                              No

Macro CTL_CODE( DeviceType, Function, Method, Access )
  (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
EndMacro

#FILE_DEVICE_DISK = 7
#IOCTL_DISK_BASE = #FILE_DEVICE_DISK
#METHOD_BUFFERED = 0
#FILE_ANY_ACCESS = 0
#IOCTL_DISK_GET_PARTITION_INFO_EX = CTL_CODE(#IOCTL_DISK_BASE, $12, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
#IOCTL_DISK_GET_DRIVE_LAYOUT_EX = CTL_CODE(#IOCTL_DISK_BASE, $14, #METHOD_BUFFERED, #FILE_ANY_ACCESS)

Structure PartData
  sDrive.s
  PartitionID.GUID
EndStructure

NewList Partition.PartData()

aa.DRIVE_LAYOUT_INFORMATION_EX
bb.PARTITION_INFORMATION_EX

mask = GetLogicalDrives_()
For HDSpace = 0 To 31
  If mask  & (1 << HDSpace )
    Drive$ = Chr(65+HDSpace)+":\"
    Result = GetDriveType_(@Drive$)
    If Result = 3
      Partition$ = "\\.\"+ Chr(65+HDSpace)+":"
      hDrive = CreateFile_(Partition$, #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
      If hDrive <> #INVALID_HANDLE_VALUE
        Result = DeviceIoControl_(hDrive,#IOCTL_DISK_GET_PARTITION_INFO_EX, #Null,0,@bb, SizeOf(PARTITION_INFORMATION_EX), @BytesRet,0)
        If Result
          If AddElement(Partition())
            Partition()\sDrive = Drive$
            
            Select bb\PartitionStyle
              Case #PARTITION_STYLE_MBR
                CopyMemory(@bb\Mbr\PartitionId, @Partition()\PartitionID, SizeOf(GUID))
                
              Case #PARTITION_STYLE_GPT
                CopyMemory(@bb\Gpt\PartitionId, @Partition()\PartitionID, SizeOf(GUID))
                
              Case #PARTITION_STYLE_RAW
                Debug Drive$ + " = RAW"
            EndSelect
          EndIf
        EndIf
        CloseHandle_(hDrive)
      EndIf
    EndIf
  EndIf
Next

For ii=0 To 49
  hdh = CreateFile_("\\.\PhysicalDrive" + Str(ii), #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
  If hdh <> #INVALID_HANDLE_VALUE
    Result = DeviceIoControl_(hdh, #IOCTL_DISK_GET_DRIVE_LAYOUT_EX, #Null,0,@aa, SizeOf(DRIVE_LAYOUT_INFORMATION_EX), @BytesRet,0)   
    If Result
      Debug "PhysicalDrive " + ii +  " , PartitionCount: " + aa\PartitionCount
      
      For i=0 To aa\PartitionCount-1 
        If aa\PartitionEntry[i]\PartitionNumber > 0 And aa\PartitionEntry[i]\StartingOffset > 0
          Debug "  Partition # " + Str(aa\PartitionEntry[i]\PartitionNumber) + "   "+GetPartitionStyle(aa\PartitionEntry[i]\PartitionStyle) + " , length  =  " + Str(aa\PartitionEntry[i]\PartitionLength) + " bytes (" + SpaceDivider(aa\PartitionEntry[i]\PartitionLength) + ")"
          
          Select aa\PartitionEntry[i]\PartitionStyle
            Case #PARTITION_STYLE_MBR
              ForEach Partition()
                If CompareMemory(@Partition()\PartitionID, @aa\PartitionEntry[i]\Mbr\PartitionId, SizeOf(GUID))
                  Debug "Drive = " + Partition()\sDrive
                  Break
                EndIf
              Next
              Debug "Type = " + GetPartitionType(aa\PartitionEntry[i]\Mbr\PartitionType)
              Debug "Hidden Sectors = " + Str(aa\PartitionEntry[i]\Mbr\HiddenSectors)
              Debug "Boot Indicator = " + Str(aa\PartitionEntry[i]\Mbr\BootIndicator)
              Debug "Recognized Partition = " + Str(aa\PartitionEntry[i]\Mbr\RecognizedPartition)
              
            Case #PARTITION_STYLE_GPT
              ForEach Partition()
                If CompareMemory(@Partition()\PartitionID, @aa\PartitionEntry[i]\Gpt\PartitionId, SizeOf(GUID))
                  Debug "Drive = " + Partition()\sDrive
                  Break
                EndIf
              Next
              Debug "Type = " + GetGptPartitionType(@aa\PartitionEntry[i]\Gpt\PartitionType)
              
            Case #PARTITION_STYLE_RAW
              Debug "Type = RAW"
              
          EndSelect
          
          Debug "Starting Offset = " + Str(aa\PartitionEntry[i]\StartingOffset)
          Debug "Partition Length = " + Str(aa\PartitionEntry[i]\PartitionLength)
          Debug "Partition Number = " + Str(aa\PartitionEntry[i]\PartitionNumber)
          Debug "Rewrite Partition = " + Str(aa\PartitionEntry[i]\RewritePartition)
          
          Debug "================"
        EndIf
      Next
      Debug ""
    EndIf
    
    CloseHandle_(hdh)
  EndIf
Next
hoangdiemtinh
User
User
Posts: 29
Joined: Wed Nov 16, 2022 1:51 pm

Re: Get partition letter?

Post by hoangdiemtinh »

Thanks @breeze4me. Great line of code.

I tested on Win 10 x64 running PB6, everything works smoothly. And there is 1 problem that is not correct, that is Partition Count.
As on my computer I plug in 4 HDDs:
+ where hard drive is at index 0 (MBR, system disk), see in Disk Management it has 2 partitions. After running the code I got the result for Partition Count as 8.
+ where the hard drive is at index 2 (MBR disk), see in the Disk Management it has 7 partitions (both linux, windows, unallocated,... partitions. The first partition is an unallocated partition). After running the code I got the result for Partition Count as 8.
+ where the hard drive is at index 3 (MBR disk), see in the Disk Management it has 2 partitions. After running the code I got the result for Partition Count as 4.
.
Image
.
This is image of Disk 2 (index 2) on DiskGenius Partition software:
.
Image
.
(Sorry for my bad English, English is not main my language)

@breeze4me, please fix.

Code: Select all

[08:27:25] [Debug] PhysicalDrive 0 , PartitionCount: 8
[08:27:25] [Debug]   Partition # 1   MBR , length  =  54761881600 bytes (51.001 GB)
[08:27:25] [Debug] Drive = C:\
[08:27:25] [Debug] Type = Installable File System (NTFS/HPFS/FAT64)
[08:27:25] [Debug] Hidden Sectors = 2048
[08:27:25] [Debug] Boot Indicator = 1
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 1048576
[08:27:25] [Debug] Partition Length = 54761881600
[08:27:25] [Debug] Partition Number = 1
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 2   MBR , length  =  73271345152 bytes (68.239 GB)
[08:27:25] [Debug] Drive = D:\
[08:27:25] [Debug] Type = Installable File System (NTFS/HPFS/FAT64)
[08:27:25] [Debug] Hidden Sectors = 2048
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 54763978752
[08:27:25] [Debug] Partition Length = 73271345152
[08:27:25] [Debug] Partition Number = 2
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug] 
[08:27:25] [Debug] PhysicalDrive 1 , PartitionCount: 2
[08:27:25] [Debug]   Partition # 1   GPT , length  =  320038313472 bytes (298.059 GB)
[08:27:25] [Debug] Drive = E:\
[08:27:25] [Debug] Type = PARTITION BASIC DATA
[08:27:25] [Debug] Starting Offset = 1048576
[08:27:25] [Debug] Partition Length = 320038313472
[08:27:25] [Debug] Partition Number = 1
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 2   GPT , length  =  33554432 bytes (32.000 MB)
[08:27:25] [Debug] Type = PARTITION BASIC DATA
[08:27:25] [Debug] Starting Offset = 320039362048
[08:27:25] [Debug] Partition Length = 33554432
[08:27:25] [Debug] Partition Number = 2
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug] 
[08:27:25] [Debug] PhysicalDrive 2 , PartitionCount: 8
[08:27:25] [Debug]   Partition # 1   MBR , length  =  104857600 bytes (100.000 MB)
[08:27:25] [Debug] Type = 
[08:27:25] [Debug] Hidden Sectors = 616448
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 315621376
[08:27:25] [Debug] Partition Length = 104857600
[08:27:25] [Debug] Partition Number = 1
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 2   MBR , length  =  63535316992 bytes (59.172 GB)
[08:27:25] [Debug] Drive = F:\
[08:27:25] [Debug] Type = Installable File System (NTFS/HPFS/FAT64)
[08:27:25] [Debug] Hidden Sectors = 1083392
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 554696704
[08:27:25] [Debug] Partition Length = 63535316992
[08:27:25] [Debug] Partition Number = 2
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 3   MBR , length  =  12967739392 bytes (12.077 GB)
[08:27:25] [Debug] Type = 
[08:27:25] [Debug] Hidden Sectors = 125175808
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 64090013696
[08:27:25] [Debug] Partition Length = 12967739392
[08:27:25] [Debug] Partition Number = 3
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 4   MBR , length  =  169000042496 bytes (157.394 GB)
[08:27:25] [Debug] Drive = G:\
[08:27:25] [Debug] Type = Installable File System (NTFS/HPFS/FAT64)
[08:27:25] [Debug] Hidden Sectors = 63
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 81059119104
[08:27:25] [Debug] Partition Length = 169000042496
[08:27:25] [Debug] Partition Number = 4
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug] 
[08:27:25] [Debug] PhysicalDrive 3 , PartitionCount: 4
[08:27:25] [Debug]   Partition # 1   MBR , length  =  256025911296 bytes (238.443 GB)
[08:27:25] [Debug] Drive = H:\
[08:27:25] [Debug] Type = Installable File System (NTFS/HPFS/FAT64)
[08:27:25] [Debug] Hidden Sectors = 2048
[08:27:25] [Debug] Boot Indicator = 1
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 1048576
[08:27:25] [Debug] Partition Length = 256025911296
[08:27:25] [Debug] Partition Number = 1
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug]   Partition # 2   MBR , length  =  33554432 bytes (32.000 MB)
[08:27:25] [Debug] Drive = I:\
[08:27:25] [Debug] Type = 
[08:27:25] [Debug] Hidden Sectors = 500052656
[08:27:25] [Debug] Boot Indicator = 0
[08:27:25] [Debug] Recognized Partition = 1
[08:27:25] [Debug] Starting Offset = 256026959872
[08:27:25] [Debug] Partition Length = 33554432
[08:27:25] [Debug] Partition Number = 2
[08:27:25] [Debug] Rewrite Partition = 0
[08:27:25] [Debug] ================
[08:27:25] [Debug] 
++++++++++++++++++++++++++++++++++++++

Code: Select all

Structure PARTITION_INFORMATION_MBR Align #PB_Structure_AlignC
  PartitionType.b
  BootIndicator.b
  RecognizedPartition.b
  HiddenSectors.l
  PartitionId.GUID
EndStructure

Structure PARTITION_INFORMATION_GPT Align #PB_Structure_AlignC
  PartitionType.GUID
  PartitionId.GUID
  Attributes.q
  Name.c[36]
EndStructure

Structure PARTITION_INFORMATION_EX Align #PB_Structure_AlignC
  PartitionStyle.l
  StartingOffset.q
  PartitionLength.q
  PartitionNumber.l
  RewritePartition.b
  IsServicePartition.b
  StructureUnion
    Mbr.PARTITION_INFORMATION_MBR
    Gpt.PARTITION_INFORMATION_GPT
  EndStructureUnion
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_MBR Align #PB_Structure_AlignC
  Signature.l
  CheckSum.l
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_GPT Align #PB_Structure_AlignC
  DiskId.GUID
  StartingUsableOffset.q
  UsableLength.q
  MaxPartitionCount.l
EndStructure

Structure DRIVE_LAYOUT_INFORMATION_EX Align #PB_Structure_AlignC
  PartitionStyle.l
  PartitionCount.l
  StructureUnion
    Mbr.DRIVE_LAYOUT_INFORMATION_MBR
    Gpt.DRIVE_LAYOUT_INFORMATION_GPT
  EndStructureUnion
  PartitionEntry.PARTITION_INFORMATION_EX[50]
EndStructure

; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-drive_layout_information_ex
; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ne-winioctl-partition_style
#PARTITION_STYLE_MBR = 0 ;Master boot record (MBR) format.
#PARTITION_STYLE_GPT = 1 ;GUID Partition Table (GPT) format.
#PARTITION_STYLE_RAW = 2 ;Partition Not formatted in either of the recognized formats - MBR Or GPT.

Procedure.s GetPartitionStyle(Style)
  Select Style
    Case #PARTITION_STYLE_MBR
      ProcedureReturn "MBR"
    Case #PARTITION_STYLE_GPT
      ProcedureReturn "GPT"
    Case #PARTITION_STYLE_RAW
      ProcedureReturn "RAW"
  EndSelect
  
  ProcedureReturn ""
EndProcedure

Procedure.s GetGptPartitionType(*Type.GUID)
  Protected sResult.s, sGUID.s{64}
  If StringFromGUID2_(*Type, @sGUID, 63) > 0
    sGUID = RemoveString(sGUID, "{")
    sGUID = RemoveString(sGUID, "}")
    sGUID = LCase(sGUID)
    
    ; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ns-winioctl-partition_information_gpt
    Select sGUID
      Case "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
        sResult = "PARTITION BASIC DATA"
        
      Case "00000000-0000-0000-0000-000000000000"
        sResult = "PARTITION ENTRY UNUSED"
        
      Case "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
        sResult = "PARTITION SYSTEM"
        
      Case "e3c9e316-0b5c-4db8-817d-f92df00215ae"
        sResult = "PARTITION MSFT RESERVED"
        
      Case "5808c8aa-7e8f-42e0-85d2-e1e90434cfb3"
        sResult = "PARTITION LDM METADATA"
        
      Case "af9b60a0-1431-4f62-bc68-3311714a69ad"
        sResult = "PARTITION LDM DATA"
        
      Case "de94bba4-06d1-4d40-a16a-bfd50179d6ac"
        sResult = "PARTITION MSFT RECOVERY"
        
    EndSelect
  EndIf
  ProcedureReturn sResult
EndProcedure

Procedure.s GetPartitionType(type.b)
  ; Disk Partition Types
  ; https://learn.microsoft.com/en-us/windows/win32/fileio/disk-partition-types
  
  Select type
    Case 0
      ProcedureReturn "Unused"
    Case 1
      ProcedureReturn "12-bit FAT"
    Case 2, 3
      ProcedureReturn "Xenix"
    Case 4
      ProcedureReturn "16-bit FAT"
    Case 5
      ProcedureReturn "Extended"
    Case 6
      ProcedureReturn "Huge partition MS-DOS V4"
    Case 7
      ProcedureReturn "Installable File System (NTFS/HPFS/FAT64)"
    Case 8
      ProcedureReturn "OS/2 (v1.0-1.3 only)/AIX boot partition/Commodore DOS/SplitDrive/DELL partition spanning multiple drives/QNX 1.x and 2.x (qny)"
    Case 9
      ProcedureReturn "AIX data partition/Coherent filesystem/QNX 1.x and 2.x (qnz)"
    Case $A
      ProcedureReturn "OS/2 Boot Manager/OPUS/Coherent swap"
    Case $B
      ProcedureReturn "FAT32"
    Case $C
      ProcedureReturn "FAT32 using extended int13 services"
    Case $E
      ProcedureReturn "Win95 partition using extended int13 services"
    Case $F
      ProcedureReturn "Extended using extended int13 services"
    Case $41
      ProcedureReturn "PowerPC Reference Platform (PReP) Boot Partition"
    Case $42
      ProcedureReturn "Logical Disk Manager partition"
    Case $63
      ProcedureReturn "Unix"
    Case $C0
      ProcedureReturn "NTFT uses high order bits"
    Case $80
      ProcedureReturn "NTFT"
  EndSelect
EndProcedure

Procedure.s SpaceDivider(space.q)
  Protected sGroupDemicals.s{4}
  tm.s : mt.d = space
  If mt>1000: mt / 1024:tm = " KB":EndIf
  If mt>1000: mt / 1024:tm = " MB":EndIf
  If mt>1000: mt / 1024:tm = " GB":EndIf
  If mt>1000: mt / 1024:tm = " TB":EndIf
  If GetLocaleInfo_(#LOCALE_USER_DEFAULT, #LOCALE_SDECIMAL, @sGroupDemicals, 4) > 0
    ProcedureReturn ReplaceString(StrD(mt,3), ".", sGroupDemicals) + tm
  EndIf
  ProcedureReturn StrD(mt,3) + tm
EndProcedure

; IOCTL_DISK_GET_PARTITION_INFO_EX IOCTL (winioctl.h)
; https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-ioctl_disk_get_partition_info_ex

; The disk support can be summarized as follows. Currently, GPT is supported only on 64-bit systems.

; Disk type                         IOCTL_DISK_GET_PARTITION_INFO   IOCTL_DISK_GET_PARTITION_INFO_EX
; Basic master boot record (MBR)    Yes                             Yes
; Basic GUID partition table (GPT)  No                              Yes
; Dynamic MBR boot/system           Yes                             Yes
; Dynamic MBR data                  Yes                             No
; Dynamic GPT boot/system           No                              Yes
; Dynamic GPT data                  No                              No

Macro CTL_CODE( DeviceType, Function, Method, Access )
  (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
EndMacro

#FILE_DEVICE_DISK = 7
#IOCTL_DISK_BASE = #FILE_DEVICE_DISK
#METHOD_BUFFERED = 0
#FILE_ANY_ACCESS = 0
#IOCTL_DISK_GET_PARTITION_INFO_EX = CTL_CODE(#IOCTL_DISK_BASE, $12, #METHOD_BUFFERED, #FILE_ANY_ACCESS)
#IOCTL_DISK_GET_DRIVE_LAYOUT_EX = CTL_CODE(#IOCTL_DISK_BASE, $14, #METHOD_BUFFERED, #FILE_ANY_ACCESS)

Structure PartData
  sDrive.s
  PartitionID.GUID
EndStructure

NewList Partition.PartData()

aa.DRIVE_LAYOUT_INFORMATION_EX
bb.PARTITION_INFORMATION_EX

mask = GetLogicalDrives_()
For HDSpace = 0 To 31
  If mask  & (1 << HDSpace )
    Drive$ = Chr(65+HDSpace)+":\"
    Result = GetDriveType_(@Drive$)
    If Result = 3
      Partition$ = "\\.\"+ Chr(65+HDSpace)+":"
      hDrive = CreateFile_(Partition$, #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
      If hDrive <> #INVALID_HANDLE_VALUE
        Result = DeviceIoControl_(hDrive,#IOCTL_DISK_GET_PARTITION_INFO_EX, #Null,0,@bb, SizeOf(PARTITION_INFORMATION_EX), @BytesRet,0)
        If Result
          If AddElement(Partition())
            Partition()\sDrive = Drive$
            
            Select bb\PartitionStyle
              Case #PARTITION_STYLE_MBR
                CopyMemory(@bb\Mbr\PartitionId, @Partition()\PartitionID, SizeOf(GUID))
                
              Case #PARTITION_STYLE_GPT
                CopyMemory(@bb\Gpt\PartitionId, @Partition()\PartitionID, SizeOf(GUID))
                
              Case #PARTITION_STYLE_RAW
                Debug Drive$ + " = RAW"
            EndSelect
          EndIf
        EndIf
        CloseHandle_(hDrive)
      EndIf
    EndIf
  EndIf
Next

For ii=0 To 49
  hdh = CreateFile_("\\.\PhysicalDrive" + Str(ii), #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
  If hdh <> #INVALID_HANDLE_VALUE
    Result = DeviceIoControl_(hdh, #IOCTL_DISK_GET_DRIVE_LAYOUT_EX, #Null,0,@aa, SizeOf(DRIVE_LAYOUT_INFORMATION_EX), @BytesRet,0)   
    If Result
      Debug "PhysicalDrive " + ii +  " , PartitionCount: " + aa\PartitionCount
      
      For i=0 To aa\PartitionCount-1 
        If aa\PartitionEntry[i]\PartitionNumber > 0 And aa\PartitionEntry[i]\StartingOffset > 0
          Debug "  Partition # " + Str(aa\PartitionEntry[i]\PartitionNumber) + "   "+GetPartitionStyle(aa\PartitionEntry[i]\PartitionStyle) + " , length  =  " + Str(aa\PartitionEntry[i]\PartitionLength) + " bytes (" + SpaceDivider(aa\PartitionEntry[i]\PartitionLength) + ")"
          
          Select aa\PartitionEntry[i]\PartitionStyle
            Case #PARTITION_STYLE_MBR
              ForEach Partition()
                If CompareMemory(@Partition()\PartitionID, @aa\PartitionEntry[i]\Mbr\PartitionId, SizeOf(GUID))
                  Debug "Drive = " + Partition()\sDrive
                  Break
                EndIf
              Next
              Debug "Type = " + GetPartitionType(aa\PartitionEntry[i]\Mbr\PartitionType)
              Debug "Hidden Sectors = " + Str(aa\PartitionEntry[i]\Mbr\HiddenSectors)
              Debug "Boot Indicator = " + Str(aa\PartitionEntry[i]\Mbr\BootIndicator)
              Debug "Recognized Partition = " + Str(aa\PartitionEntry[i]\Mbr\RecognizedPartition)
              
            Case #PARTITION_STYLE_GPT
              ForEach Partition()
                If CompareMemory(@Partition()\PartitionID, @aa\PartitionEntry[i]\Gpt\PartitionId, SizeOf(GUID))
                  Debug "Drive = " + Partition()\sDrive
                  Break
                EndIf
              Next
              Debug "Type = " + GetGptPartitionType(@aa\PartitionEntry[i]\Gpt\PartitionType)
              
            Case #PARTITION_STYLE_RAW
              Debug "Type = RAW"
              
          EndSelect
          
          Debug "Starting Offset = " + Str(aa\PartitionEntry[i]\StartingOffset)
          Debug "Partition Length = " + Str(aa\PartitionEntry[i]\PartitionLength)
          Debug "Partition Number = " + Str(aa\PartitionEntry[i]\PartitionNumber)
          Debug "Rewrite Partition = " + Str(aa\PartitionEntry[i]\RewritePartition)
          
          Debug "================"
        EndIf
      Next
      Debug ""
    EndIf
    
    CloseHandle_(hdh)
  EndIf
Next

Olli
Addict
Addict
Posts: 1071
Joined: Wed May 27, 2020 12:26 pm

Re: Get partition letter?

Post by Olli »

@HDT

Subject title = << Get partition letter >>
How would you fix it ?

--> Would you adapt the partitions quantity ?
or
--> Would you add the non-treated partitions ?
breeze4me
Enthusiast
Enthusiast
Posts: 500
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: Get partition letter?

Post by breeze4me »

@hoangdiemtinh
The API partition count value( aa\PartitionCount ) seems to be inaccurate. Therefore, it may be better to manually count the number of valid partitions from the result.

Another way to obtain partition information may be to use WMI COM, as shown below.
However, if the partition informations are also inaccurate in the code below, it can't be helped.

Referred to:
WMI Lib

Code: Select all

; Author : DataMiner and many other
; Tweaked by Droopy for Library purpose
; PureBasic 3.93
; 14/06/05
; reworked by DataMiner 28/07/05
;
;- KONSTANTEN  PROZEDUREN  STRUKTUREN
#VT_EMPTY = 0
#VT_NULL = 1
#VT_I2 = 2
#VT_I4 = 3
#VT_R4 = 4
#VT_R8 = 5
#VT_CY = 6
#VT_DATE = 7
#VT_BSTR = 8
#VT_DISPATCH = 9
#VT_ERROR = 10
#VT_BOOL = 11
#VT_VARIANT = 12
#VT_UNKNOWN = 13
#VT_DECIMAL = 14
#VT_I1 = 16
#VT_UI1 = 17
#VT_UI2 = 18
#VT_UI4 = 19
#VT_I8 = 20
#VT_UI8 = 21
#VT_INT = 22
#VT_UINT = 23
#VT_VOID = 24
#VT_HRESULT = 25
#VT_PTR = 26
#VT_SAFEARRAY = 27
#VT_CARRAY = 28
#VT_USERDEFINED = 29
#VT_LPSTR = 30
#VT_LPWSTR = 31
#VT_RECORD = 36
#VT_INT_PTR = 37
#VT_UINT_PTR = 38
#VT_FILETIME = 64
#VT_BLOB = 65
#VT_STREAM = 66
#VT_STORAGE = 67
#VT_STREAMED_OBJECT = 68
#VT_STORED_OBJECT = 69
#VT_BLOB_OBJECT = 70
#VT_CF = 71
#VT_CLSID = 72
#VT_VERSIONED_STREAM = 73
#VT_BSTR_BLOB = $FFF
#VT_VECTOR = $1000
#VT_ARRAY = $2000
#VT_BYREF = $4000
#VT_RESERVED = $8000
#VT_ILLEGAL = $FFFF
#VT_ILLEGALMASKED = $FFF
#VT_TYPEMASK = $FFF
#COINIT_MULTITHREAD = 0
#RPC_C_AUTHN_LEVEL_CONNECT = 2
#RPC_C_IMP_LEVEL_IDENTIFY = 2
#EOAC_NONE = 0
#RPC_C_AUTHN_WINNT = 10
#RPC_C_AUTHZ_NONE = 0
#RPC_C_AUTHN_LEVEL_CALL = 3
#RPC_C_IMP_LEVEL_IMPERSONATE = 3
#CLSCTX_INPROC_SERVER = 1
#wbemFlagReturnImmediately = 16
#wbemFlagForwardOnly = 32
#IFlags = #wbemFlagReturnImmediately + #wbemFlagForwardOnly
;#WBEM_INFINITE = $FFFFFFFF
;#VARIANT_TRUE = $FFFF
#VARIANT_FALSE = $0000
#WMISeparator = ","

ProcedureDLL.s WMI(WMICommand.s)
  ;- WMI Initialize
  CoInitializeEx_(0,#COINIT_MULTITHREAD)
  hres=CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT,#RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0)
  If hres <> 0: MessageRequester("ERROR", "unable to call CoInitializeSecurity", #MB_OK): Goto cleanup: EndIf
  hres=CoCreateInstance_(?CLSID_WbemLocator,0,#CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc.IWbemLocator)
  If hres <> 0: MessageRequester("ERROR", "unable to call CoCreateInstance", #MB_OK): Goto cleanup: EndIf
  hres=loc\ConnectServer(@"root\cimv2",0,0,0,0,0,0,@svc.IWbemServices)
  If hres <> 0: MessageRequester("ERROR", "unable to call IWbemLocator::ConnectServer", #MB_OK): Goto cleanup: EndIf
  hres=svc\queryinterface(?IID_IUnknown,@pUnk.IUnknown)
  hres=CoSetProxyBlanket_(svc,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
  If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf
  hres=CoSetProxyBlanket_(pUnk,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
  If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf
  pUnk\release()
  
  
  ;- CallData
  k=CountString(WMICommand,#WMISeparator)
  Dim wmitxt$(k)
  For i=0 To k
    wmitxt$(i) = Trim(StringField(WMICommand,i+1,#WMISeparator))
  Next
  
  hres=svc\ExecQuery(@"WQL",@wmitxt$(0), #IFlags,0,@pEnumerator.IEnumWbemClassObject)
  If hres <> 0: MessageRequester("ERROR", "unable to call IWbemServices::ExecQuery", #MB_OK): Goto cleanup: EndIf
  hres=pEnumerator\reset()
  Repeat
    hres=pEnumerator\Next(#WBEM_INFINITE, 1, @pclsObj.IWbemClassObject, @uReturn)
    For i=1 To k
      hres=pclsObj\get(@wmitxt$(i), 0, @x.Variant, 0, 0)
      
      If hres = #S_OK
        type=x\vt
        
        Select type
            
          Case #VT_ARRAY | #VT_BSTR
            val.s=""
            nDim=SafeArrayGetDim_(x\lVal)
            SafeArrayGetUBound_(x\lVal, nDim, @plUbound)
            ;Dim rgVar(plUbound)
            For z=0 To plUbound
              SafeArrayGetElement_(x\lVal, @z, @rgVar)
              val.s=val.s+", "+PeekS(rgVar)
            Next
            val.s=Mid(val.s, 3, Len(val.s))
            
          Case #VT_ARRAY | #VT_I4
            val.s=""
            nDim=SafeArrayGetDim_(x\scode)
            SafeArrayGetUBound_(x\scode, nDim, @plUbound)
            ;Dim rgVar(plUbound)
            For z=0 To plUbound
              SafeArrayGetElement_(x\scode, @z, @rgVar)
              val.s=val.s + ", " +  Str(rgVar)
            Next
            val.s=Mid(val.s, 3, Len(val.s))
            
          Case #VT_BOOL
            If x\boolVal=0
              val.s="FALSE"
            ElseIf x\boolVal=-1
              val.s="TRUE"
            EndIf
            
          Case #VT_BSTR
            val.s=PeekS(x\bstrVal)
            
            
          Case #VT_NULL
            val.s="n/a"
            
          Default       ;Case #VT_I4, #VT_I2, #VT_UI4, #VT_UI2, ......
            val.s=Str(x\lVal)
            ;val.s=""
            
        EndSelect
        If uReturn <> 0: wmi$=wmi$+wmitxt$(i)+" = "+val+ #CR$: EndIf
      EndIf
    Next
    
    wmi$ + #CR$
    
  Until uReturn = 0
  
  ;- Cleanup
  cleanup:
  svc\release()
  loc\release()
  pEnumerator\release()
  pclsObj\release()
  CoUninitialize_()
  
  ProcedureReturn wmi$
EndProcedure

;- Data
DataSection
  CLSID_IEnumWbemClassObject:
  ;1B1CAD8C-2DAB-11D2-B604-00104B703EFD
  Data.l $1B1CAD8C
  Data.w $2DAB, $11D2
  Data.b $B6, $04, $00, $10, $4B, $70, $3E, $FD
  IID_IEnumWbemClassObject:
  ;7C857801-7381-11CF-884D-00AA004B2E24
  Data.l $7C857801
  Data.w $7381, $11CF
  Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
  CLSID_WbemLocator:
  ;4590f811-1d3a-11d0-891f-00aa004b2e24
  Data.l $4590F811
  Data.w $1D3A, $11D0
  Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24
  IID_IWbemLocator:
  ;dc12a687-737f-11cf-884d-00aa004b2e24
  Data.l $DC12A687
  Data.w $737F, $11CF
  Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
  IID_IUnknown:
  ;00000000-0000-0000-C000-000000000046
  Data.l $00000000
  Data.w $0000, $0000
  Data.b $C0, $00, $00, $00, $00, $00, $00, $46
  
EndDataSection


; https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-diskpartition
Debug #CR$ + WMI("SELECT * FROM Win32_DiskPartition, Availability, StatusInfo, Access, BlockSize, Bootable, BootPartition, Caption, CreationClassName, Description, DeviceID, DiskIndex, HiddenSectors, Index, Name, NumberOfBlocks, PNPDeviceID, PrimaryPartition, Purpose, RewritePartition, Size, StartingOffset, Status, SystemCreationClassName, Type")

User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Get partition letter?

Post by Mijikai »

Just want to add this (same as TI-994A example but with error checking):

Code: Select all

EnableExplicit

Procedure.i GetDrives()
  Protected siz.i
  Protected str.s
  Protected index.i
  siz = GetLogicalDriveStrings_(#Null,#Null);<- how big should the buffer be?
  str = Space(siz)
  If str <> #Null$;<- check allocation!
    If GetLogicalDriveStrings_(siz,@str) = siz - 1;<- check if all bytes where copied!
      siz = (siz >> 2) - 1;<- how many drives?
      For index = 0 To siz
        Debug PeekS(@str + index << 3);<- read out the drive strings!
      Next      
    EndIf
  EndIf
EndProcedure

GetDrives()

End

hoangdiemtinh
User
User
Posts: 29
Joined: Wed Nov 16, 2022 1:51 pm

Re: Get partition letter?

Post by hoangdiemtinh »

@breeze4me

I need it working on WinPE.
In WinPE, WMI not work.
AZJIO
Addict
Addict
Posts: 1298
Joined: Sun May 14, 2017 1:48 am

Re: Get partition letter?

Post by AZJIO »

Post Reply