Results 1 to 3 of 3

Thread: [RESOLVED] SetFilePointer with large files/drives (vb6)

  1. #1

    Thread Starter
    Addicted Member pcuser's Avatar
    Join Date
    Jun 2008
    Posts
    219

    Resolved [RESOLVED] SetFilePointer with large files/drives (vb6)

    I'm trying to read a physical hard drive but SetFilePointer throws an overflow error trying to read past 2GB using this code:

    Code:
    Option Explicit
    
    Private Const GENERIC_READ = &H80000000
    Private Const GENERIC_WRITE = &H40000000
    Private Const FILE_SHARE_READ = &H1
    Private Const FILE_SHARE_WRITE = &H2
    Private Const OPEN_EXISTING = 3
    Private Const INVALID_HANDLE_VALUE = -1&
    
    Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) 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 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 CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    
    Private Const FILE_BEGIN = 0
    Private Const FILE_CURRENT = 1
    
    Private BytesPerSector As Integer
    
    
    Public Function Direct_Read_Drive(ByVal sDrive As String, ByVal iStartSec As Long, ByVal iOffset As Long, ByVal cBytes As Long) As Variant
        Dim hDevice As Long
        Dim abBuff() As Byte
        Dim abResult() As Byte
        Dim nSectors As Long
        Dim nRead As Long
        BytesPerSector = 512
        nSectors = Int((iOffset + cBytes - 1) / BytesPerSector) + 1
        hDevice = CreateFile(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0&, 0&)
        If hDevice = INVALID_HANDLE_VALUE Then Exit Function
        Call SetFilePointer(hDevice, iStartSec * BytesPerSector, 0, FILE_BEGIN)
        ReDim abResult(cBytes - 1)
        ReDim abBuff(nSectors * BytesPerSector - 1)
        Call ReadFile(hDevice, abBuff(0), UBound(abBuff) + 1, nRead, 0&)
        CloseHandle hDevice
        CopyMemory abResult(0), abBuff(iOffset), cBytes
        Direct_Read_Drive = abResult(0)
        If Direct_Read_Drive = 0 Then Direct_Read_Drive = "00"
    End Function
    Code:
    Private Sub Form_Load()
        Dim retVal As Long
        retVal = Direct_Read_Drive("\\.\PhysicalDrive0", 0, 0, 1)
        MsgBox retVal
    End Sub

    Any ideas how to work around this? SetFilePointer can accept FILE_CURRENT and I'm thinking about some kind of loop 2gb chunks at a time but I'm not quite sure if that would be the best/quickest way or how to even pass a huge number to it.

  2. #2

    Thread Starter
    Addicted Member pcuser's Avatar
    Join Date
    Jun 2008
    Posts
    219

    Re: SetFilePointer with large files/drives (vb6)

    I found THIS code by Joacim Andersson. I changed iStartSec in my original code from long to double and replaced the call to SetFilePointer with a call to this function:

    Code:
    Private Sub SetMyFilePointer(hDevice As Long, dblPos As Double)
        Do While dblPos > &H7FFFFFFF '= 2147483647
            Call SetFilePointer(hDevice, &H7FFFFFFF, ByVal 0&, FILE_CURRENT)
            dblPos = dblPos - &H7FFFFFFF
        Loop
        If CLng(dblPos) Then
            Call SetFilePointer(hDevice, CLng(dblPos), ByVal 0&, FILE_CURRENT)
        End If
    End Sub
    I need to do some testing and and report back...

  3. #3

    Thread Starter
    Addicted Member pcuser's Avatar
    Join Date
    Jun 2008
    Posts
    219

    Re: SetFilePointer with large files/drives (vb6)

    Well, this ended up being way too simple. Here's what I'm using:

    vb Code:
    1. Private Sub SetMyFilePointer(hDevice As Long, dblPos As Currency)
    2.     Dim tmpPos As Long, tmpPos2 As Long
    3.     Dim MyPos As Currency
    4.    
    5.     MyPos = 0
    6.     tmpPos = 2147483646
    7.    
    8.     If dblPos <= tmpPos Then
    9.         ' it's less than or equal to 2gb so no need to loop
    10.         Call SetFilePointer(hDevice, dblPos, ByVal 0&, FILE_BEGIN)
    11.     Else
    12.         Do While dblPos > MyPos
    13.             If dblPos - MyPos <= tmpPos Then
    14.                 tmpPos2 = dblPos - MyPos
    15.                 ' there's less than or equal to 2gb left so make one last call
    16.                 Call SetFilePointer(hDevice, tmpPos2, 0, FILE_CURRENT)
    17.                 Exit Sub
    18.             Else
    19.                 ' there's more than 2gb left so read another 2gb and loop
    20.                 Call SetFilePointer(hDevice, tmpPos, 0, FILE_CURRENT)
    21.                 MyPos = MyPos + tmpPos
    22.             End If
    23.         Loop
    24.     End If
    25. End Sub

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width