Recent

Author Topic: API definitions  (Read 733 times)

440bx

  • Hero Member
  • *****
  • Posts: 5073
API definitions
« on: February 08, 2025, 12:29:57 pm »
Hello,

This post is just to find out if the FPC developers would be interested in an updated set of Windows API definitions that, IMO, have a few improvements.  For instance, consider the declaration:
Code: Pascal  [Select][+][-]
  1. function BroadcastSystemMessage
  2.            (
  3.             { _in_        } InFlags      : DWORD;
  4.             { _inout_opt_ } InoutoptInfo : PDWORD;
  5.             { _in_        } InMsg        : DWORD;
  6.             { _in_        } InWparam     : ptruint;
  7.             { _in_        } InLparam     : ptrint
  8.            )
  9.          : longint; stdcall; external user32;
  10.  
  11.   { WARNING: this function is exported without an "A" to indicate Ansi and    }
  12.   {       with an "A" to also indicate Ansi.  They are the same function as   }
  13.   {       they identify the same entry point.                                 }
  14.   {                                                                           }
  15.   {       IOW, don't assume that calling the function without the "A" at the  }
  16.   {       end may be calling the "W" version of the function                  }
  17.  
  18.   { ALSO: the reason for the existence of an "A"-free names is likely due to  }
  19.   {       the fact that in Win95 this function did NOT have an "A" to mark it }
  20.   {       as Ansi                                                             }
  21.  
  22.   { documented at :                                                           }
  23.   {                                                                           }
  24.   { https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-broadcastsystemmessage }
  25.  
Note that the parameter disposition is part of its name, i.e, "in", "inout", "inoutopt' and "out", the parameters are stacked.  The parameter types are often (not always) Pascal types, e.g, ptruint instead of WPARAM.  The result type is always aligned with the function's name beginning.  the calling convention is always explicit, the "name" is only stated if for whatever reason the function is exported by a different name.  The dll name always refers to a constant, e.g, user32 (instead of a string 'user32')

"in"    means a valid value must be passed
"out"  means the parameter value will be set/returned
"opt"  means the parameter is optional (nil in the case of a pointer)

Parameter "const"ness is not part of the parameter name but, if the parameter is "const" that fact is in the disposition comment that precedes the parameter, e.g.,
Code: Pascal  [Select][+][-]
  1. function GetPropA
  2.            (
  3.             { _in_       } InWnd    : HWND;
  4.             { _in_ const } InString : pchar
  5.            )
  6.          : THANDLE; stdcall; external user32;
  7.  

Some API definitions have comments and/or warnings about notable characteristics they may have. This is convenient when jumping to a function definition to find out if there are "details" the programmer should be aware of.

Whenever possible the url where the API is fully documented follows the definition.

The parameter dispositions being part of the parameter name is particularly useful due to CODETOOLS, that way when programming, CODETOOLS tells you if the parameter is "in", "out", "opt", etc which is definitely nice to know on the spot.

To give an idea of the differences from current to proposed, consider the definitions of GetClientRect (current definition);
Code: Pascal  [Select][+][-]
  1. function GetClientRect(hWnd:HWND; lpRect:LPRECT):WINBOOL; external 'user32' name 'GetClientRect';
  2. function GetClientRect(hWnd: HWND; var lpRect: TRect): BOOL; external 'user32' name 'GetClientRect';
  3.  

Updated definitions:
Code: Pascal  [Select][+][-]
  1.   function GetClientRect
  2.              (
  3.               { _in_  } InWnd   : HWND;
  4.               { _out_ } OutRect : PRECT
  5.              )
  6.            : BOOL; stdcall; external user32;
  7.  
  8.   function GetClientRect
  9.              (
  10.               { _in_  }     InWnd   : HWND;
  11.               { _out_ } out OutRect : TRECT
  12.              )
  13.            : BOOL; stdcall; external user32;
  14.  
  15.   { documented at :                                                           }
  16.   {                                                                           }
  17.   { https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect }
  18.  
One of the definitions would be in func.inc, the other in redef.inc.  The "Documented at:" part would be in both.

I have roughly 3500 such definitions (they are the definitions I use in my programs, therefore they have been tested) and I would ensure that the updated definitions are functionally equivalent to the current ones.

Also and particularly in the case of NTDLL, I have hundreds of definitions for undocumented functions/procedures.  All of them are current and tested.  NOTE: much more complete, not to mention current, than the Jwa... definitions.

If there is interest, I would update the necessary files (func.inc, redef.inc for regular win and wince.)

Note: unlike the current definitions in func.inc which use "var' for parameters that are "out", e.g, GetClientRect, which cause warnings about uninitialized data, my definitions use either "out" or a pointer type (the C equivalent definition which is what I normally use.)

Lastly, as previously stated, I have about 3500 such definitions.  I don't have the entire Windows API, therefore this offer is for about 3500 definitions (maybe a few more, maybe a few less but definitely not the 13000+ APIs Windows currently supports nor every API that is currently declared in func.inc and redef.inc. (though, I'd try to include as many of those as reasonably possible.)

