This question already has answers here:
How to detect true Windows version?
(9 answers)
Closed 7 years ago.
It appears that the version info functions in the Win32 API that I know and love have changed their behavior. GetVersionEx now return what the program's manifest is set for, not the actual version.
The new function IsWindows10OrGreater seems pointless since it is only available on windows 10 or greater, so if the program includes it and successfully links it will always return TRUE.
But, in an installer or similar program, how does it determine whether the current environment really is Windows 10 or greater? It needs this to know what to download or which options to set up for other programs.
Your premise is false. The IsWindows10OrGreater function is a macro, so provided you are using a suitably recent version of the SDK the compiled program will work on all currently supported versions of Windows. (As well as Windows XP and I think even Windows 2000.)
(Of course, this mistake is understandable, since the documentation is wrong.)
Note that the program's manifest must still indicate that it supports Windows 10 in order for the macro to work.
Related
If context menu key that launches some executable exists in Windows registry and the "%1" command line patrameter place holder is mentioned, the path this executable gets over GetCommandLine() is limited to MAX_PATH and in some cases Windows tries to make the short path name out of it.
Example:
[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\*\shell\showpath\command]
#="\"C:\\Program Files (x86)\\Utilities\\COMLINE.EXE\" \"%1\""
When the path is:
"\\\\SERVER\MediaFilder25\Philosophic\20220407 Draft thoughts. Questions without answers on the background of the torn Internet\20220407-1 Draft thoughts. Questions without answers on the background of the torn Internet\20220407 Draft thoughts. Questions without answers on the background of the torn Internet.ysssss"
COMLINE.EXE will get following:
"\\\\SERVER\MediaFilder25\39FC~1\202204~3\202204~2\20220407 Draft thoughts. Questions without answers on the background of the torn Internet.ysssss"
Nowadays string length isn't limited. NTFS path depth isn't limited, too.
How to overcome this?
There is a way in registry to allow long paths, explained in this URL.
I comes down to the following registry key:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001
In order to know your current value, you might do this:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" | findstr "LongPathsEnabled"
It is limited to Windows 10, Version 1607, and Later, but your question is about Windows 7.
Windows 10, Version 1607 contains api-ms-win-core-path-l1-1-0.dll.
There is a replica version of api-ms-win-core-path-l1-1-0.dll that can manipulate long paths the way the Windows 10, Version 1607 it does.
Source code is available here: https://github.com/nalexandru/api-ms-win-core-path-HACK
I managed to compile it in Visual Studio 2012 after switching platform toolset to v110 and tested it successfully, for example, with Python 3.9 that relies now on this DLL.
I think, Windows 7 shell can't take advantage of using LongPathsEnabled registry parameter out of the box, and applications should use this DLL directly (but in this case - why to use a DLL? we can build the proper function right into the application). My question was whether the shell can take advantage of it, and the answer is - "not yet!". It depends on shell itself.
recently I stumbled upon a strange phenomenon.
I am building a dumper for PE-files, reading along the section header and "optional" section header quite well. Now, when I reach the fields "OS major" and "OS minor", I notice a strange value.
[WORD] OS VERSION major :0x00000006
[WORD] OS VERSION minor :0x00000000
Apparently this would mean Windows Vista....
Here: https://learn.microsoft.com/de-de/windows/win32/sysinfo/operating-system-version?redirectedfrom=MSDN
I wrote a simple hello-world 32bit executable, and also tested with 7zip.exe (where it, for some reason, was 4.0 [==Win98]).
Now I am confused.... How can my freshly written PE-file (Visual Studio 2019) NOT be of OS version 10???
Did Microsoft maybe, because of lazyness, not update their Linker correctly???
On that page it says something about a manifest file, but only that it would tell you Windows 8.0 if you'd not manifest your executable (however I am supposed to do that, doesn't really matter for the question tho).
Question: Is there a way to read the correct OS-version from a binary?
As it turned out, it seems like this number is more of a
"Required Minimum Opreating system",
that would explain why it is windows Vista.
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.
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.
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