Jump to content

How to do Absolute Hard disk read/writes?


Recommended Posts

I want to make an x86 and x64 program to write all 0's to the entire hard disk.

I have vb6 code but this won't compile to x64 so I was thinking of using AutoIt.

Does anyone know if this is possible please? I have little experience of AutoIT.

in Vb6 I use these APIs:

Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long) As Long

Private Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long) As Long

Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long

Private Declare Function LockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToLockLow As Long, ByVal nNumberOfBytesToLockHigh As Long) As Long

Private Declare Function UnlockFile Lib "kernel32" (ByVal hFile As Long, ByVal dwFileOffsetLow As Long, ByVal dwFileOffsetHigh As Long, ByVal nNumberOfBytesToUnlockLow As Long, ByVal nNumberOfBytesToUnlockHigh As Long) As Long

Public Declare Function GetDiskFreeSpaceEx2 Lib "kernel32" Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, lpFreeBytesAvailableToCaller As Currency, lpTotalNumberOfBytes As Currency, lpTotalNumberOfFreeBytes As Currency) As Long

Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long

Private Declare Function SetFilePointerEx Lib "kernel32" (ByVal hFile As Long, ByVal liDistanceToMove As Currency, lpNewFilePointer As Currency, ByVal dwMoveMethod As Long) As Long

Any help appreciated.

Link to comment
Share on other sites

What about the Native file functions? :) something wrong with them?

Thanks for replies. I have used _WinAPI as Yashied suggested.

I also need to find the size of the physical hard disk (not the volume which may be smaller) - e.g. \\.\PhysicalDisk1

It may be quite large (up to 1TB).

I can't seem to find any _WinAPI for this???

Thanks in advance,

Steve

Link to comment
Share on other sites

Link to comment
Share on other sites

To do this, you can use DeviceIoControl(). It depends on what the size you need. If a useful amount of physical disk, it will be equal to the sum of all its logical drives. Full size of the physical disk can be obtained as follows.

#Include <WinAPI.au3>

$Drive = 0

While 1
    $Size = _WinAPI_IOCtlDiskGetLenghtInfo($Drive)
    If @error Then
        ExitLoop
    EndIf
    ConsoleWrite('Drive' & $Drive & ': ' & $Size & ' bytes' & @CR)  
    $Drive +=1
WEnd

Func _WinAPI_IOCtlDiskGetLenghtInfo($iDrive)

    Local $tGET_LENGTH_INFORMATION = DllStructCreate('int64')
    Local $hFile = _WinAPI_CreateFile('\\.\PhysicalDrive' & $iDrive, 2, 2, 2, 128)

    If $hFile = 0 Then
        Return SetError(1, 0, -1)
    EndIf

    Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', 0x0007405C, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tGET_LENGTH_INFORMATION), 'dword', DllStructGetSize($tGET_LENGTH_INFORMATION), 'dword*', 0, 'ptr', 0)

    If (@error) Or ($Ret[0] = 0) Then
        $Ret = 0
    EndIf
    _WinAPI_CloseHandle($hFile)
    If Not IsArray($Ret) Then
        Return SetError(2, 0, -1)
    EndIf
    Return SetError(0, 0, DllStructGetData($tGET_LENGTH_INFORMATION, 1))
EndFunc   ;==>_WinAPI_IOCtlDiskGetLenghtInfo

*This function will work in Windows XP and above.

EDIT:

Here is another example of using this function.

Edited by Yashied
Link to comment
Share on other sites

Cool!

Many thanks - this has saved me loads of time. I have all the vb6 code for this but have only just started on AutoIT. (I wrote my USB format program RMPrepUSB in vb6).

I am using AutoIt because I need x86 and x64 exe's which will work under WinPE v2 (VistaPE) so I have no .Net environment and vb6 only compiles to x86.

Many thanks again for your time - much appreciated.

Edited by Steve6375
Link to comment
Share on other sites

This is better.

