how to call different Win API based on Windows version? - winapi

The specific problem is, the support of condition variable on Windows begins from Vista, for early version of Windows (Windows XP), I have a emulated condition variable code sort of solved the problem. However, I'd like to have the ability to call native condition variable API when the system supported and fallback to my version only on XP and earlier version. I tried to detect windows version with GetVersionInfo API, but it still gives me error on start time (cannot find API entry of InitializeConditionVariable sort of).
I am not familiar with Windows programming, how do you solve the gentle fallback problem nicely?

if you want to call a function that may or may not exist depending on platform version then use dynamic loading
LoadLibrary and GetProcAddress
These will tell you if the entry point exists and then let you call it if it does

Related

GetProcAddress fails on Win 7 even though the DLL actually exports the function (works on Win 10)

I have a 32-bit application and I have a problem with it on Windows 7 x64. I'm loading a DLL. LoadLibraryW succeeds and the subsequent call to GetProcAddress fails with the error code 127 ("procedure not found" or something like that).
The funny part is that I know for a fact the function is exported by the DLL. I made no typos in the GetProcAddress call. I can see the function with Depends.exe and DllExp.exe. The exact same application binary successfully loads the function from the exact same DLL on Windows 10 x64, but not on Windows 7 x64.
Some more details: the library is dbghelp.dll and the "missing" function is MiniDumpWriteDump.
And the fun bit: dbghelp.dll provides API for inspecting the modules loaded into the process and for enumerating functions exported by those modules. So, first I took the HMODULE for this problematic dbghelp.dll and ran
auto ptrSymInitialize = (decltype(&SymInitialize))GetProcAddress(hDbgHelpDll, "SymInitialize");
It worked, this function did load! Then I loaded SymEnumSymbols, written the enumerator callback and finally ran the following to enumerate all the functions in this very `dbghelp.dll":
ptrSymEnum(GetCurrentProcess(), 0, "dbghelp*!*", &Enumerator, nullptr);
And what do you know, MiniDumpWriteDump is, in fact, listed there. Go figure.
Thoughts?
I can see your intent is to use MiniDumpWriteDump. We also make minidumps in our product, and I'm the one to support this.
I would suggest against using dbghelp.dll supplied with OS. First, they tend to be outdated and not support the latest minidump capabilities, which you would want to have. Second, they have proven to be rather unreliable. I believe they simply lack too many bugfixes.
What I found to work quite well is to take dbghelp.dll from Debugging Tools for Windows package (currently part of Windows SDK) and ship it along with our product. This way, I can be sure minidumps will have all the latest features and it works reliably on all OS. It has been some 8 years now, with OS ranging from WinXP to Win10, and I didn't have any issues.
I'm not exactly sure which version of SDK I used to extract the currently used dbghelp.dll, probably it was Win7 SDK. I simply didn't have a reason to update since then. However, we do use Debugging Tools for Windows package from Win10 SDK on Win7 without any issues, so I guess you can use Win10 version as well.
that's exactly what I've been doing, and I didn't bring dbgcore.dll
This was just a plain bad idea. Microsoft makes no effort to make the DLLs that are included with the OS to be backwards compatible. They don't have to. In their implementation, only the interface needs to be compatible. They do take advantage of new capabilities or design changes to improve the implementation.
Like you saw here, a side-effect of the MinWin project. There is no reasonable guess where that ended, if it happens to work now on the Win7 machine then you got lucky. Maybe you won't be so lucky on a Win7 machine without SP1, maybe some minwin glue DLLs are missing on a clean install, maybe the minidump itself is affected negatively some way. Impossible to predict.
So never do this. Afaik you should not be doing this at all, a Win7 machine already has dbghelp.dll available. Not 100% sure, it has been too long and Win7 is rapidly turning into the new XP. If you find it to be necessary then always use the redistributable version. Included with the SDK's Debugging Tools for Windows. Copy it into the same folder as the EXE that needs it so you don't mess up a machine.

Detect Windows version on Delphi 2007 with no APIs

Simple question : how to detect Windows version in a reliable way using Delphi 2007 ? Is there a way to do it without APIs ie, checking only some folder or files in system directory ?
Thanks in advance !
You cannot check a file or registry value without calling a Windows API function!
The only way to check the version without calling any API is to read from the PEB but most of the fields there are undocumented and could in theory change from version to version. It is also affected by the compatibility shims. I don't recommend that you do this but if you insist then this code might be a good starting point, just read the OSMajorVersion and OSMinorVersion members (Teb from GetTeb and Peb := Teb.Peb from Teb).
Microsoft recommends that you check if the feature you need exists instead of checking the version. The recommended way to check the version is with VerifyVersionInfo but you can still continue to use the deprecated GetVersionEx if you need the version number for display purposes. Both of these functions require a manifest to get the correct version on Windows 8.1 and 10.
In theory you can parse EXPLORER.EXE for its version details and then speculate on the Windows version. But every Delphi version uses for Pascal's blockread() implementation the WinApi again. And wanting tofind the Windows-directory (which can have any name on any drive) also leads to WinApi calls again.

How does OpenGL find the implementation to use on Windows?

I have a Java program using OpenGL via JOGL, and there are some bugs that only appear on Windows that I'd like to debug. For this purpose, I tried setting up a spare computer with Windows, but encountered a strange problem when I went to debug my program:
When I run the program "normally" via Java Web Start, it works perfectly normally, but when I compiled the program and try to run it either via the command-line java launcher or via NetBeans (which I presume does the same thing), it appears to be using a different and very primitive OpenGL implementation that doesn't support programmable shading or anything.
When researching the problem, I've let myself understand that OpenGL programs running on Windows load opengl32.dll, which is apparently a common library that ships with Windows (correct me if I'm wrong) and which in turn loads the "real" OpenGL implementation and forwards OpenGL function calls to it. (It also appears to be somewhat of a misnomer, as it is in fact loaded in a 64-bit process at a base address clearly above 232.)
Using Process Explorer, I see that, when I run the program under Java Web Start (where it works), it loads the library ig4icd64.dll, which I assume is the actual OpenGL implementation library for the Intel GPU driver; whereas when trying to run the program via java.exe, opengl32.dll is loaded, but ig4icd64.dll is never loaded, which appears to confirm my suspicion that it's using a different OpenGL implementation.
So this leads to the main question, then: How does opengl32.dll select the OpenGL implementation to use, and how can I influence this choice to ensure the correct implementation is loaded? What means are available to debug this? (And what is different between these two contexts that causes it to choose different implementations? In both cases, 64-bit Java is used, so there should be no confusion between 32- or 64-bit implementations.)
Update: I found this page at Microsoft's site that claims that the OpenGL ICD is found by way of the OpenGLDriverName value in the HKLM/System/CurrentControlSet/Control/Class/{Adapter GUID}/0000/ registry key. That value does correctly contain ig4icd64.dll, however, and perhaps more strangely, using Process Monitor to monitor the syscalls (if that's the correct Windows terminology) of the Java process reveals that it never attempts to access that key. I can't say I know if that means that the article is incorrect, or if I'm using Process Monitor incorrectly, or if it's something else.
When researching the problem, I've let myself understand that OpenGL programs running on Windows load opengl32.dll, which is apparently a common library that ships with Windows (correct me if I'm wrong) and which in turn loads the "real" OpenGL implementation and forwards OpenGL function calls to it.
Yes, this is exactly how it works. opengl32.dll acts as a conduit between the Installable Client Driver (ICD) and the programs using OpenGL.
So this leads to the main question, then: How does opengl32.dll select the OpenGL implementation to use, and how can I influence this choice to ensure the correct implementation is loaded? What means are available to debug this?
It chooses based on the window class flags (that's not a Java class, but a set of settings for a window as part of the Windows API, see https://msdn.microsoft.com/en-us/library/windows/desktop/ms633577(v=vs.85).aspx for details), the window style flags the pixel format set for the window, the position of the window (which means which screen and graphics device it's on) and the context creation flags.
For example if you were to start it as a service then there's be no graphics device to create a window on at all. If you were to start it in a remote desktop session it would run on a headless, software rasterizer implementation.
I don't know the particular details in how the CLI java interpreter differs from WebStart. But IIRC you use javaw (note the extra w) for GUI programs.
(It also appears to be somewhat of a misnomer, as it is in fact loaded in a 64-bit process at a base address clearly above 2^32.)
It's not just opengl32.dll but all Windows system DLLs that are named …32 even in a 64 bit environment, and they're even located in \Windows\System32 to add to the confustion. For a very simple reason: Source code level backwards compatibility when compiling for 64 bits. If all the library names would have been changed to …64 then for compiling programs for a 64 bit environment all the string literals and references to the libraries would have to be renamed to …64.
If it makes you feel better about the naming, think of the …32 as a version designator, not an architecture thing: The Win32 API was developed in parallel for Windows 9x and Windows NT 3, so just in your mind let that …32 stand for "API version created for Windows NT 3.2".

WIA microdrivers do not work - why?

I wrote a WIA microdriver that currently only produces dummy data - later on it should acquire data from a scanner.
The MicroEntry() and SetPixelWindow() functions are called as expected, then Scan(SCAN_FIRST,...) is called and Scan(SCAN_NEXT,...) is called multiple times.
Then I get an error (message has no special meaning) - both when using "Windows Live Image Gallery" and when using "Windows Fax and Scan". I use Windows 7, 64-bit.
I tried to use the official WIA microdriver example from the Windows Driver Kit. I cannot see which functions are called in which order but I get an error message using both programs, too.
Because the official driver from Microsoft does also not work I think the problem is not in my program but somewhere in the OS.
My questions:
Is there any known reason why these drivers do not work?
Is there any work-around?
Thanks.
I found out the answer myself:
The official example microdriver has a bug! Because I used that driver as template for my own one my driver had the same bug.
The problem is that the last argument of the "Scan()" function is NULL in the SCAN_FINISH phase but the example driver will always write 0 to the location this pointer points to.
I wonder why Microsoft didn't find this bug because it will always lead to an exception in the driver!

GetProfileInt() is failing

In my application, I am using the following Win32 API to before loading the mapi32.dll.
win32 API: ::GetProfileInt(_T("MAIL"), _T("MAPI"), 0);
This API is consistently failing on Windows 8.1 Italian 64-Bit PC.
But, this API is succeeding on all other PCs like Windows 8.1 English(US) 64-Bit PC, Windows 8.1 Japanese 64-Bit PC.
Kindly provide your kind help for fixing the above issue.
To find MAPI32.dll look in either of these paths:
C:\Windows\SysWOW64\mapi32.dll
C:\Windows\System32\mapi32.dll
or use this
GetWindowsDirectory(buf, 260);
lstrcat(buf, TEXT("\\SysWOW64\\mapi32.dll"));
...
To access old win.ini settings, look in this registry key:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\win.ini
But there is probably nothing there about MAPI, it's about 20 years out of date.
The code you originally got this from was probably very old and is no longer supported. If you read the documentation for GetProfileInt, you'll see that its purpose is to support 16-bit applications.
I recommend removing the call. I have also observed it failing on Windows 7 machines while succeeding on Windows 10 machines. I think the more appropriate calls are to use SearchPath(nullptr, L"MAPI32.DLL", nullptr, 0, nullptr, nullptr) to see if MAPI32.DLL would even be found. An alternative is to just attempt the LoadLibrary(L"MAPI32.DLL") and check the returned handle.
An even better solution might be to change your code to call MAPISendMailHelper as it will do the LoadLibrary, GetProcAddress, etc. for you.

Resources