Jump to content
Sign in to follow this  

Disk imaging attempt

Recommended Posts


I just wanted to create a sample disk imager that will make a sector by sector copy of a physical disk to a file. The code works, but I'm wondering if there's anything obvious in the loop that affects the speed of the imaging, and can be improved? Is there for instance a rule of thumb for what to configure $block to be? Here it is;

#include <winapi.au3>
#Include <WinAPIEx.au3>
#Include <APIConstants.au3>
Global  $nBytes, $tBuffer, $hFile, $hFile0
Global $sDrivePath = '\\.\PhysicalDrive', $sDriveNumber = '2'
$begin = TimerInit()
$block = 8388608 
Global $hFile0 = _WinAPI_CreateFile("\\.\" & $sDrivePath & $sDriveNumber,2,2,2)
If $hFile0 = 0 then exit
$DiskInfo = _WinAPI_GetDriveGeometryEx($sDriveNumber)
$DiskSize = DllStructGetData($DiskInfo, "DiskSize")
$remainder = 0
$sizediff = $DiskSize/$block
$maxblocks = Ceiling($sizediff)
$maxblocks_low = Floor($sizediff)
$sizediff2 = $sizediff-$maxblocks_low
$remainder = $sizediff2 * $block
If @error Then
    ConsoleWrite("@error = " & @error & @crlf)
    ConsoleWrite("@extended = " & @extended & @crlf)
ProgressOn("AutoIt disk imaging in progress", "Opening target", "", -1, -1, 16)
$outputimage = "\\.\c:\temp\image.dd"
Global $hFile = _WinAPI_CreateFile($outputimage, 3, 6, 7)
If $hFile = 0 then
    ConsoleWrite("Error occured when creating file." & @crlf)
_WinAPI_SetFilePointerEx($hFile, $DiskSize)
_WinAPI_SetFilePointerEx($hFile, 0)
For $i = 0 To $maxblocks
    If $i = $maxblocks Then
        $block = $remainder
    $tBuffer=DllStructCreate("byte[" & $block & "]")
    $read = _WinAPI_ReadFile($hFile0, DllStructGetPtr($tBuffer), $block, $nBytes)
    If $read = 0 then
        ConsoleWrite("Error when reading at block: " & $i & @crlf)
    _WinAPI_WriteFile($hFile, DllStructGetPtr($tBuffer), $block, $nBytes)
    If @error Then ConsoleWrite("Error occured when writing to file." & @crlf)
    ProgressSet(Round((($i/$maxblocks)*100), 1),Round(($i/$maxblocks)*100, 1) & "  % finished imaging", "")
    If $i = $maxblocks Then
    _WinAPI_SetFilePointerEx($hFile, $i*$block)
    _WinAPI_SetFilePointerEx($hFile0, $i*$block)
$diff = TimerDiff($begin)
$diff = Round(($diff/1000),2)
$BytesPerSec = Round(($DiskSize/$diff),0)
$DiskSizeKB = $DiskSize/1024
$KBPerSec = Round(($DiskSizeKB/$diff),0)
$DiskSizeMB = $DiskSize/1024/1024
$MBPerSec = Round(($DiskSizeMB/$diff),1)
$MBPerMin = $MBPerSec * 60
MsgBox(0,"Finished imaging","Job took: " & $diff & " seconds" & @crlf _
& "Performed " & $MBPerMin & " MB per minute")

Share this post

Link to post
Share on other sites

Anybody want to have a quick look at the loop and see if anything can be changed to speed it up?

Share this post

Link to post
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
Sign in to follow this  


Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.