Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2001-12

Win32 API Call

10 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

Sorry for what's most likely a neophytes question...

I'm trying to call the Win32 API function GetDiskFreeSpaceEx, but when I do the compiler complains and I get the following error: Incompatible type for arg no. 4: Got "pLongint", expected "PLARGEINTEGER"

The 4th argument is the same type as the 2nd and 3rd arguments, which according to the API Reference they're supposed to be.

Here's the code:

Program SI;
uses
  WINDOWS;
const
  BUF_SIZE = 255;
type
  pLongint = ^longint;
  Buffer   = array [1..BUF_SIZE] of char;
var
  BytesAvail   : pLongint;
  BytesTotal   : pLongint;
  BytesFree    : pLongint;
  CharBuffer   : ^Buffer;
BEGIN
  new (BytesAvail); new (BytesTotal);
  new (BytesFree);  new (CharBuffer);
  GetDiskFreeSpaceEx (CharBuffer,BytesAvail,BytesTotal,BytesFree);
END.

This is from the Win32 Reference:

BOOL GetDiskFreeSpaceEx
(
LPCTSTR lpDirectoryName, // pointer to directory name on disk of interest
PULARGE_INTEGER lpFreeBytesAvailableToCaller, // pointer to variable to receive free bytes on disk available to the caller PULARGE_INTEGER lpTotalNumberOfBytes, // pointer to variable to receive number of bytes on disk
PULARGE_INTEGER lpTotalNumberOfFreeBytes // pointer to variable to receive free bytes on disk

   );

Now, I'll be the first to admit that I'm no Win32 expert, but to me I did everything correct (but obviously FPC is smarter then I am :-)

Can anybody point me in the right direction? TIA...

Jim

Reply by email

Gabor DEAK JAHN
to Unknown author

At 12/7/2001 11:53 AM, you wrote:

Jim,

I'm trying to call the Win32 API function GetDiskFreeSpaceEx, but when I do the compiler complains and I get the following error: Incompatible type

for

arg no. 4: Got "pLongint", expected "PLARGEINTEGER"

Several problems and you're innocent in one of them... :-))

First, your variables are Longints which are to small (32 bit) for a LARGE_INTEGER (64 bit)--an unsigned longint could only count to 4 GB which is pretty small for a HDD today. Second, there is a typo in Redef.inc (and the libraries generated) that should be corrected by the developers: in the three lines declaring the various flavors of GetDiskFreeSpaceEx, 'lpTotalNumberOfBytes' should be followed by a comma, not a semicolon.

