by Michael Rüsweg-Gilbert
To get the amount of available disk space you can call GetDiskFreeSpace or GetDiskFreeSpaceEx.
GetDiskFreeSpaceEx is best because it supports disks larger than 2 gigabyte. Unfortunately this function may not be available on every Windows version (Windows 95 before OSR2 only supports GetDiskFreeSpace).
The following program shows how to call GetDiskFreeSpaceEx. Note how the 64-bit parameters are cast in MEMPTR variables and converted to decimal values.
/* ===============================================================================
Program: VolSpace.p
Created: Michael R?Gilbert Feb 2001
mailto:rg@rgilbert.de
Description: returns the capacity and free space of a volume (even if Vol > 2 GB)
Usage: for ex. run VolSpace.p ("C:",
"KB",
output freeSpace,
output totalSpace).
Parameters: - Volume to check or Blank
(Blank returns informations abaout the working drirector drive)
It does not have to be the root, accepts any directory.
- Unit to format the result; legal entries are
"KB", "MB" or "GB".
If the unit is not recognized or empty, VolSpace will return
Number of Bytes.
- OUTPUT available free space in given unit
- OUTPUT total space in given unit
When VolSpace is not successful, both output parameters will return ?.
modifications:
March 14, 2001: Jurjen - added function IsAPIFunctionSupported()
===================================================================================== */
DEFINE INPUT PARAMETER ip_drive AS CHARACTER NO-UNDO.
DEFINE INPUT PARAMETER ip_unit AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER op_free AS DECIMAL NO-UNDO.
DEFINE OUTPUT PARAMETER op_total AS DECIMAL NO-UNDO.
&SCOPED-DEFINE WTRUE 1
&SCOPED-DEFINE WFALSE 0
FUNCTION get64BitValue RETURNS DECIMAL
(INPUT m64 AS MEMPTR) FORWARD.
FUNCTION IsAPIFunctionSupported RETURNS LOGICAL
(FunctionName AS CHAR, ModuleName AS CHARACTER) FORWARD.
DEFINE VARIABLE retval AS INTEGER NO-UNDO.
DEFINE VARIABLE divident AS INTEGER NO-UNDO INIT 1.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE mem1 AS MEMPTR NO-UNDO.
DEFINE VARIABLE mem2 AS MEMPTR NO-UNDO.
DEFINE VARIABLE mem3 AS MEMPTR NO-UNDO.
/* See if GetDiskFreeSpaceEx is available in this Windows version.
(it is available in NT4, Windows 95 OSR2, Windows 98, Windows 2000) */
IF NOT IsAPIFunctionSupported("GetDiskFreeSpaceExA":U, "kernel32.dll":U) THEN DO:
MESSAGE "Sorry, your version of Windows does not support GetDiskFreeSpaceEx"
VIEW-AS ALERT-BOX.
ASSIGN op_free = ?
op_total = ?.
RETURN.
END.
IF CAN-DO("KB,Kilo,Kilobyte,Kilobytes", ip_unit)
THEN divident = 1024.
ELSE
IF CAN-DO("MB,Mega,Megabyte,Megabytes", ip_unit)
THEN divident = 1024 * 1024.
ELSE
IF CAN-DO("GB,Giga,Gigabyte,Gigabytes", ip_unit)
THEN divident = 1024 * 1024 * 1024.
ELSE divident = 1.
/* No directory specified? Then use the current directory */
IF (ip_drive = "") OR (ip_drive=?) THEN DO:
FILE-INFO:FILE-NAME = ".".
ip_drive = FILE-INFO:FULL-PATHNAME.
END.
/* If a UNC name was specified, make sure it ends with a backslash ( \\drive\share\dir\ )
This won't hurt for a mapped drive too */
IF SUBSTR(ip_drive, LENGTH(ip_drive), 1) NE "\"
THEN ip_drive = ip_drive + "\".
SET-SIZE(mem1) = 8. /* 64 bit integer! */
SET-SIZE(mem2) = 8.
SET-SIZE(mem3) = 8.
RUN GetDiskFreeSpaceExA ( ip_drive + CHR(0),
OUTPUT mem1,
OUTPUT mem2,
OUTPUT mem3,
OUTPUT retVal ).
IF retVal NE {&WTRUE} THEN DO:
op_free = ?.
op_total = ?.
END.
ELSE DO:
ASSIGN
op_free = TRUNC( get64BitValue(mem3) / divident, 3)
op_total = TRUNC( get64BitValue(mem2) / divident, 3).
END.
SET-SIZE(mem1) = 0.
SET-SIZE(mem2) = 0.
SET-SIZE(mem3) = 0.
RETURN.
PROCEDURE GetModuleHandleA EXTERNAL "kernel32.dll" :
DEFINE INPUT PARAMETER lpModuleName AS CHARACTER NO-UNDO.
DEFINE RETURN PARAMETER hModule AS LONG NO-UNDO.
END PROCEDURE.
PROCEDURE GetProcAddress EXTERNAL "kernel32.dll" :
DEFINE INPUT PARAMETER hModule AS LONG NO-UNDO.
DEFINE INPUT PARAMETER lpProcName AS CHARACTER NO-UNDO.
DEFINE RETURN PARAMETER lpFarproc AS LONG NO-UNDO.
END PROCEDURE.
PROCEDURE GetDiskFreeSpaceExA EXTERNAL "kernel32.dll" :
DEFINE INPUT PARAMETER lpDirectoryName AS CHARACTER NO-UNDO.
DEFINE OUTPUT PARAMETER FreeBytesAvailable AS MEMPTR NO-UNDO.
DEFINE OUTPUT PARAMETER TotalNumberOfBytes AS MEMPTR NO-UNDO.
DEFINE OUTPUT PARAMETER TotalNumberOfFreeBytes AS MEMPTR NO-UNDO.
DEFINE RETURN PARAMETER retval AS LONG NO-UNDO.
END PROCEDURE.
/* See if GetDiskFreeSpaceEx is available in this Windows version */
FUNCTION IsAPIFunctionSupported RETURNS LOGICAL
(FunctionName AS CHAR, ModuleName AS CHARACTER):
DEFINE VARIABLE hModule AS INTEGER NO-UNDO.
DEFINE VARIABLE lpFarProc AS INTEGER NO-UNDO.
/* you should run LoadLibraryA to load the module into memory,
but this is not necessary for ModuleName="kernel32.dll": the kernel is
always available. */
RUN GetModuleHandleA (ModuleName, OUTPUT hModule).
RUN GetProcAddress (hModule, FunctionName, OUTPUT lpFarProc).
RETURN lpFarProc NE 0.
END FUNCTION.
/* Converts a 64-bit integer given in a 8 byte mempointer into a decimal */
FUNCTION get64BitValue RETURNS DECIMAL
( INPUT m64 AS MEMPTR ):
/* constant 2^32 */
&SCOPED-DEFINE BigInt 4294967296
DEFINE VARIABLE d1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE d2 AS DECIMAL NO-UNDO.
d1 = GET-LONG(m64, 1).
IF d1 < 0
THEN d1 = d1 + {&BigInt}.
d2 = GET-LONG(m64, 5).
IF d2 < 0
THEN d2 = d2 + {&BigInt}.
IF d2 GT 0
THEN d1 = d1 + (d2 * {&BigInt}).
RETURN d1.
END FUNCTION.