Recent

Author Topic: The declaration of WriteFile, ReadFile win32 api may be incorrect.  (Read 1741 times)

Red_prig

  • Jr. Member
  • **
  • Posts: 60
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #15 on: May 20, 2022, 01:00:38 pm »
The declaration is binary correct and is unlikely to be changed. In all this, there is only the problem of atypical differences with the "C" code. This is especially true for beginners who cannot understand what the problem is.

tetrastes

  • Full Member
  • ***
  • Posts: 216
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #16 on: May 20, 2022, 04:13:22 pm »
Note that WriteFileEX does have an overload.
WriteFileEx is defined correctly, that is, the buffer  parameter is of type pointer as it should be. 
I would not be so sure:
Code: Pascal  [Select][+][-]
  1. function WriteFileEx(hFile: THandle; lpBuffer: Pointer; nNumberOfBytesToWrite: DWORD; const lpOverlapped: TOverlapped; lpCompletionRoutine: FARPROC): BOOL; external 'kernel32' name 'WriteFileEx';
  2.  
lpBuffer is pointer, but lpOverlapped is not, and even const, while in MS docs it is
Quote
[in, out]      LPOVERLAPPED                    lpOverlapped,
But I have found only one WriteFileEx (in redef.inc), where is overload?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10071
  • FPC developer.
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #17 on: May 20, 2022, 04:34:38 pm »
But I have found only one WriteFileEx (in redef.inc), where is overload?

in func.inc

Code: Delphi  [Select][+][-]
  1. function WriteFileEx(hFile:HANDLE; lpBuffer:LPCVOID; nNumberOfBytesToWrite:DWORD; lpOverlapped:LPOVERLAPPED; lpCompletio
  2. nRoutine:LPOVERLAPPED_COMPLETION_ROUTINE):WINBOOL; external 'kernel32' name 'WriteFileEx';
  3.  

tetrastes

  • Full Member
  • ***
  • Posts: 216
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #18 on: May 20, 2022, 10:14:04 pm »
But I have found only one WriteFileEx (in redef.inc), where is overload?

in func.inc

Code: Delphi  [Select][+][-]
  1. function WriteFileEx(hFile:HANDLE; lpBuffer:LPCVOID; nNumberOfBytesToWrite:DWORD; lpOverlapped:LPOVERLAPPED; lpCompletio
  2. nRoutine:LPOVERLAPPED_COMPLETION_ROUTINE):WINBOOL; external 'kernel32' name 'WriteFileEx';
  3.  
Thank you for information.
But by default the declaration from redef.inc is used, so this overload is still not very helpful for C-minded beginners.
« Last Edit: May 20, 2022, 10:25:58 pm by tetrastes »

440bx

  • Hero Member
  • *****
  • Posts: 2812
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #19 on: May 20, 2022, 10:51:07 pm »
But by default the declaration from redef.inc is used, so this overload is still not very helpful for C-minded beginners.
:D That is hilarious.  The incorrect definition of WriteFile is more of a problem to an experienced programmer than a beginner.  An experienced C programmer expects the definition to be as MS defined it (if you wonder why that is, it's got something to do with the fact that MS authored the O/S the function is used in but, that's a small, 25 million line of code detail.)

Since Pascal can replicate _exactly_ the C definition, there is no justifiable reason to have one that is semantically different that does _not_ function like the original.   In the case of FPC, the justification is that Delphi defined it that way and for compatibility FPC followed but, it doesn't make it right.

And, to make matters worse, the definitions of WriteFile and WriteFileEx are not parallel (they should be.)

Other than all that, it's perfectly fine. :)

FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

tetrastes

  • Full Member
  • ***
  • Posts: 216
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #20 on: May 21, 2022, 12:26:32 am »
:D That is hilarious.
That's what it's designed for  ;)

Quote
The incorrect definition of WriteFile..
You may call it incorrect, others call it correct, I don't care, as it works as expected.  8-)

Quote
An experienced C programmer expects the definition to be as MS defined it
?? My experience in C was much longer, than in Pascal, but I didn't expect that Pascal declaration would be exactly as C. And what does unexperienced programmer expect?

