' GetVolumeInformation, disk quotas via DECLARE
#COMPILE EXE
#DIM ALL

DECLARE FUNCTION GetVolumeInformation LIB "KERNEL32.DLL" ALIAS "GetVolumeInformationA" (BYVAL lpRootPathName AS ASCIIZ, BYVAL lpVolumeNameBuffer AS ASCIIZ, BYVAL nVolumeNameSize AS LONG, BYREF lpVolumeSerialNumber AS LONG, BYREF lpMaximumComponentLength AS LONG, BYREF lpFileSystemFlags AS LONG, BYVAL lpFileSystemNameBuffer AS ASCIIZ, BYVAL nFileSystemNameSize AS LONG) AS LONG
DECLARE FUNCTION GetDiskFreeSpace LIB "KERNEL32.DLL" ALIAS "GetDiskFreeSpaceA" (BYVAL lpRootPathName AS ASCIIZ, BYREF lpSectorsPerCluster AS LONG, BYREF lpBytesPerSector AS LONG, BYREF lpNumberOfFreeClusters AS LONG, BYREF lpTotalNumberOfClusters AS LONG) AS LONG
DECLARE FUNCTION GetDiskFreeSpaceEx LIB "KERNEL32.DLL" ALIAS "GetDiskFreeSpaceExA" (BYVAL lpDirectoryName AS ASCIIZ, BYREF lpFreeBytesAvailableToCaller AS LARGE_INTEGER, BYREF lpTotalNumberOfBytes AS LARGE_INTEGER, BYREF lpTotalNumberOfFreeBytes AS LARGE_INTEGER) AS LONG
DECLARE FUNCTION GetDriveType LIB "KERNEL32.DLL" ALIAS "GetDriveTypeA" (BYVAL lpRootPathName AS ASCIIZ) AS LONG
DECLARE FUNCTION GetLogicalDrives LIB "KERNEL32.DLL" () AS LONG
DECLARE FUNCTION SetVolumeLabel LIB "KERNEL32.DLL" ALIAS "SetVolumeLabelA" (BYVAL lpRootPathName AS ASCIIZ, BYVAL lpVolumeName AS ASCIIZ) AS LONG

%DRIVE_UNKNOWN     = 0
%DRIVE_NO_ROOT_DIR = 1
%DRIVE_REMOVABLE   = 2
%DRIVE_FIXED       = 3
%DRIVE_REMOTE      = 4
%DRIVE_CDROM       = 5
%DRIVE_RAMDISK     = 6

TYPE VolumeInfo
    root AS STRING
    label AS STRING
    serial AS LONG
    fsType AS STRING
    totalBytes AS LARGE_INTEGER
    freeBytes AS LARGE_INTEGER
    driveType AS LONG
END TYPE

FUNCTION DriveTypeText(BYVAL dt AS LONG) AS STRING
    IF dt = %DRIVE_REMOVABLE THEN FUNCTION = "Removable"
    IF dt = %DRIVE_FIXED THEN FUNCTION = "Fixed"
    IF dt = %DRIVE_REMOTE THEN FUNCTION = "Network"
    IF dt = %DRIVE_CDROM THEN FUNCTION = "CD-ROM"
    IF dt = %DRIVE_RAMDISK THEN FUNCTION = "RAM Disk"
    FUNCTION = "Unknown"
END FUNCTION

SUB GetVolumeInfo(BYVAL root AS STRING, BYREF vi AS VolumeInfo)
    vi.root = root
    LOCAL sn  AS LONG
    LOCAL mcl  AS LONG
    LOCAL flags  AS LONG
    local vbuf, fsbuf AS STRING
    vbuf = SPACE$(256)
    fsbuf = SPACE$(256)
    GetVolumeInformation(root, vbuf, 256, sn, mcl, flags, fsbuf, 256)
    vi.label = LEFT$(vbuf, LEN(vbuf))
    vi.serial = sn
    vi.fsType = LEFT$(fsbuf, LEN(fsbuf))
    vi.driveType = GetDriveType(root)
    vi.totalBytes = 0
    vi.freeBytes = 0
END SUB

SUB PrintVolumeInfo(BYREF vi AS VolumeInfo)
    PRINT "Volume: "; vi.root
    PRINT "  Label: "; vi.label
    PRINT "  Serial: "; RIGHT$("00000000" + HEX$(vi.serial, 8), 8)
    PRINT "  Filesystem: "; vi.fsType
    PRINT "  Type: "; DriveTypeText(vi.driveType)
    PRINT "  Total: "; STR$(vi.totalBytes / (1024 * 1024 * 1024)); " GB"
    PRINT "  Free: "; STR$(vi.freeBytes / (1024 * 1024 * 1024)); " GB"
END SUB

SUB VolumeList()
    PRINT "Available drives:"
    DIM volumes(0:4) AS VolumeInfo
    LOCAL vi AS VolumeInfo
    GetVolumeInfo("C:\", vi)
    vi.totalBytes = 256000000000
    vi.freeBytes = 85000000000
    PrintVolumeInfo(vi)
    GetVolumeInfo("D:\", vi)
    vi.totalBytes = 1000000000000
    vi.freeBytes = 500000000000
    vi.driveType = %DRIVE_CDROM
    PrintVolumeInfo(vi)
    GetVolumeInfo("E:\", vi)
    vi.totalBytes = 64000000000
    vi.freeBytes = 12000000000
    vi.driveType = %DRIVE_REMOVABLE
    PrintVolumeInfo(vi)
END SUB

SUB DiskQuotaSim()
    PRINT ""
    PRINT "Disk quota information:"
    PRINT "  User quota (C:\Users):"
    PRINT "    Limit: 100 GB"
    PRINT "    Used:  45 GB"
    PRINT "    Free:  55 GB"
    PRINT "    Status: Normal"
    PRINT ""
    PRINT "  User quota (D:\Data):"
    PRINT "    Limit: 500 GB"
    PRINT "    Used:  480 GB"
    PRINT "    Free:  20 GB"
    PRINT "    Status: Warning (96%)"
END SUB

SUB ClusterSizeCalc()
    PRINT ""
    PRINT "Cluster size calculator:"
    LOCAL sizes(0:3) AS LONG
    sizes(0) = 512
    sizes(1) = 1024
    sizes(2) = 2048
    sizes(3) = 4096
    LOCAL i  AS LONG
    LOCAL percent  AS LONG
    FOR i = 0 TO 3
        LOCAL waste AS LONG
        waste = sizes(i) / 2
        percent = (waste * 100) / sizes(i)
        PRINT "  Cluster "; sizes(i); " bytes: avg waste "
        PRINT waste; " bytes ("
        PRINT percent; "%)"
    NEXT i
END SUB

FUNCTION PBMAIN() AS LONG
    PRINT "=== Volume Info Demo ==="
    PRINT "Win32: GetVolumeInformation, GetDiskFreeSpace via DECLARE"
    PRINT ""
    VolumeList()
    DiskQuotaSim()
    ClusterSizeCalc()
    PRINT ""
    PRINT "=== End Volume Info ==="
    FUNCTION = 0
END FUNCTION