Comments welcome.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

gidesa

  • Full Member
  • ***
  • Posts: 160
Re: API definitions
« Reply #1 on: February 08, 2025, 04:33:22 pm »
Hello,
your proposal is interesting.
But that functions are part of MS libraries, not FPC own libraries. So I think should be better to adhere exactly to MS docs. So no in/out prefix on parameters, and always use Windows types (although often they are only an alias for a FPC type).
In the example function should be:
Code: Pascal  [Select][+][-]
  1. function BroadcastSystemMessage
  2.            (
  3.             { _in_        } flags        : DWORD;
  4.             { _inout_opt_ } lpInfo  : PDWORD;
  5.             { _in_        } Msg         : DWORD;
  6.             { _in_        } Wparam   : WPARAM;
  7.             { _in_        } lParam     : LPARAM
  8.            )
  9.          : longint; stdcall; external user32;
  10.  

Note that also names are have different upper/lowercase. And reference is changed:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-broadcastsystemmessage
If you try old link it automatically transfer to new one. So comments with a detailed description of function could be problematic, MS being continuously changing things...



440bx

  • Hero Member
  • *****
  • Posts: 5073
Re: API definitions
« Reply #2 on: February 08, 2025, 05:02:25 pm »
So I think should be better to adhere exactly to MS docs. So no in/out prefix on parameters, and always use Windows types (although often they are only an alias for a FPC type).
In the example function should be:
Code: Pascal  [Select][+][-]
  1. function BroadcastSystemMessage
  2.            (
  3.             { _in_        } flags        : DWORD;
  4.             { _inout_opt_ } lpInfo  : PDWORD;
  5.             { _in_        } Msg         : DWORD;
  6.             { _in_        } Wparam   : WPARAM;
  7.             { _in_        } lParam     : LPARAM
  8.            )
  9.          : longint; stdcall; external user32;
  10.  
I would normally agree about the definition being as close to MS' but, MS' definitions have too many problems.  Among them, there are no longer "far pointers" in 32 and 64 bit, therefore the "lp" prefix is not only meaningless but downright inappropriate for any 32 or 64 bit platform. 
As far as types WPARAM and LPARAM, I find that hiding the _true_ types of some parameters is a bad idea particularly in the case of wParam and lParam because their meaning depends on the message, therefore their real type is message dependent.

Lastly, as far as the disposition, I find it annoying to have to often waste time having to look up an API just to find out if a parameter is input, output or both.  If the disposition is part of the name then codetools gives me that information on the spot, IOW, no need to waste time looking it up.

There are plenty of reasons I invested the time in writing my own Windows API definitions.  The time savings from better API definitions isn't immediately obvious but, once you have them, you'd be surprised how much time and aggravation it saves.

