Search code examples
windowsapifilevb6large-files

SEEK_FAILURE What to do if SetFilePointer fails if file is over 4.1 GB


If SetFilePointer(hFile, 0&, ByVal 0&, FILE_END) _
    = INVALID_SET_FILE_POINTER Then

This call raises the HBF_SEEK_FAILURE error ( 45603) at some point of time.

The decoded API error message is:

Seek Error 
Error 87 
Wrong parameter

I believe it fails when the file size is over 4.1 GB.

What could I do to work around this problem?

I have read here that this error is a valid response if a file is over 4 GB. So should I just ignore it?

According to a suggestion, I am now using the Ex version, but I get a Wrong DLL Calling Convention error:

Public Sub SeekEnd()
    RaiseErrorIfClosed
        
    If SetFilePointerEx(hFile, 0&, ByVal 0&, FILE_END) _
        = INVALID_SET_FILE_POINTER Then
            RaiseError HBF_SEEK_FAILURE
    End If
End Sub

Thank you!


Solution

  • The easy solution; call SetFilePointerEx instead.

    If you want to continue using SetFilePointer with large files then you should set the lpDistanceToMoveHigh parameter to a valid pointer (which may point to a value that is 0 in this specific case).

    When lpDistanceToMoveHigh is set you can check the return value like this:

    If SetFilePointer(...) = INVALID_SET_FILE_POINTER _
    AndAlso If Not Err.LastDLLError = 0
      ' Handle error
    Else
      ' Success
    End If
    

    Here is a version that uses SetFilePointerEx

    Private Declare Function SetFilePointerEx Lib "kernel32" ( _
            ByVal hFile As Long, _
            ByVal liDistanceToMove As Currency, _
            ByRef lpNewFilePointer As Currency, _
            ByVal dwMoveMethod As Long) As Boolean
    
    Public Function SeekEOF() As Currency
    '++++++ NEW
    ' Seek to a base 0 EOF and return the pointer position
    ' The returned value is the new ABSOLUTE pointer positon.
        Dim RetVal As Long
        Dim tmpPosition As Currency
        Dim returnedPosition As Currency
        RaiseErrorIfClosed
        tmpPosition = 0@
        RetVal = SetFilePointerEx(hFile, (tmpPosition), returnedPosition, FILE_END) ' seek relative to the END of the file. thius returns a pointer to the final byte ?
        If RetVal = 0 Then  ' failed
            RaiseError HBFH_SEEK_FAILURE
        End If
        fCurrentPointerPosition = (returnedPosition) * 10000@
        If fCurrentPointerPosition <> Me.fileSize() Then 'gosh, what could have happened ? BASE 0 compared to BASE 1 position should=file size (ie 1 past the last byte!)
            RaiseError HBFH_SEEK_FAILURE
        End If
        SeekEOF = fCurrentPointerPosition ' returns the BASE 0 absolute pointer positon which is 1 past the last byte
    End Function