GFFileAccess/GFFileAccessmod.bas

Attribute VB_Name = "GFFileAccessmod"
Option Explicit
'(c)2001, 2004, 2006, 2008 by Louis. Functions for FAST (!) file access.
'GFFileAccess_GetDirFileSizeTotal
Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
'Get[Total/Avail]DiskSpace (source: drvspace.zip)
Private Declare Function GetDiskFreeSpace Lib "kernel32.dll" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpClusterSectorNumber As Long, lpSectorByteNumber As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long
Private Declare Function GetDiskFreeSpaceEx Lib "kernel32.dll" Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, lpFreeBytesAvailableToCaller As ULARGE_INTEGER, lpTotalNumberOfBytes As ULARGE_INTEGER, lpTotalNumberOfFreeBytes As ULARGE_INTEGER) As Long
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As AnyByVal Length As Long)
'GFFileAccess_GetDirFileSizeTotal
Private Const MAX_PATH = 260
Private Const FILE_ATTRIBUTE_DIRECTORY As Long = &H10
'GFFileAccess_GetDirFileSizeTotal
Private Type FILETIME
    dwLowDateTime As Long
    dwHighDateTime As Long
End Type
'GFFileAccess_GetDirFileSizeTotal
Private Type WIN32_FIND_DATA
    dwFileAttributes As Long
    ftCreationTime As FILETIME
    ftLastAccessTime As FILETIME
    ftLastWriteTime As FILETIME
    nFileSizeHigh As Long
    nFileSizeLow As Long
    dwReserved0 As Long
    dwReserved1 As Long
    cFileName As String * MAX_PATH
    cAlternate As String * 14
End Type
'GFFileAccess_Get[Free/Total]DiskSpace
Private Type ULARGE_INTEGER
    LowPart As Long
    HighPart As Long
End Type

