Windows API examples

From Lazarus wiki
Revision as of 11:58, 13 March 2021 by Alextpp (talk | contribs)
Jump to navigationJump to search

This is a collection of Lazarus forum posts from user 440bx, about Windows API examples. Source codes were collected in GutHub.

Post 1

Attached to this post are six (6) "teaser" API programs that give an idea of what these programs/examples are about. In addition, there is a "Windows Bitness" program that is more an illustration of how to get the Windows bitness than how to use a specific API.

The teaser examples do _not_ include source at this time. I will include the source when the time comes to give an example of the API they demonstrate. The "Windows Bitness" includes full source to give an idea of what the source code for a typical example looks like.

I will first give a quick description of the purpose of the "teaser" programs before discussing details of the "Windows Bitness" program. The teaser program/examples are:

ExpandEnvironmentStrings

This is an example of the many trivial API functions in Windows. These are APIs that don't have much to say about them. IOW, you read its documentation in MSDN, code the call and you're done.

Roughly (iow, an estimate) 50% of the examples fall in that category. Their main reason to exist was to test their performance and/or behavior in unusual cases. (those were my personal reasons.)


SetConsoleWindowInfo

The description of SetConsoleWindowInfo in MSDN isn't particularly enlightening and the MSDN example's purpose seems to be to confuse the reader (just in case you understood the questionable description that preceded it.)

The teaser example is a visual representation of how that API works. It shows the parameters before the call, the parameters after the call and the effects of the call.

Roughly, 10% of the examples fall in that category (API operation visualization).

I won't go into a detailed explanation at this time. It will be included along with the program source when it is its turn.


ExtTextOut (two (2) examples) InvalidateRect SelectClipRgn

These examples, in addition to demonstrating what the API does and how it works are related by one common goal which is, reducing or eliminating _flicker_ when redrawing.

The InvalidateRect example flickers when the mouse coordinates are updated in the area dedicated to them. Selecting "Invalidate entire area" from the InvalidateRect menu shows how the size of the invalid area makes the flicker more noticeable.


ExtTextOut (v1)

That example is almost identical to the InvalidateRect example but, it demonstrates how to use ExtTextOut to significantly reduce flicker. In the case of the example, to a level that is almost imperceptible.


ExtTextOut (v0)

This example also demonstrates how to significantly reduce flicker but in a larger area. It also demonstrates the clipping abilities of ExtTextOut. The example also shows how to slow a GUI program down by using a console and, how to use the console to help in debugging.


SelectClipRgn

This example shows one the ways available to totally eliminate flicker (zero flicker without using double buffering.) Resize the window horizontally and/or vertically. Control flicker/no flicker with the menu options under "Flicker".


Window Bitness

Consider a program, let's call it program "A" that can be compiled as a 32 bit and 64 bit versions.

The 64 bit version of the program has it easy. All it has to do is determine that it is itself a 64 bit program, once it knows that, it must be running on a 64 bit version of Windows (until MS releases a 128 bit version of Windows - won't happen tomorrow.) To determine if it is itself a 64 bit program, all it has to do is check the size of a pointer, i.e, sizeof(pointer) and if the size is 8 then it knows that it is a 64 bit program and since it is running, it must be running under a 64 bit version of Windows. Easy as pie.

The 32 bit version cannot use that "trick" since its pointer size will be four (4) whether or not it is running under a 32 bit or 64 bit version of Windows.

MS would have the programmer use the IsWowProcess() or IsWowProcess2() API to make the determination but, those two APIs have a few annoyances associated with them. First, they may not be present (IsWowProcess() requires XP SP2 or higher) and, even when present, the user running the program must have some privileges, that while not high, he/she may not have.

There is a way to determine the bitness without using either or these APIs that do not require the user to have any "special" privileges. The "trick" resides in two details. The first one is that the Windows server is what determines the Windows bitness, the second one is that LoadLibraryEx will load almost anything you want as long as you don't intend to run it.

Using the first observation, if Windows is 32 bit then its csrss.exe (client service runtime subsystem) will also be 32 bit and, it will always be 64 bit in a 64 bit version of Windows.

Using the second observation, we can simply ask LoadLibraryEx to load csrss.exe as a datafile and unless the user is totally "privilege destitute", LoadLibraryEx will serve csrss.exe in a sliver platter.

All that's left is for the program to rummage in csrss.exe to determine its bitness and whatever its bitness is, that's the Windows bitness too :) Done!

That's what the program below does (full source in the attachment)

On line 192, the program uses LoadLibraryEx to load csrss.exe. On line 211, it checks the address returned by LoadLibraryEx, which fiddles with the LSB to indicate that it was loaded as a data file and adjusts the address to turn it into the real load address.

On line 219, using the real load address, it determines the module bitness (see GetModuleBitness on line 75.) If anything does not go according to plan, the program states it could not determine the Windows bitness, otherwise it outputs it. Easy as 32 bit pie. :)


My intention is to start with the simplest most trivial API and build from there. This way those who follow the examples can gain the necessary knowledge to understand more subtle and complex use the API.

NOTE: There is an example dedicated to LoadLibraryEx by itself which shows how it behaves under various circumstances.


About 1% (maybe slightly more) of the examples are like the one above, where one API along with "peripheral" knowledge can be used to extract information out of Windows.

I suggest creating a "WinAPI" directory and under that directory, create directories named "Techniques" (which the above example would go into), ntdll, kernel32, gdi32 and user32. Of course, you're free the arrange the examples however you like but, I have found that way to make the large number of programs easier to manage and find.

Post 2

Post 3

Post 4

Post 5

Post 6

Post 7