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.
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.
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.
Linux operating system identifies files by looking at its magic number at the starting of the header. How does windows do it ? Does it also have some kind of magic number mechanism or does it only rely on the file extension ?
It relies only on the extension, as provided by the filesystem; the contents of the file are not examined. See e.g. this article - it talks about Windows XP, but AFAIK the general behavior is shared by all released versions of Windows so far: http://support.microsoft.com/kb/307859
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
I'd like to configure visual studio 2005 to copy .dll's based on whether the OS is 64-bit or 32-bit during a build.
I do not want to specify what the platform target is.
My first attempt was to use a batch file to lookup the Windows version, but some 32-bit and 64-bit versions of Windows share the same version number.
Anyone know of any way to check this?
Thanks!
You should be able to read the environment variable %PROCESSOR_ARCHITECTURE%. Here is some great information on it.
http://blogs.msdn.com/david.wang/archive/2006/03/26/HOWTO-Detect-Process-Bitness.aspx
Check out isWow64, I think that shopuld give you what you are after.
Determines whether the specified process is running under WOW64.
Jon's link is a total hack because it relies upon no new processor architectures being added.
See: http://support.microsoft.com/kb/556009 for the "official" batch file method.