But in the meantime, you can call it like this (note that, although you can, you don't have to allocate your simple variables dynamically):

{$APPTYPE CONSOLE}
program SI;
uses
   Windows;
var
   BytesAvail, BytesTotal, BytesFree : int64;
begin
   GetDiskFreeSpaceEx ('G:\', BytesAvail, BytesTotal, @BytesFree);
   writeln (BytesAvail, ' free bytes for user');
   writeln (BytesTotal, ' bytes total for user');
   writeln (BytesFree, ' free bytes on disk');
end.

Bye,
Gábor

------------------------------------------------------------------- Gabor DEAK JAHN -- Budapest, Hungary.
E-mail:

Reply by email

Thomas Schatzl
to Unknown author: Sorry for what's most likely a neophytes question... I'm trying to call the Win32 API…

Hi,

Show quoted text 9 lines
Sorry for what's most likely a neophytes question... I'm trying to call the Win32 API function GetDiskFreeSpaceEx, but when I do the compiler complains and I get the following error: Incompatible type for arg no. 4: Got "pLongint", expected "PLARGEINTEGER" The 4th argument is the same type as the 2nd and 3rd arguments, which according to the API Reference they're supposed to be.

FPC seems to do argument type checking from right to left (e.g. in the order the parameters are pushed on the stack). Since the compiler is by default set up to exit after the first error you simply don't see the others. ^^

Show quoted text 9 lines
Here's the code: Program SI; uses WINDOWS; const BUF_SIZE = 255;

I think you better use the constant MAX_PATH here which should be defined in the windows unit.... (well, I think it's 255 anyway but you never know). [Didn't check the documentation, but those buffers usually ought to be MAX_PATH in size]

type pLongint = ^longint; Buffer = array [1..BUF_SIZE] of char;

I'm not sure here again, but I think 0..MAX_PATH (or BUF_SIZE) is more appropriate here...

var BytesAvail : pLongint; BytesTotal : pLongint; BytesFree : pLongint;

Use PULARGE_INTEGER here and it should work fine.

Show quoted text 8 lines
CharBuffer : ^Buffer; BEGIN new (BytesAvail); new (BytesTotal); new (BytesFree); new (CharBuffer); GetDiskFreeSpaceEx (CharBuffer,BytesAvail,BytesTotal,BytesFree); END.

Btw, I'd recommend using ULARGE_INTEGERs (64 bit integers) or the Pascal Int64 type for the three size parameters and call the function this way:

GetDiskFreeSpaceEx(CharBuffer, @BytesAvail, @BytesTotal, @BytesFree);

Although it doesn't look that good you save the new() and dispose() calls here. It's more to write too, and you often forget either one new() or dispose() calls which cause memory leaks or weird program behaviour. Otoh there might be a function declaration in the windows unit which automatically dereferences the variables using var parameters. E.g. try

GetDiskFreeSpaceEx(CharBuffer, BytesAvail, BytesTotal, BytesFree);

too.

Now, I'll be the first to admit that I'm no Win32 expert, but to me I did everything correct (but obviously FPC is smarter then I am :-) Can anybody point me in the right direction? TIA...

Hth,
Thomas

Reply by email

Unknown author

Thanks (again) Gabor for your help. And kudos to Thomas Schatzl as well. I took the suggestions both of you had and got it to work.

Several problems and you're innocent in one of them... :-))

Well, what do you know -- perhaps I'm only half as dumb as I thought... :-)

GetDiskFreeSpaceEx ('G:\', BytesAvail, BytesTotal, @BytesFree);

But is that why you're using the @ symbol for BytesFree? Somehow I get the feeling you're going to tell me no. And if you do, then how come the Win32 Reference says all the values are pularge_integer but only ones need to be referenced by it's address?

Jim

Reply by email

Gabor DEAK JAHN
to Unknown author

At 12/7/2001 03:38 PM, you wrote:

Jim,

But is that why you're using the @ symbol for BytesFree? Somehow I get the feeling you're going to tell me no. And if you do, then how come the Win32 Reference says all the values are pularge_integer but only ones need to be referenced by it's address?

That's the error I mentioned in Redef.inc. You are right and your Win32 reference is right, this is an error of the compiler. The original in Redef.inc looks like this:

function GetDiskFreeSpaceEx(lpDirectoryName: PChar; var
lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes;
lpTotalNumberOfFreeBytes: PLargeInteger): BOOL;external 'kernel32' name
'GetDiskFreeSpaceExA';

This is not equivalent to what Windows expects: the first two parameters, lpFreeBytesAvailableToCaller and lpTotalNumberOfBytes are declared as untyped var parameters (generic pointers), while the third parameter, lpTotalNumberOfFreeBytes is a pointer to a large integer. The Win32 API, in contrast to this, specifies all three parameters as pointers to large integers, hence the need to change the semicolon after lpTotalNumberOfBytes to a comma.

If this is corrected, you don't have to use the '@' operator before the third parameter any more.

Bye,
Gábor

------------------------------------------------------------------- Gabor DEAK JAHN -- Budapest, Hungary.
E-mail:

Reply by email

Gabor DEAK JAHN

At 12/7/2001 03:38 PM, you wrote:

Jim,

If this is corrected, you don't have to use the '@' operator before the third parameter any more.

Self-correction: actually, you'll have to use it for all three parameters. What I really meant to say was that you don't have to write one parameter different than the others.

The '@' is simply a result of not using dynamic variables like you did (with New and Dispose) but static ones. With dynamic variables, the reference you keep and use is the pointer to it, with static variables, the variable itself.

There are four cases in total (two kinds of variables times two roles, the variable itself and a pointer to it), thus you need two additional operators to cater for all cases: @ and ^.

Bye,
Gábor

------------------------------------------------------------------- Gabor DEAK JAHN -- Budapest, Hungary.
E-mail:

Reply by email

Thomas Schatzl
to Gabor DEAK JAHN: That's the error I mentioned in Redef.inc. You are right and your Win32 reference is…

Hi,

> But is that why you're using the @ symbol for BytesFree? Somehow I get

the

> feeling you're going to tell me no. And if you do, then how come the

Win32

> Reference says all the values are pularge_integer but only ones need to

be

Show quoted text 11 lines
> referenced by it's address? [error in redef.inc] This is not equivalent to what Windows expects: the first two parameters, lpFreeBytesAvailableToCaller and lpTotalNumberOfBytes are declared as untyped var parameters (generic pointers), while the third parameter, lpTotalNumberOfFreeBytes is a pointer to a large integer. The Win32 API, in contrast to this, specifies all three parameters as pointers to large integers, hence the need to change the semicolon after lpTotalNumberOfBytes to a comma.

Well, but you forget that the third param is optional, e.g. can be nil.

If this is corrected, you don't have to use the '@' operator before the third parameter any more.

No, because the third parameter is optional, e.g. can be null. By using a 'var' parameter you'd force the programmer to always declare a (probably dummy-) variable for the third param which limits your options to use that function. A completely correct translation for the Pascal language (imo):

function GetDiskFreeSpaceEx(lpDirectoryName: PChar; var
lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes : LargeInteger;
lpTotalNumberOfFreeBytes: PLargeInteger): BOOL;external 'kernel32' name
'GetDiskFreeSpaceExA';

This forces the programmer to use a large integer as mentioned in the MS docs for the first two params but still allows for 'nil' for the third param and preserving the option to ignore the result of lpTotalNumberOfFreeBytes, e.g. not requiring you to declare never used dummy variables in your calling program.

Regards,
Thomas

Reply by email

Gabor DEAK JAHN
to Thomas Schatzl

At 12/8/2001 02:58 PM, you wrote:

Thomas,

Well, but you forget that the third param is optional, e.g. can be nil.

Yes, I did forget that... :-))

OK, then not simply a comma but two separate declarations, yet, the first two should also reference a PLargeInteger. Or whatever else but it is true that if you do provide all three parameters, it oughtn't be necessary to use @ with only one of them and not with the others...

Bye,
Gábor

------------------------------------------------------------------- Gabor DEAK JAHN -- Budapest, Hungary.
E-mail:

Reply by email

Jonas Maebe
to Thomas Schatzl: the Win32 be Well, but you forget that the third param is optional, e.g. can be nil. No,…
Thomas Schatzl wrote 7 lines
function. A completely correct translation for the Pascal language (imo): function GetDiskFreeSpaceEx(lpDirectoryName: PChar; var lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes : LargeInteger; lpTotalNumberOfFreeBytes: PLargeInteger): BOOL;external 'kernel32' name 'GetDiskFreeSpaceExA';

I've changed it to this (the same for the other GetDiskFreeSpaceEx? functions)

Jonas

Reply by email

Unknown author
OK, then not simply a comma but two separate declarations, yet, the

first

two should also reference a PLargeInteger. Or whatever else but it is

true

that if you do provide all three parameters, it oughtn't be necessary to

use

@ with only one of them and not with the others...

I tend to agree with you here. I rigidly adhere to the calling conventions listed in the API Reference, so this could be a bit confusing for someone like me.

Jim

Reply by email