Public Function GFFileAccess_GetDirFileSizeTotal(ByVal DirectoryName As StringByVal Pattern As String) As Double
    'on error resume next 'returns total file size of all files matching the passed search pattern or ‑1 for error
    Dim FindFileHandle As Long
    Dim FileSizeTotal As Double
    Dim WIN32_FIND_DATAVar As WIN32_FIND_DATA
    '
    'NOTE: this function is bloody fast, in tests it needed less that 2 seconds
    'on an Athlon 800 to get the total size of 31.461 mp3 files.
    '
    'verify
    If Dir$(DirectoryName, vbDirectory) = "" Then
        GFFileAccess_GetDirFileSizeTotal = (‑1#) 'error
        Exit Function
    End If
    If Not (Right$(DirectoryName, 1) = "\") Then DirectoryName = DirectoryName + "\"
    'begin
    FindFileHandle = FindFirstFile(DirectoryName + Pattern, WIN32_FIND_DATAVar)
    If FindFileHandle > 0& Then
ReDo:
        If Not ((WIN32_FIND_DATAVar.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY) Then 'just to make sure
            FileSizeTotal = FileSizeTotal + CDbl(WIN32_FIND_DATAVar.nFileSizeLow)
        End If
        If FindNextFile(FindFileHandle, WIN32_FIND_DATAVar) > 0& Then GoTo ReDo:
        Call FindClose(FindFileHandle)
        GFFileAccess_GetDirFileSizeTotal = FileSizeTotal 'ok
        Exit Function
    Else
        GFFileAccess_GetDirFileSizeTotal = (‑1#) 'error
        Exit Function
    End If
End Function

'NOTE: GFFileAccess_IsFileExisting() requires Attributes to be passed, DirSave() doesn't.

Public Function GFFileAccess_IsFileExisting(ByVal File As String) As Boolean
    'on error resume next 'returns True if directory contains files that match the pattern, False if not
    Dim FindFileHandle As Long
    Dim WIN32_FIND_DATAVar As WIN32_FIND_DATA
    '
    'NOTE: use this function if it must be determined if a large amount
    'of directories contain files of a special type (pattern).
    'Directory must exist and must be back‑slash terminated.
    '
    'begin
    FindFileHandle = FindFirstFile(File, WIN32_FIND_DATAVar)
    If (WIN32_FIND_DATAVar.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY Then
        GFFileAccess_IsFileExisting = GFFileAccess_GetDirFileSizeTotal(GetDirectoryName(File), GetFileName(File)) > 0& 'slower, but save as all files/sub dirs are examined
    Else
        GFFileAccess_IsFileExisting = (FindFileHandle > 0&)
    End If
    Call FindClose(FindFileHandle)
End Function

Public Function GFFileAccess_IsDirExisting(ByVal DirectoryName As String) As Boolean
    'on error resume next 'returns True if directory exists, False if not
    Dim FindFileHandle As Long
    Dim WIN32_FIND_DATAVar As WIN32_FIND_DATA
    'preset
    If Right$(DirectoryName, 1) = "\" Then DirectoryName = Left$(DirectoryName, Len(DirectoryName) ‑ 1)
    'begin
'    FindFileHandle = FindFirstFile(DirectoryName, WIN32_FIND_DATAVar) 'does not ALWAYS work (?!? :(====== )
'    If (WIN32_FIND_DATAVar.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY Then
'        GFFileAccess_IsDirExisting = True
'    Else
'        GFFileAccess_IsDirExisting = False
'    End If
'    Call FindClose(FindFileHandle)
    On Error GoTo 0
    On Error GoTo Error:
    GFFileAccess_IsDirExisting = Dir$(DirectoryName, vbDirectory) <> "" 'quick hack. Pay attention we don't include the last backslash or RmDir/Kill fails
    Exit Function
Error:
    GFFileAccess_IsDirExisting = False
    Exit Function
End Function

Public Function GFFileAccess_DirSave(ByVal PathName As StringByVal Attributes As Integer) As String
    On Error GoTo Error: 'important
    '
    'NOTE: Dir$() raises an error if PathName represents a cdrom drive
    'and the cd is not inserted (damn VB!). Use this function rather than Dir$().
    '
    GFFileAccess_DirSave = Dir$(PathName, Attributes) 'ok
    Exit Function
Error:
    GFFileAccess_DirSave = "" 'error
    Exit Function
End Function

Public Function DirSave(ByVal PathName As String, Optional ByVal Attributes As Integer = vbNormal) As String
    On Error GoTo Error: 'important
    '
    'NOTE: Dir$() raises an error if PathName represents a cdrom drive
    'and the cd is not inserted (damn VB!). Use this function rather than Dir$().
    '
    DirSave = Dir$(PathName, Attributes) 'ok
    Exit Function
Error:
    DirSave = "" 'error
    Exit Function
End Function

Public Function GetAttrSave(ByRef PathName As String) As VbFileAttribute
    On Error GoTo Error: 'important
    '
    'NOTE: GetAttr() raises an error if PathName is a cdrom drive
    'with no cd inserted. Use GetAttrSave() instead of GetAttr() if
    'PathName could be a cdrom drive.
    '
    GetAttrSave = GetAttr(PathName)
    Exit Function
Error:
    GetAttrSave = vbNormal
    Exit Function
End Function

'***DISK SPACE FUNCTIONS***
'NOTE: the following two functions are to be used to determine the free or total space available on a given drive.
'The two functions were created out of the Noname99 functions GetAvailableDiskSpace() and GetTotalDiskSpace().
'The two functions use the API functions GetDiskFreeSpace() and GetDiskFreeSpaceEx().
'The largest determinable size using GetDiskFreeSpace() is 2 GB, from Win95 OSR 2 on GetDiskFreeSpaceEx()
'can be used to retrieve sizes above 2 GB.
'Code was partially taken from http://www.vbapi.com/ref/g/getdiskfreespaceex.html (03.02.2002).

Public Function GFFileAccess_GetFreeDiskSpace(ByVal DiskName As String) As Double
    On Error GoTo Error: 'important; returns free disk space in bytes
    Dim BytesFreeToUser As ULARGE_INTEGER
    Dim BytesTotal As ULARGE_INTEGER
    Dim BytesFree As ULARGE_INTEGER
    Dim TempCurrency As Currency
    Dim Temp As Long
    'begin
    Call GetDiskFreeSpaceEx(DiskName, BytesFreeToUser, BytesTotal, BytesFree)
    Call CopyMemory(TempCurrency, BytesFreeToUser, 8) 'taken from http://www.vbapi.com/ref/g/getdiskfreespaceex.html
    GFFileAccess_GetFreeDiskSpace = CDbl(TempCurrency * 10000@)
    Exit Function
Error: 'on Win95 OSR 1
    Dim ClusterSectorNumber As Long
    Dim SectorByteNumber As Long
    Dim ClusterNumberFree As Long
    Dim ClusterNumberTotal As Long
    Call GetDiskFreeSpace(DiskName, ClusterSectorNumber, SectorByteNumber, ClusterNumberFree, ClusterNumberTotal)
    GFFileAccess_GetFreeDiskSpace = CDbl(ClusterSectorNumber) * CDbl(SectorByteNumber) * CDbl(ClusterNumberFree)
    Exit Function
End Function

Public Function GFFileAccess_GetTotalDiskSpace(ByVal DiskName As String) As Double
    On Error GoTo Error: 'important; returns total disk space in bytes
    Dim BytesFreeToUser As ULARGE_INTEGER
    Dim BytesTotal As ULARGE_INTEGER
    Dim BytesFree As ULARGE_INTEGER
    Dim TempCurrency As Currency
    Dim Temp As Long
    'begin
    Call GetDiskFreeSpaceEx(DiskName, BytesFreeToUser, BytesTotal, BytesFree)
    Call CopyMemory(TempCurrency, BytesTotal, 8) 'taken from http://www.vbapi.com/ref/g/getdiskfreespaceex.html
    GFFileAccess_GetTotalDiskSpace = CDbl(TempCurrency * 10000@)
    Exit Function
Error: 'on Win95 OSR 1
    Dim ClusterSectorNumber As Long
    Dim SectorByteNumber As Long
    Dim ClusterNumberFree As Long
    Dim ClusterNumberTotal As Long
    Call GetDiskFreeSpace(DiskName, ClusterSectorNumber, SectorByteNumber, ClusterNumberFree, ClusterNumberTotal)
    GFFileAccess_GetTotalDiskSpace = CDbl(ClusterSectorNumber) * CDbl(SectorByteNumber) * CDbl(ClusterNumberTotal)
    Exit Function
End Function

Private Function GetFileName(ByVal GetFileNameName As String) As String
    On Error Resume Next 'returns chars after last backslash or nothing
    Dim GetFileNameLoop As Integer
    GetFileName = "" 'reset
    For GetFileNameLoop = Len(GetFileNameName) To 1 Step (‑1)
        If Mid$(GetFileNameName, GetFileNameLoop, 1) = "\" Then
            GetFileName = Right$(GetFileNameName, Len(GetFileNameName) ‑ GetFileNameLoop)
            Exit For
        End If
    Next GetFileNameLoop
End Function

Private Function GetDirectoryName(ByVal GetDirectoryNameName As String) As String
    'On Error Resume Next 'returns chars from string beginning to (including) last backslash or nothing
    Dim GetDirectoryNameLoop As Integer
    GetDirectoryName = "" 'reset
    For GetDirectoryNameLoop = Len(GetDirectoryNameName) To 1 Step (‑1)
        If Mid$(GetDirectoryNameName, GetDirectoryNameLoop, 1) = "\" Then
            GetDirectoryName = Left$(GetDirectoryNameName, GetDirectoryNameLoop)
            Exit For
        End If
    Next GetDirectoryNameLoop
End Function


[END OF FILE]