News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

how to obtain drive size?

Started by bsdsource, November 05, 2012, 01:01:49 PM

Previous topic - Next topic

bsdsource

I'm using the test code below to obtain drive information to calculate the drive size. Is my code obtaining accurate information? If the information being obtained is accurate, how would I calculate drive size? I also read somewhere that IOCTL_DISK_GET_DRIVE_GEOMETRY has a 2gb limitation and IOCTL_DISK_GET_DRIVE_GEOMETRY_EX should be used instead. Also the IOCTL_DISK_GET_DRIVE_GEOMETRY_EX structure I defined has a nested structure and also I read on MSDN that the struture is also variable in size. I'm not sure if I handled it correctly.

.586
.model flat, stdcall
option casemap :none
   
     include          /masm32/include/windows.inc
     include          /masm32/include/kernel32.inc
     include          /masm32/include/user32.inc
     include          /masm32/include/masm32.inc
     include          /masm32/include/Setupapi.inc
     include          /masm32/include/debug.inc

     includelib       /masm32/lib/kernel32.lib
     includelib       /masm32/lib/user32.lib
     includelib       /masm32/lib/masm32.lib
     includelib       /masm32/lib/Setupapi.lib
     includelib       /masm32/lib/debug.lib

     WinMain           PROTO :DWORD,:DWORD,:DWORD,:DWORD

     DISK_GEOMETRY struct
         Cylinders          dd ?
         MediaType          dd ?
         TracksPerCylinder  dd ?
         SectorsPerTrack    dd ?
         BytesPerSector     dd ?
     DISK_GEOMETRY ends

     DISK_GEOMETRY_EX struct
         Geometry           DISK_GEOMETRY <>
         DiskSize           dd ?
         Data               db 8 dup (?)
     DISK_GEOMETRY_EX ends

.const
     IOCTL_DISK_GET_DRIVE_GEOMETRY    = 70000h
     IOCTL_DISK_GET_DRIVE_GEOMETRY_EX = 700a0h
     GUID_DEVINTERFACE_DISK           TEXTEQU <{053f56307h,0b6bfh,011d0h,{094h,0f2h,000h,0a0h,0c9h,01eh,0fbh,08bh}}>
     DISK_GUID                        GUID    GUID_DEVINTERFACE_DISK

.data
     DrivePath   db "\\.\c:",0

.data?
     hDrive      HANDLE ?
     returnSize  dd ?
     dg          DISK_GEOMETRY_EX <<?>,?>

.code
  start:
     invoke RtlZeroMemory,addr dg,sizeof dg
     invoke CreateFile,addr DrivePath,0,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0
     mov hDrive,eax

     invoke DeviceIoControl,hDrive,IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,0,0,addr dg,sizeof DISK_GEOMETRY_EX,addr returnSize,0
     .if eax == 0
      invoke GetLastError
      PrintHex eax
     .endif
 
  PrintDec dg.DiskSize
  PrintDec dg.Geometry.Cylinders
  PrintDec dg.Geometry.TracksPerCylinder
  PrintDec dg.Geometry.SectorsPerTrack
  PrintDec dg.Geometry.BytesPerSector

  invoke CloseHandle,hDrive
  invoke ExitProcess,0
 
  end start

japheth

Quote from: azdps on November 05, 2012, 01:01:49 PM
Is my code obtaining accurate information?

No. I'd say the structures should be


     DISK_GEOMETRY struct
         Cylinders          dq ?
         MediaType          dd ?
         TracksPerCylinder  dd ?
         SectorsPerTrack    dd ?
         BytesPerSector     dd ?
     DISK_GEOMETRY ends

     DISK_GEOMETRY_EX struct 8
         Geometry           DISK_GEOMETRY <>
         DiskSize           dq ?
         Data               db ?
     DISK_GEOMETRY_EX ends


hfheatherfox07

Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

bsdsource

I made the changes you suggested japheth.