#Include <WinAPI.au3>

Global Const $tagDISKGEOMETRYEX = 'int64 Cylinders;dword MediaType;dword TracksPerCylinder;dword SectorsPerTrack;dword BytesPerSector;int64 DiskSize;dword Data'

$Drive = 0

While 1
    $tDISKGEOMETRYEX = _WinAPI_IOCtlDiskGetDriveGeometryEx($Drive)
    If @error Then
        ExitLoop
    EndIf
    ConsoleWrite('-------------------------------' & @CR)
    ConsoleWrite('Drive: ' & $Drive & @CR)
    ConsoleWrite('Cylinders: ' & DllStructGetData($tDISKGEOMETRYEX, 'Cylinders') & @CR)
    ConsoleWrite('Tracks per Cylinder: ' & DllStructGetData($tDISKGEOMETRYEX, 'TracksPerCylinder') & @CR)
    ConsoleWrite('Sectors per Track: ' & DllStructGetData($tDISKGEOMETRYEX, 'SectorsPerTrack') & @CR)
    ConsoleWrite('Bytes per Sector: ' & DllStructGetData($tDISKGEOMETRYEX, 'BytesPerSector') & ' bytes' & @CR)
    ConsoleWrite('Total Space: ' & DllStructGetData($tDISKGEOMETRYEX, 'DiskSize') & ' bytes' & @CR)
    ConsoleWrite('-------------------------------' & @CR)
    $tDISKGEOMETRYEX = 0
    $Drive +=1
WEnd

Func _WinAPI_IOCtlDiskGetDriveGeometryEx($iDrive)

    Local $hFile = _WinAPI_CreateFile('\\.\PhysicalDrive' & $iDrive, 2, 2, 2, 128)

    If $hFile = 0 Then
        Return SetError(1, 0, 0)
    EndIf

    Local $tDISKGEOMETRYEX = DllStructCreate($tagDISKGEOMETRYEX)
    Local $Ret = DllCall('kernel32.dll', 'int', 'DeviceIoControl', 'ptr', $hFile, 'dword', 0x000700A0, 'ptr', 0, 'dword', 0, 'ptr', DllStructGetPtr($tDISKGEOMETRYEX), 'dword', DllStructGetSize($tDISKGEOMETRYEX), 'dword*', 0, 'ptr', 0)

    If (@error) Or ($Ret[0] = 0) Then
        $Ret = 0
    EndIf
    _WinAPI_CloseHandle($hFile)
    If Not IsArray($Ret) Then
        Return SetError(2, 0, 0)
    EndIf
    Return SetError(0, 0, $tDISKGEOMETRYEX)
EndFunc   ;==>_WinAPI_IOCtlDiskGetDriveGeometryEx
Link to comment
Share on other sites

  • 2 years later...

:bye: Hello, everyone!! This is my first post on AutoIt Script Forums. Using this script, I could write 0's on my I: drive and got the sector count of this drive using HxD Disk Editor Tool.

Also, I would like to point out here that Read/Write Commands work for Physical Disks only when the writing Length is a multiple of 512. Thanx to Joakim for this info.

Happy to help. :oops:

#include <WinAPI.au3>
Global $nBytes
$DRIVE = "I:"
$DRVSECCOUNT = 1981440
$tBuffer = DllStructCreate("byte[" & 2048 & "]")
DllStructSetData($tBuffer, 1, "")
$hFile = _WinAPI_CreateFile("." & $DRIVE, 2, 4)
For $i = 0 to $DRVSECCOUNT
_WinAPI_SetFilePointer($hFile, $i * 2048)
_WinAPI_WriteFile($hFile, DllStructGetPtr($tBuffer), 2048, $nBytes)
Next
_WinAPI_CloseHandle($hFile)

----------------------------------------

:bye: Hey there, was I helpful?

----------------------------------------

My Current OS: Win8 PRO (64-bit); Current AutoIt Version: v3.3.8.1

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...