How to check the hard disc space - Clarion9
Pay attention to the data types used here Windows API help with CopyFileExA() and Callback to show Progress and here
Windows API help with CopyFileExA() and Callback to show Progress
namely, you need to create a pointer (long but Paul Attryde says use a ulong for pointers How can I access the raw stack data? MS callback proc prototype changes when asm starts popping the stack) pointing to a clarion Type’d group structure which matches this MS data type
ULARGE_INTEGER - Win32 apps | Microsoft Docs
Dword’s are ulong’s so this would apply.
UINT64 GROUP,TYPE lo ULONG hi ULONG END
And would be the group data type to point (long/ulong) to in the api.
Its worth noting in the svapi.inc SV have declared which is different to what MS have declared on their website.
_ULARGE_INTEGER group,type LowPart long HighPart long end
They also have an equate in WinEqu.clw defined as
Which would be wrong, unless there is some behind the scenes things going on in the runtime.
and then apply to this api.
SHGetDiskFreeSpaceExA function (shellapi.h) - Win32 apps | Microsoft Docs
map module MyPrefixForUniquenessToAvoidCompilerWarningsWith3rdPartyAddons_SHGetDiskFreeSpaceExA(CONST *cstring pNullTerminatedStringAkaCstring, long pPointerToUlarge_IntegerFreeBytes,long pPointerToUlarge_IntegerByteNumber , long pPointerToUlarge_IntegerFreeByteNumber),Bool,Raw,Pascal,Name('SHGetDiskFreeSpaceExA') !Which is also the same as Prefix_SHGetDiskFreeSpaceExA(long,long,long,long),bool,Pascal,Name(SHGetDiskFreeSpaceExA') End End
The next challenge is getting the value out of the group data type UINT64 in order to display.
Because I dont know what data conversion is taking place in the runtime, you could try a Real Over the group structure as shown
also mentioned here complete with calculations needed to be performed. Hint: Decimal is easiest and scalable.
I should add, you’ll know when you have the right calculations because they will match what you see in file explorer or dos.
I use GetDiskFreeSpaceExA from Kernel32, the calculation is quite easy.
myINT64 Group lo ULONG hi ULONG . szDirectory CSTRING(32) u64_FreeBytesAvailableToCaller LIKE(myINT64) u64_TotalNumberOfBytes LIKE(myINT64) u64_TotalNumberOfFreeBytes LIKE(myINT64) freeBytes DECIMAL(31) Code !-- Set szDirectory to the drive required .. szDirectory = 'C:\' if GetDiskFreeSpaceExA(Address(szDirectory),Address(u64_FreeBytesAvailableToCaller),Address(u64_TotalNumberOfBytes),Address(u64_TotalNumberOfFreeBytes)) = TRUE freeBytes = (u64_FreeBytesAvailableToCaller.Hi * 4294967295) + u64_FreeBytesAvailableToCaller.Lo .
To save looking up the 32 bit max:
.Hi * 0FFFFFFFFh )
Clarion has a base type of LONG so I would worry that may end up as -1. I usually declare a variable:
Here’s a quick conversion on prototype, untested:
BOOL GetDiskFreeSpaceExA( [in, optional] LPCSTR lpDirectoryName, [out, optional] PULARGE_INTEGER lpFreeBytesAvailableToCaller, [out, optional] PULARGE_INTEGER lpTotalNumberOfBytes, [out, optional] PULARGE_INTEGER lpTotalNumberOfFreeBytes ); GetDiskFreeSpaceEx PROCEDURE( | !BOOL GetDiskFreeSpaceExA( <*CSTRING lpDirectoryName> , | !in optional LPCSTR lpDirectoryName LONG lpFreeBytesAvailableToCaller=0 , | !out optional PULARGE_INTEGER lpFreeBytesAvailableToCaller LONG lpTotalNumberOfBytes=0 , | !out optional PULARGE_INTEGER lpTotalNumberOfBytes LONG lpTotalNumberOfFreeBytes=0 | !out optional PULARGE_INTEGER lpTotalNumberOfFreeBytes ),BOOL,PROC,RAW,PASCAL,DLL(1),name('GetDiskFreeSpaceExA')
<omittable> on LONG, add =0 default value. It was wrong, thanks @FedericoNavarro.
Probably best to use a named Group,Type for the UInt64 prototyped
<*UInt64 > so no needed for the Address() in code.
To set hi offset it needs to be multiplied by 2^n not 2^n-1
freeBytes = (u64_FreeBytesAvailableToCaller.Hi * 4294967296) + u64_FreeBytesAvailableToCaller.Lo freeBytes = (u64_FreeBytesAvailableToCaller.Hi * 2^32) + u64_FreeBytesAvailableToCaller.Lo
or this function which should be optimized
needs on the MAP
I think those should be either LONG lpEtc = 0 without angles <> , or as pointer to structures <*UINT64 lpEtc> because for OMITTED() support Clarion tends to add information about the omission or presence of the parameter, even indicating other calling conventions.
I’ve always coded API prototypes using < omitted > and it worked to pass NULL without any problems or extra flag.
The help says PASCAL is exactly correct for Windows API calls so it should handle <> correctly. Using Default=0 would work well for the LONGs but a pain for the <*CSTRING Dir>. Optional (omittable) parameters are so common in API calls it must to work.
BTW if the Directory Parameter is omitted then the Current Path() is used, which seems useful.
<* > pointer based parameters have no problem, as Clarion assumes the absense of a parameter can be represented with a 0 pointer, but with simple value parameters, extra data is needed to support OMITTED.
Here there is an example app based on both prototypes. With <> on simple value parameters it crashes, with = 0 it works.
Also there is an screen capture of Clarion Debugger where it can be seen the extra PUSH 1’s to the stack when using <>TestOmitParam.clw (1,4 KB)