Does PrintDec in vkdebug work with qwords? I'm obtaining a 0 value in the debug window for dg.Geometry.Cylinders.

LARGE_INTEGER also appears to be a structure. Should I use the LARGE_INTEGER structure in place of dq?

Lets suppose I changed the code to the following:
      DISK_GEOMETRY struct
         Cylinders          LARGE_INTEGER <>
         MediaType          dd ?
         TracksPerCylinder  dd ?
         SectorsPerTrack    dd ?
         BytesPerSector     dd ?
     DISK_GEOMETRY ends

     DISK_GEOMETRY_EX struct
         Geometry           DISK_GEOMETRY <>
         DiskSize           LARGE_INTEGER <>
         Data               db ?
     DISK_GEOMETRY_EX ends


How should I define the following:
dg          DISK_GEOMETRY_EX <<?>,?>

I really don't know how to deal with qwords so I'm having difficulty working with the return qword values. Hopefully I can figure this out quickly. Also thanks for that example hfheatherfox07. Actually will come in handy.

hfheatherfox07

my apologies .... I have too much stuff on my PC  ::)
This is exactly what you want .386

.model flat, stdcall
option casemap :none

include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\user32.inc
include \MASM32\INCLUDE\kernel32.inc
includelib \MASM32\LIB\user32.lib
includelib \MASM32\LIB\kernel32.lib

FPUProc PROTO :QWORD,:DWORD

_DISK_EXTENT struct
  DiskNumber DWORD ?
  StartingOffset INT64 ?
  ExtentLength INT64 ?
_DISK_EXTENT ends

_VOLUME_DISK_EXTENTS struct
  NumberOfDiskExtents DWORD ?
  Extents _DISK_EXTENT <>
_VOLUME_DISK_EXTENTS ends

_DISK_GEOMETRY struct
  Cylinders INT64 ?
  MediaType DWORD ?
  TracksPerCylinder DWORD ?
  SectorsPerTrack DWORD ?
  BytesPerSector DWORD ?
_DISK_GEOMETRY ends

.data
PhysicalDrive0 db '\\.\PhysicalDrive0',0
NumberD db 'MediaType %u',13,10,'TracksPerCylinder %u',13,10,'SectorsPerTrack %u',13,10,'BytesPerSector %u',13,10,'Cylinders ',0
form db "error: %u", 0
perenos db 13,10,0
IOCTL_DISK_GET_DRIVE_GEOMETRY = 70000h

Mtype db 'Format is unknown',0
db 'A5.25" floppy, with 1.2MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 1.44MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 2.88MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 20.8MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 720KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 360KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 320KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 320KB and 1024 bytes/sector.',0
db 'A5.25" floppy, with 180KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 160KB and 512 bytes/sector.',0
db 'Removable media other than floppy.',0
db 'Fixed hard disk media.',0
db 'A3.5" floppy, with 120MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 640KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 640KB and 512 bytes/sector.',0
db 'A5.25" floppy, with 720KB and 512 bytes/sector.',0
db 'A3.5" floppy, with 1.2MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 1.23MB and 1024 bytes/sector.',0
db 'A5.25" floppy, with 1.23MB and 1024 bytes/sector.',0
db 'A3.5" floppy, with 128MB and 512 bytes/sector.',0
db 'A3.5" floppy, with 230MB and 512 bytes/sector.',0
db 'An 8" floppy, with 256KB and 128 bytes/sector.',0
db 'A3.5" floppy, with 200MB and 512 bytes/sector. (HiFD).',0
db 'A3.5" floppy, with 240MB and 512 bytes/sector. (HiFD).',0
db 'A3.5" floppy, with 32MB and 512 bytes/sector.',0
baza dw 0,18,66,114,162,210,257,305,353,402,450,498,533,556,603,650,698,746,793,842,892,939,986,1033,1088,1143,1189

.data?
cw dd ?
data1 _DISK_GEOMETRY <>
buffer db 512 dup (?)

