DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Just starting out? Need help? Post your questions and find answers here.
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by firace »

Would anyone have an example of how to call the DeviceIoControl Windows API with FSCTL_GET_VOLUME_BITMAP?


Ref: https://docs.microsoft.com/fr-fr/window ... ume_bitmap

Thanks!

(example code in C - see my next post)
Last edited by firace on Sun Sep 18, 2022 8:55 am, edited 1 time in total.
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by Olli »

Hello, here :

Code: Select all

hDevice = CreateFile_ ("\\.\PhysicalDrive0", 0, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
I think you have to replace 0 with #Generic_Read (1 << 31).
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by firace »

Hi, I've removed the code in the OP as it is not so relevant to the topic.

More info about the cluster map (volume bitmap):
https://redcircle.blog/2008/11/26/cluster-map/
https://codeistry.wordpress.com/2015/01 ... fs-volume/

This is what I would like to write in PB:

Code: Select all

	const int bitmapSize = 65536;
	byte bitmapBuffer[bitmapSize + sizeof (VOLUME_BITMAP_BUFFER)];
	VOLUME_BITMAP_BUFFER *bitmap = (VOLUME_BITMAP_BUFFER *) bitmapBuffer;
	startLcn.q = 0;

	DWORD bytesReturned;
    DeviceIoControl (volumeHandle, FSCTL_GET_VOLUME_BITMAP, &startLcn, sizeof (startLcn), &bitmapBuffer, sizeof (bitmapBuffer), &bytesReturned, NULL)
	
My main obstacle is the VOLUME_BITMAP_BUFFER type I guess.
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by infratec »

You need 'Administrator mode' in compiler options.

Else LastError is 6 (0x6): The handle is invalid.

If LastError is 234 (0xEA): More data is available.
then the buffer is to small,

And you can not open a 'physical drive', you need to open a Volume.

In my case, this works:
(222GB Volume returns 7288861 bytes -> clustersize is 32768)

Code: Select all

EnableExplicit

#FSCTL_GET_VOLUME_BITMAP = $0009006F

Define.i hVolume, Result, LastError
Define.q startLcn, bytesReturned
Define *bitmapBuffer

hVolume = CreateFile_ ("\\.\c:", #GENERIC_READ | #GENERIC_WRITE, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
If hVolume
  
  *bitmapBuffer = AllocateMemory($800000)
  If *bitmapBuffer  
    Result = DeviceIoControl_(hVolume, #FSCTL_GET_VOLUME_BITMAP, @startLcn, SizeOf(startLcn), *bitmapBuffer, MemorySize(*bitmapBuffer), @bytesReturned, #Null)
    LastError = GetLastError_()
    If LastError
      MessageRequester("Last Error", Str(LastError) + " (" + Hex(LastError) + ") " + Str(bytesReturned))
    Else
      MessageRequester("Info", "Bytes returned: " + Str(bytesReturned))
    EndIf
    FreeMemory(*bitmapBuffer)
  EndIf
  CloseHandle_(hVolume)
EndIf	
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by firace »

Thanks a lot infratec, great answer as usual!
infratec
Always Here
Always Here
Posts: 7604
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by infratec »

A bit more extended:

Code: Select all

EnableExplicit

#IOCTL_STORAGE_READ_CAPACITY = $2D5140

#FSCTL_GET_VOLUME_BITMAP = $0009006F

Structure STORAGE_READ_CAPACITY Align #PB_Structure_AlignC
  Version.l
  Size.l
  BlockLength.l
  NumberOfBlocks.LARGE_INTEGER
  DiskLength.LARGE_INTEGER
EndStructure

Structure STARTING_VCN_INPUT_BUFFER Align #PB_Structure_AlignC
  StartingVcn.LARGE_INTEGER
EndStructure

Structure VOLUME_BITMAP_BUFFER Align #PB_Structure_AlignC
  StartingLcn.LARGE_INTEGER
  BitmapSize.LARGE_INTEGER
  Buffer.a[0]
EndStructure


Define.i hVolume, Result, LastError
Define.q startLcn, bytesReturned
Define *bitmapBuffer.VOLUME_BITMAP_BUFFER
Define StorageReadCapacity.STORAGE_READ_CAPACITY
Define Msg$


hVolume = CreateFile_ ("\\.\c:", #GENERIC_READ, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
If hVolume
  

  Result = DeviceIoControl_(hVolume, #IOCTL_STORAGE_READ_CAPACITY, #Null, 0, @StorageReadCapacity, SizeOf(STORAGE_READ_CAPACITY), @bytesReturned, #Null)
  LastError = GetLastError_()
  If LastError
    MessageRequester("Last Error", Str(LastError) + " (" + Hex(LastError) + ") " + Str(bytesReturned))
  Else
    Msg$ = "Bytes returned: " + Str(bytesReturned) + #LF$
    Msg$ + "Size: " + Str(StorageReadCapacity\Size) + #LF$
    Msg$ + "BlockLength: " + Str(StorageReadCapacity\BlockLength) + #LF$
    Msg$ + "NumberOfBlocks: " + Str(StorageReadCapacity\NumberOfBlocks\QuadPart) + #LF$
    Msg$ + "DiskLength: " + Str(StorageReadCapacity\DiskLength\QuadPart)
    MessageRequester("Info", Msg$)
  EndIf
  
  
  *bitmapBuffer = AllocateMemory(StorageReadCapacity\DiskLength\QuadPart / 4096 / 8)
  If *bitmapBuffer  
    Result = DeviceIoControl_(hVolume, #FSCTL_GET_VOLUME_BITMAP, @startLcn, SizeOf(startLcn), *bitmapBuffer, MemorySize(*bitmapBuffer), @bytesReturned, #Null)
    LastError = GetLastError_()
    If LastError
      MessageRequester("Last Error", Str(LastError) + " (" + Hex(LastError) + ") " + Str(bytesReturned))
    Else
      Msg$ = "Bytes returned: " + Str(bytesReturned) + #LF$
      Msg$ + "StartingLcn: " + Str(*bitmapBuffer\StartingLcn\QuadPart) + #LF$
      Msg$ + "BitMapSize: " + Str(*bitmapBuffer\BitmapSize\QuadPart)
      MessageRequester("Info", Msg$)
    EndIf
    FreeMemory(*bitmapBuffer)
  EndIf
  CloseHandle_(hVolume)
EndIf	
In front of the real data is the Starting LCN and the BitMap size.
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by Olli »

Very good subject, very good questions, and very good answers.

Thanks to you two, firace and infratec. I cannot test it actually, but just the name of "cluster" makes me remember the hundreds hours I spent more than twenty years ago, to format and repair freely harddisks. Imagine the start of this very strange session, as the children of my time were playing "PSX" or football outdoor : a message I discovered on a stick on a side of a harddisk in a garbage, just this << 11 megabytes Execute C800:0005 >> !

When I had only 3 floppy disks of 1.44MB, 11 megabytes was the paradise ! I did not remember if it was a seagate (ST), but I read the "cluster" word, for the first time on its stick.

It was noisy like a vacuum cleaner, took about twenty seconds to initialize in a din, and was so bulky, but I loved this first hard drive! Thank you so, just to read a so interesting subject !

Without computer, I cannot give a lot, to complete your work, certainly less than you already know :

Code: Select all

Structure bit32
   i.L[0]
EndStructure

Structure bit64
   i.q[0]
EndStructure

Procedure bit32GetBit(*this.bit32, i)
   ProcedureReturn *this\i[i >> 5] >> (i & 31) & 1
EndProcedure

Procedure bit64GetBit(*this.bit64, i)
   ProcedureReturn *this\i[i >> 6] >> (i & 63) & 1
EndProcedure

Here, is a linear bit reader (from long or from quad). But I am even not sure it is okay, depending of the endianness of the API...
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by firace »

Thanks again! Image Image
tester
User
User
Posts: 34
Joined: Sun Dec 28, 2014 1:12 pm

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by tester »

infratec wrote: Sun Sep 18, 2022 3:37 pm A bit more extended:

Code: Select all

EnableExplicit

#IOCTL_STORAGE_READ_CAPACITY = $2D5140

#FSCTL_GET_VOLUME_BITMAP = $0009006F

Structure STORAGE_READ_CAPACITY Align #PB_Structure_AlignC
  Version.l
  Size.l
  BlockLength.l
  NumberOfBlocks.LARGE_INTEGER
  DiskLength.LARGE_INTEGER
EndStructure

Structure STARTING_VCN_INPUT_BUFFER Align #PB_Structure_AlignC
  StartingVcn.LARGE_INTEGER
EndStructure

Structure VOLUME_BITMAP_BUFFER Align #PB_Structure_AlignC
  StartingLcn.LARGE_INTEGER
  BitmapSize.LARGE_INTEGER
  Buffer.a[0]
EndStructure


Define.i hVolume, Result, LastError
Define.q startLcn, bytesReturned
Define *bitmapBuffer.VOLUME_BITMAP_BUFFER
Define StorageReadCapacity.STORAGE_READ_CAPACITY
Define Msg$


hVolume = CreateFile_ ("\\.\c:", #GENERIC_READ, #FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null, #OPEN_EXISTING, 0, #Null)
If hVolume
  

  Result = DeviceIoControl_(hVolume, #IOCTL_STORAGE_READ_CAPACITY, #Null, 0, @StorageReadCapacity, SizeOf(STORAGE_READ_CAPACITY), @bytesReturned, #Null)
  LastError = GetLastError_()
  If LastError
    MessageRequester("Last Error", Str(LastError) + " (" + Hex(LastError) + ") " + Str(bytesReturned))
  Else
    Msg$ = "Bytes returned: " + Str(bytesReturned) + #LF$
    Msg$ + "Size: " + Str(StorageReadCapacity\Size) + #LF$
    Msg$ + "BlockLength: " + Str(StorageReadCapacity\BlockLength) + #LF$
    Msg$ + "NumberOfBlocks: " + Str(StorageReadCapacity\NumberOfBlocks\QuadPart) + #LF$
    Msg$ + "DiskLength: " + Str(StorageReadCapacity\DiskLength\QuadPart)
    MessageRequester("Info", Msg$)
  EndIf
  
  
  *bitmapBuffer = AllocateMemory(StorageReadCapacity\DiskLength\QuadPart / 4096 / 8)
  If *bitmapBuffer  
    Result = DeviceIoControl_(hVolume, #FSCTL_GET_VOLUME_BITMAP, @startLcn, SizeOf(startLcn), *bitmapBuffer, MemorySize(*bitmapBuffer), @bytesReturned, #Null)
    LastError = GetLastError_()
    If LastError
      MessageRequester("Last Error", Str(LastError) + " (" + Hex(LastError) + ") " + Str(bytesReturned))
    Else
      Msg$ = "Bytes returned: " + Str(bytesReturned) + #LF$
      Msg$ + "StartingLcn: " + Str(*bitmapBuffer\StartingLcn\QuadPart) + #LF$
      Msg$ + "BitMapSize: " + Str(*bitmapBuffer\BitmapSize\QuadPart)
      MessageRequester("Info", Msg$)
    EndIf
    FreeMemory(*bitmapBuffer)
  EndIf
  CloseHandle_(hVolume)
EndIf	
In front of the real data is the Starting LCN and the BitMap size.

; PB 6.0 LTS (x86) & (x64) ASM Backend
; OK

; PB 6.0 LTS (x86) & (x64) C Backend:
; Error: Negative DiskLength (and the NumberOfBlocks also not correct)
The disk length is determined correctly if I change the structure.:

Code: Select all

Structure STORAGE_READ_CAPACITY Align #PB_Structure_AlignC
  Version.l
  Size.l
  BlockLength.l
  NumberOfBlocks.q
  DiskLength.q
EndStructure
The size of the disk being checked is 1000204886016 bytes.
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by Olli »

My apologize, it was a Western Digital... 0.000011 terabytes. And it is Microsoft DBLSPACE which has killed my vacuum cleaner... I had been too greedy... It had fins like moped engines...
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: DeviceIoControl API call with FSCTL_GET_VOLUME_BITMAP

Post by Olli »

I was typing the extended version of infratec, when I stopped on front of "4096"...

On one level we have 512, and on a second level we habe 4096 : does this mean, there are two allocating table ?
Post Reply