Quote
Since Pascal can replicate _exactly_ the C definition, there is no justifiable reason to have one that is semantically different that does _not_ function like the original.
On the other hand, there is no justifiable reason _not_ to have one. This is Sparta Pascal  :D

Quote
In the case of FPC, the justification is that Delphi defined it that way and for compatibility FPC followed but, it doesn't make it right.
Compatibility, in the first place with existing code, is the sacred cow. We still write such things like LPVOID and wait for long pointers to return...  ::)

Quote
And, to make matters worse, the definitions of WriteFile and WriteFileEx are not parallel (they should be.)
I would like to have your problems...  :D

440bx

  • Hero Member
  • *****
  • Posts: 2812
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #21 on: May 21, 2022, 12:51:28 am »
On the other hand, there is no justifiable reason _not_ to have one. This is Sparta Pascal  :D
but there _is_ a good reason not to have one and, that is, when a programmer searches for the documentation on an API function, what shows up is MS' documentation and, calling Pascal's WriteFile as it is documented in MSDN will _not_ work and, there is _no_ Free Pascal page that documents the fact that FPC's definition is not equivalent to MS'.

IOW, if a programmer follows MS' documentation for a call to WriteFile (not much alternative), what will be written is garbage and FPC will happily accept whatever is passed as buffer because the parameter is untyped (that's what strong type checking is for, throw it out the Window... <chuckle>)




FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10071
  • FPC developer.
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #22 on: May 21, 2022, 01:33:14 pm »
On the other hand, there is no justifiable reason _not_ to have one. This is Sparta Pascal  :D
but there _is_ a good reason not to have one and, that is, when a programmer searches for the documentation on an API function, what shows up is MS' documentation and, calling Pascal's WriteFile as it is documented in MSDN will _not_ work and, there is _no_ Free Pascal page that documents the fact that FPC's definition is not equivalent to MS'.

A good programmer of course has "Win32 Core Api" , the Petzold like book for Pascal.

BeniBela

  • Hero Member
  • *****
  • Posts: 840
    • homepage
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #23 on: May 21, 2022, 03:08:56 pm »
The real problem is with the optional parameters like lpNumberOfBytesWritten.


You are supposed to pass null/nil if you do not want to obtain that information, but with a var parameter, it does not allow that directly.

PascalDragon

  • Hero Member
  • *****
  • Posts: 4119
  • Compiler Developer
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #24 on: May 21, 2022, 04:52:00 pm »
Quote
yes, an overload (using the correct definition) would definitely be a good thing in this case and, it seems its presence would not break any existing code.

Overloading more than one difference is somewhat dangerous, because people get weird errormessages if they pass e.g. a pointer and don't @ the other etc. 

Normally I wouldn't mind, but by such a core procedure I get a tad conservative. It has the potential to cause problems without much gain.

But people already have problems with the current declaration already as well as highlighted by marunguy and at least then people would be able to follow C examples directly.

But I have found only one WriteFileEx (in redef.inc), where is overload?

in func.inc

Code: Delphi  [Select][+][-]
  1. function WriteFileEx(hFile:HANDLE; lpBuffer:LPCVOID; nNumberOfBytesToWrite:DWORD; lpOverlapped:LPOVERLAPPED; lpCompletio
  2. nRoutine:LPOVERLAPPED_COMPLETION_ROUTINE):WINBOOL; external 'kernel32' name 'WriteFileEx';
  3.  
Thank you for information.
But by default the declaration from redef.inc is used, so this overload is still not very helpful for C-minded beginners.

What do you mean “by default”? There is no default, because it's overloaded inside the same unit and thus both are available to the user.

Quote
In the case of FPC, the justification is that Delphi defined it that way and for compatibility FPC followed but, it doesn't make it right.
Compatibility, in the first place with existing code, is the sacred cow. We still write such things like LPVOID and wait for long pointers to return...  ::)

Well, in FPC's Win16 port they did indeed return as LPVOID is declared as a FarPointer there. ;)

The real problem is with the optional parameters like lpNumberOfBytesWritten.