.code
start:

invoke CreateFile,addr PhysicalDrive0,GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,0, OPEN_EXISTING,0,0
mov ebx, eax
invoke DeviceIoControl, ebx, IOCTL_DISK_GET_DRIVE_GEOMETRY,0,0,addr data1,sizeof data1, addr cw, 0
.if eax!=0
invoke wsprintf,ADDR buffer,addr NumberD, data1.MediaType, data1.TracksPerCylinder, data1.SectorsPerTrack, data1.BytesPerSector
invoke FPUProc, data1.Cylinders, addr buffer
invoke lstrcat, addr buffer, addr perenos
lea esi, baza
add esi, data1.MediaType
add esi, data1.MediaType
lea edi, Mtype
movzx eax, word ptr[esi]
add edi, eax
invoke lstrcat, addr buffer, edi
.else
invoke GetLastError
invoke wsprintf,ADDR buffer,addr form, eax
.endif
invoke MessageBox,0,ADDR buffer,0,MB_ICONASTERISK
invoke CloseHandle, ebx

invoke ExitProcess,0

FPUProc proc uses ebx Value:QWORD, String:DWORD
LOCAL CReg:REAL10
LOCAL FString[20]:BYTE

finit
fild qword ptr [Value];[data1.Cylinders]
fbstp CReg

lea esi,FString
add esi, 18
mov byte ptr[esi],0
lea edi,CReg
xor edx, edx
xor ebx, ebx

mov ecx, 9
next:
dec esi
dec esi
mov bl, byte ptr [edi]
shl ebx,4
add bh, 48
mov dl, bh
xor bh, bh
shr ebx, 4
add bl, 48
mov dh, bl
mov word ptr [esi], dx
inc edi
loop next

Next:
inc esi
cmp byte ptr [esi], 48
je Next

cmp byte ptr [esi], 0
jne NotZero
dec esi
NotZero:
invoke lstrcat, String, esi;addr FString
ret

FPUProc endp

end start
Your code and your skills will be assimilated. Your programming language is irrelevant.
We are the ASM Borg and you will become part of us. Compile and be assembled.

jj2007

Quote from: azdps on November 05, 2012, 04:20:38 PM
Does PrintDec in vkdebug work with qwords?

Apparently it doesn't. You may use deb instead. Full code attached, with Japheth's mods.

     deb 4, "Disk", dg.DiskSize, dg.Geometry.Cylinders, dg.Geometry.TracksPerCylinder, dg.Geometry.SectorsPerTrack, dg.Geometry.BytesPerSector

Disk
dg.DiskSize     60011642880
dg.Geometry.Cylinders   7296
dg.Geometry.TracksPerCylinder   255
dg.Geometry.SectorsPerTrack     63
dg.Geometry.BytesPerSector      512

bsdsource

Excellent info. I'm up and running again and moving past this part of my code. I would also like to thank Raymond for his fpu library which came in handy for some of the calculations that i needed done.

bomz

NtCreateFile \\??\\PhysicalDrive0 --> IOCTL_DISK_GET_DRIVE_LAYOUT --> PARTITION_INFORMATION --> PartitionNumber

NtCreateFile \\Device\\Harddisk0\\Partition[PartitionNumber]\\ --> Volume Label + Serial Number

How get volume Letter?

ragdog

http://www.masmforum.com/board/index.php?topic=13479.0

.while   byte ptr [ebx] <= "Z"
      invoke GetDriveType,ebx
      .if   eax == DRIVE_CDROM     ; Here the drivetype you want ( cdrom harddisk cardreader etc.)

      .endif
      inc byte ptr [ebx]
   .endw

bomz


red arrow show column which I already made. left 2 and 3 column and disk name. in kernel mode

bomz

IOCTL_STORAGE_GET_DEVICE_NUMBER
http://msdn.microsoft.com/ru-RU/library/windows/desktop/bb968800%28v=vs.85%29.aspx