The current definitions provide a genuinely meager amount of information about an API, basically, the absolute minimum, which effectively lessens the value of CODETOOLS because the CODETOOLS information is dependent on the information contained in the definition.  Additionally, since the url where the API is documented is not present, that necessitates copy/pasting the API name in a search engine, doing the search and clicking on one of the results to _finally_ get to the documentation page. 

If all of the above wasn't enough, MS has APIs where their parameters are named "unnamed_parm1, unnamed_parm2..." and so on, that really helps the programmer figuring out what should be fed to those APIs.

The MS definitions, like the FPC ones, can be _greatly_ improved.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12107
  • FPC developer.
Re: API definitions
« Reply #3 on: February 08, 2025, 05:13:28 pm »
I'm not going to replace existing functions. But it would be nice to have for reference, and to scan for new signatures.

I don't consider having the modifiers in comments so useful. It takes up space, and in and occasional case of doubt it easily looked up.

redef  (var and out variants) is not something that is done systematically, only for known exceptions due to the fact that early FPC's or delphi's defined them thus, mostly in the pre overloading era.

gidesa

  • Full Member
  • ***
  • Posts: 160
Re: API definitions
« Reply #4 on: February 08, 2025, 05:24:12 pm »
I think that Windows functions could be used in 3 modes:
1) you simply copy from an example, maybe an MS one, so things should exactly corresponding to MS nomenclature to avoid confusion.
2) you want to use the function, not knowing much, and then you open MS doc and see. Again, it's better to have exact correspondence
3) you use the function and are a real expert: no problem at all
 
Perhaps your very detailed comments, with addition/explaination of MS doc gained from first person experience , in my opinion could be extracted and
fomatted in an external document.

440bx

  • Hero Member
  • *****
  • Posts: 5073
Re: API definitions
« Reply #5 on: February 08, 2025, 06:00:31 pm »
I'm not going to replace existing functions.
I'm offering to do all the work including ensuring that the updated definition is fully functionally equivalent to the old one.

I don't consider having the modifiers in comments so useful. It takes up space, and in and occasional case of doubt it easily looked up.
It does take additional space but, it is also much more readable and, while it is easy to look things up, it does take time which adds up.

redef  (var and out variants) is not something that is done systematically, only for known exceptions due to the fact that early FPC's or delphi's defined them thus, mostly in the pre overloading era.
I would not add new re-definitions only update the current ones.

Just to give an idea of what I'm talking about, just as an example, here are the current definitions of SetScrollInfo:
Code: Pascal  [Select][+][-]
  1. function SetScrollInfo(_para1:HWND; _para2:longint; _para3:LPCSCROLLINFO; _para4:WINBOOL):longint; external 'user32' name 'SetScrollInfo';
  2. function SetScrollInfo(hWnd: HWND; BarFlag: Integer; const ScrollInfo: TScrollInfo; Redraw: BOOL): Integer; external 'user32' name 'SetScrollInfo';
  3.  
The first one from func.inc and the second one from redef.inc.