You are supposed to pass null/nil if you do not want to obtain that information, but with a var parameter, it does not allow that directly.

If one knows how, it's perfectly fine to pass a Nil to a reference parameter:

Code: Pascal  [Select][+][-]
  1. program tvar;
  2.  
  3. {$mode objfpc}
  4.  
  5. procedure Test(var aArg: LongWord);
  6. begin
  7.   Writeln(HexStr(@aArg));
  8. end;
  9.  
  10. begin
  11.   Test(PLongWord(Nil)^);
  12. end.

This will print a bunch of zeros ;)

tetrastes

  • Full Member
  • ***
  • Posts: 216
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #25 on: May 21, 2022, 06:16:48 pm »
What do you mean “by default”? There is no default, because it's overloaded inside the same unit and thus both are available to the user.
Yes, you are right. By "default" I meant that you see the declaration from redef.inc by placing cursor over WriteFileEx in Lazarus Source Editor, and it is not obvious how to find the second one.

440bx

  • Hero Member
  • *****
  • Posts: 2812
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #26 on: May 21, 2022, 07:23:44 pm »
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:
I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil.  Using any of the var parameters that got passed a nil value will cause an access violation.


FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 4390
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #27 on: May 21, 2022, 10:54:20 pm »
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:
I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil.  Using any of the var parameters that got passed a nil value will cause an access violation.

Sven saved me the trouble of digging out the message of a couple of weeks ago where he showed me how to do this.

I'd suggest that the bottom line is that (a) Pascal was designed when programs were basically still the expression of mathematical or logical formulae where (of course) there is no such thing as an optional parameter, and (b) the scope of software is now much wider so we have to admit that additional syntax and semantics are needed.

I have no problem with a var parameter being nullable (is that the right term?) provided it can be checked and/or an error caused by a reference can be caught.

Arguably, the same applies to both const and out parameters.

Let's face it, at least some of the above could be handled by procedure/function overloads which quite simply omit the relevant parameter, but Wirth didn't think of those either.

Finally, pragmatism dictates that modern Pascal's parameter conventions need to be compatible with C. Broadly speaking, var parameters are superior to pointers since they don't have to be explicitly dereferenced and aren't at risk from pointer arithmetic, and not allowing a var parameter to be nulled is a major omission.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 2812
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #28 on: May 22, 2022, 12:18:37 am »
Finally, pragmatism dictates that modern Pascal's parameter conventions need to be compatible with C. Broadly speaking, var parameters are superior to pointers since they don't have to be explicitly dereferenced and aren't at risk from pointer arithmetic, and not allowing a var parameter to be nulled is a major omission.

MarkMLl
I completely agree that a computer language has to be compatible/accommodate C's parameter passing semantics but, I strongly believe that a "var" parameter should _not_ be nullable because, if that parameter is nullable then it should _not_ be a "var" parameter.

IOW, it is implicit that "var" is the address of a _variable_ and _not_ the address of "nothing".  if the parameter can be nil then it should be a "pointer" not a "var".

That's one of the many logical advantages of Pascal over C.  When a parameter is "var", the fact that it is "var" means that it cannot be null/nil.  That makes the usage of "var" informative.  IOW, "var" states that there exists a pre-condition that the parameter cannot be a null/nil pointer.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 4119
  • Compiler Developer
Re: The declaration of WriteFile, ReadFile win32 api may be incorrect.
« Reply #29 on: May 23, 2022, 01:32:04 pm »
If one knows how, it's perfectly fine to pass a Nil to a reference parameter:
I wouldn't go as far as saying it's "perfectly fine", I'd say it's definitely possible but, IMO, it should be strongly discouraged because it is completely reasonable for a procedure/function that uses "var" parameters to presume the parameters are _not_ nil.  Using any of the var parameters that got passed a nil value will cause an access violation.

You're right that the function in question should handle that correctly (which essentially all Pascal code doesn't because as you rightfully stated in your other post, var means not Nil), however for dealing with imported C functions that use var instead of a pointer and for which the parameter may indeed be NULL this is a valid trick to be used as from the PoV of the compiler no special magic is involved here.

 

TinyPortal © 2005-2018