Notable in those definitions is the inconsistent naming of the parameters, basically unnamed in the first one and "better named" in the second one.  The second definition uses a feature which depends on internal implementation, specifically, it is depending on the compiler passing a pointer to a TSCROLLINFO because the parameter is declared as "const".  That's, as you often say: "undefined territory" because that behavior is not documented and has been explicitly disavowed in the past by FPC developers.  If all that wasn't enough, it uses LPCSCROLLINFO, there are no "LP" pointers in 32 and 64bit, therefore, that type description is actually incorrect (but that's on MS shoulders), one definition uses BOOL, the other WINBOOL and, one definition uses "integer" while the other one uses "longint".   It would be nice for the current definitions to be consistent.

The correct definition should have the parameter as "constref" to properly and correctly indicate that what is being passed is a pointer to a constant TSCROLLINFO structure/record.

To summarize, the current definitions are highly inconsistent and one of them depends on internal FPC behavior (which admittedly is unlikely to change.)  This is _not_ an isolated example.

I offer this instead:
Code: Pascal  [Select][+][-]
  1.   function SetScrollInfo
  2.              (
  3.               { _in_       } InWnd           : HWND;
  4.               { _in_       } InScrollbarType : longint;
  5.               { _in_ const } InScrollInfo    : PSCROLLINFO;
  6.               { _in_       } InRedraw        : BOOL
  7.              )
  8.            : longint; stdcall; external user32;
  9.  
  10.   function SetScrollInfo
  11.              (
  12.               { _in_       }          InWnd           : HWND;
  13.               { _in_       }          InScrollbarType : longint;
  14.               { _in_ const } constref InScrollInfo    : TSCROLLINFO;
  15.               { _in_       }          InRedraw        : BOOL
  16.              )
  17.            : longint; stdcall; external user32;
  18.  
  19.   { documented at :                                                           }
  20.   {                                                                           }
  21.   { https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setscrollinfo }
  22.  

True that what I offer takes more space but, it is significantly more readable (nice when someone jumps to the definition), the definitions use types consistently and, give the url where full documentation is located (granted those urls could change but, they change very seldom and updating them is easy and can be done in an on-going basis.)

One thing that crossed my mind is adding "overload" for functions that are overloaded so it is obvious they are overloaded when reading either func.inc or redef.inc. I'm willing to do that, it's just a few additional seconds per overloaded API.




I'm putting this part separately because I know it will be controversial but, I have somewhere in the vicinity of a thousand undocumented functions from various dlls, e.g., ntdll, kernel32, kernelbase, gdi32, user32 and others.  I think it would be really nice to include those as well. 

Having those definitions would definitely set FPC apart from other development tools.  It would have the best set of ring-3 API definitions second to MS internal definitions only (not the VS stuff but the definitions they use for Windows itself.)

That might get some attention towards FPC. :)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5904
  • Compiler Developer
Re: API definitions
« Reply #6 on: February 08, 2025, 06:27:28 pm »
I'm putting this part separately because I know it will be controversial but, I have somewhere in the vicinity of a thousand undocumented functions from various dlls, e.g., ntdll, kernel32, kernelbase, gdi32, user32 and others.  I think it would be really nice to include those as well. 

Having those definitions would definitely set FPC apart from other development tools.  It would have the best set of ring-3 API definitions second to MS internal definitions only (not the VS stuff but the definitions they use for Windows itself.)

That might get some attention towards FPC. :)

The Windows unit is intended for the documented API of Windows. If at all such functions would belong into a separate unit in packages/winunits-base or maybe they already exist in packages/winunits-jedi, then they aren't required somewhere else.

440bx

  • Hero Member
  • *****
  • Posts: 5073
Re: API definitions
« Reply #7 on: February 08, 2025, 07:35:57 pm »
The Windows unit is intended for the documented API of Windows. If at all such functions would belong into a separate unit in packages/winunits-base or maybe they already exist in packages/winunits-jedi, then they aren't required somewhere else.
I can see the point in having them in a separate unit, prevents anyone from inadvertently using an undocumented function.  Maybe a "WinUndoc" unit ?

As far as the Jwa... (jedi) units, I'm sure at one time they were useful.  I've looked at those units and have found too many outdated definitions (particularly structures) and too many incorrect definitions.  They were probably ok at one time but today (2025), I openly recommend not to use those units.  That said, I have seen the opposite too, a correct definition in a Jedi unit and an incorrect one in the func.inc and/or redef.inc files.  IOW, it's a mixed bag.

I believe that having a correct, reasonably well documented set of undocumented functions along with _working_ example code for a majority of them _may_ actually contribute to having some eyeballs look the FPC way, which would not hurt.

That said, the undocumented part, if not part of the Windows unit itself (which is fine) would probably best be done as a second step since in that case it would be separate anyway.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

 

TinyPortal © 2005-2018