The programming / os / win does sound like it would be the best suited forum. I estimate that I have somewhere between 700 and 800 examples/test programs.700 topics would mean anyone just browsing the board would see nothing else.
The reason I thought about doing one post per API was to make it easy to find. I would title each post along the lines of "Win API example - api name" which I believe would make it easy to find using the forum's search engine. Combining multiple APIs into one post could make finding the example for a specific API more difficult for the interested party.An idea would be to have on overview topic, in which to post the name and link (to the post inside a thread) for each example. That would help finding them. You can keep that topic locked, so only you can write to it (you may need to unlock it to edit it, not sure).
I don't find the repositories attractive because they are very static. The great advantage of the forum is that they are interactive, every one can participate either with questions, suggestions and/or improvements.
700 topics would mean anyone just browsing the board would see nothing else.that's definitely a valid concern, which is why I thought about limiting the number of posts to a maximum of 5 per day, to avoid "drowning" other posts in the target forum.
Even 140 (700 div 5) is way too much (unless they really all attract big exchange of messages).
An idea would be to have on overview topic, in which to post the name and link (to the post inside a thread) for each example. That would help finding them. You can keep that topic locked, so only you can write to it (you may need to unlock it to edit it, not sure).I figured we could try 5 posts a day in a particular forum (the one you suggested sounds very appropriate) and if that creates a problem then address whatever problem arises (if any) with a solution tailored for it.
(It may need updating, if topics need to be split/merged)
Well you can disable all feedback on github, and include a readme that points to the forum as place for discussion.That is a possibility but, since the examples would be on github (or some other repo) it would result in a lack of context (the API in one place - the repo - and, its discussion in another - the forums here.)
Build it and they will come :)I think you're quite right about that. I'm going to prepare a few "teaser" examples in the next few days. That might raise interest. "Seeing is coveting" ;)
In my past experience, relying on a Forum for longevity of preservation does not work. <snip> perhaps the biggest disadvantage is that the content becomes scattered and hard to find once it's been buried in several hundred/thousand posts.I'm not concerned about the longevity. I presume that if members find the examples useful they will be remain, if not they'll be dropped or archived away as they eventually should be.
The Wiki is a good place to collect the examples and document them. Discussion can then be either linked back to the Forum (as is already done in some cases) or held on the Discussion page assuming there's an Overview page which lists them all with links to each one on its own page. Yes, it sounds like work :) I could help.I definitely appreciate the offer to help, particularly considering that I'm not particularly good at structuring and formatting text. I'm much better at casual explanations (like those found in forum posts. ;) )
Anyway, what you do is, of course, up to you.Thank you, my "greatest" concern is to ensure I don't disrupt the smooth operation of the forum by, for instance, "drowning" other posts.
I was thinking about this (and yes, I'm also very interested:Adding one (1) to the "interested count". :)
Of course, builiding a whole new site has its own problems too (mainly that "someone" has to maintain it ;))I just don't have the talent nor ability to format a bunch of text. My artistic abilities are at the low end of the Kelvin scale.
Adding one (1) to the "interested count". :)
I just don't have the talent nor ability to format a bunch of text. My artistic abilities are at the low end of the Kelvin scale.
Will your example include which library(kernel32.dll, user32.dll) in use?Examples include mostly, ntdll.dll, kernel32.dll, user32.dll and gdi.dll. There are examples for other dlls but those mentioned make up the great majority of them.
As maintainer of the windows api headers, count me in too.good :)
What you want to share, I think, will be useful to many. But on the forum, if this topic / thread is lost. And it won't be very good ...My "plan" is to name each post "Win API - api name", this way if someone uses the forum search engine, they will always be able to find it even if no one has updated it in a long time (there is only so much that can be said about any one API function.)
The topic should be periodically updated so that it is not forgotten by people. Because it can be useful and it will be in a few decades. :)
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!
Wouldn't it be better to check for WoW64.dll? If you're running on a 32-bit system that library won't exist/load and on a 64-bit system it will be always loaded into a 32-bit process already thus avoiding the need to map csrss.exe into the address space.That was my first thought too and ended up being more cumbersome than going after csrss.exe.
If the process is a 32-bit application running under 64-bit Windows 10 on ARM, the value is set to FALSE.which means that calling IsWow64Process on an ARM platform would tell the 32 bit program that it is _not_ running on a 64 bit Windows even though it is.
But I think this goes a bit far for the infinitesimally small percentage of users that still run XP 64-bit, a number that was never very big to being with.
Going after Wow64.dll, the first thing I tried was using GetModuleHandle, it failed. Tried using LoadLibrary and it also failed, most likely because a 32 bit app is not allowed to load a 64bit dll. It would work with LoadLibraryEx specifying "load as datafile" but that dll is 238K whereas csrss.exe is only 8K. Better (faster) to load the smaller one.
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.Some far-fetched reasons. First, IsWow64Process present in the original XP 64, because it was born from Windows 2003 Server (it also has this function). The 32-bit version of XP may not have this function, but the 64-bit version has always had it, from birth.
Some far-fetched reasons. First, IsWow64Process present in the original XP 64, because it was born from Windows 2003 Server (it also has this function). The 32-bit version of XP may not have this function, but the 64-bit version has always had it, from birth.Not far fetched. The fact that the 64 bit version had it from the start is useless since a 64 bit program does not need either function to determine that it is running under a 64 bit version of Windows.
Second, the process of course has read rights to its own kernel32.
So far, the level of interest does not seem to be high enough to even merit concern on how to go about it.
I'm interested for sure. I've just been busy of late, but this would be of interest to me, especially APIs dealing with physical memory and the Task Scheduler.Pleased to hear you're interested, adding one (1) to the "interested count". :)
csrss.exe isn't going to go away anytime soon and loading it as a data file requires no privileges.It fails in wine under linux (failed to determine windows installation bitness).
But I think this goes a bit far for the infinitesimally small percentage of users that still run XP 64-bit, a number that was never very big to being with.
It's not only XP, but also Windows Server 2003. It provides the API only starting from SP1.
csrss.exe isn't going to go away anytime soon
It fails in wine under linux (failed to determine windows installation bitness).Given that it's under Linux, it should be expected for the method to fail.
No but your access from some types of accounts might. Like fully ordinary user.So far, the method seems to work with "ordinary"/"limited" users. That said, it is conceivable and even likely it would fail for users in a custom and very restricted group. In that case, IsWowProcess and IsWowProcess2 would probably fail too.
Some far-fetched reasons. First, IsWow64Process present in the original XP 64, because it was born from Windows 2003 Server (it also has this function). The 32-bit version of XP may not have this function, but the 64-bit version has always had it, from birth.Not far fetched. The fact that the 64 bit version had it from the start is useless since a 64 bit program does not need either function to determine that it is running under a 64 bit version of Windows.
Second, the process of course has read rights to its own kernel32.
In addition to that, on some platforms, e.g, ARM the API returns FALSE to a 32 bit program even though it is running under a 64 bit version of Windows. MS does not say how IsWowProcess2() behaves on the ARM platform in that case but, the inevitable conclusion is that using those APIs to determine whether a 32 bit program is running under a 64 bit version of Windows is not a reliable method to make the determination.
Note that I didn't say that it is not possible to determine the O/S bitness using IsWowProcess and/or IsWowProcess2. What I state is that, making the determination using those APIs is cumbersome and, in the case of ARM, it is unreliable. To use those APIs, the programmer first has to determine if those APIs are available and, if they are, use them. To make matters worse, on an ARM processor, the result, if using IsWowProcess, will be incorrect.
And here I don't agree.We can agree to disagree. I have no problem with that.
I consider the API the more straightforward, sane and stable approach then checking some file as long as one knows the restrictions of the functions (e.g. use IsWow64Process2 if available and only then IsWow64Process).that "sane and stable approach" takes more code that is more complicated and, in the case of ARM whether or not it works is a question mark. You know that is a fact.
In theory nothing is stopping Microsoft from using some file system redirection for csrss.exe (as they do for SysWow64 already) and then your checks would be completely screwed.But there is something in _practice_ that stops MS from using file system redirection in this case which is, a 32 bit program is allowed to load a 64 bit DLL as a resource file (to either use its resources or manipulate them.) If MS were to change that, they would break all 32 bit programs that load resources from 64 bit executables. Additionally, in the case of 64 bit modules, there is only _one_ copy available in the system, there is nowhere to redirect to. The bottom line is, yes, _in theory_ they could do it, _in practice_ doing it would result in the breaking of a fair amount of code including some of their own code for no good reason. Doesn't seem a likely possibility.
Have tried that code on an ARM platform ?... how does it work there ?No, I don't have an ARM machine. This part is based on the documentation for the IsWow64Process2 function, which does not make an exception for ARM machine.
No, I don't have an ARM machine. This part is based on the documentation for the IsWow64Process2 function, which does not make an exception for ARM machine.That's a precarious thing to depend on because the documentation for IsWowProcess does _not_ state that on an ARM machine, IsWowProcess2 should be used instead.
Unless you test it on an ARM machine, I wouldn't trust the code you provided to work on that platform. Succinctly, without testing, you're just hoping it works (it may or may not, like you, I don't know.)Until you test your code for ARM64, I can't trust it either. Mine is at least based on official documentation, and is more likely to work.
Until you test your code for ARM64, I can't trust it either. Mine is at least based on official documentation, and is more likely to work.Your argument is reasonable but, mine will work as long as csrss.exe exists, which is rather likely. :)
No, I don't have an ARM machine. This part is based on the documentation for the IsWow64Process2 function, which does not make an exception for ARM machine.That's a precarious thing to depend on because the documentation for IsWowProcess does _not_ state that on an ARM machine, IsWowProcess2 should be used instead.
When an API, such as IsWowProcess, doesn't work in a particular case, they point the reader to the one that works, which in this case should be IsWowProcess2 but, that recommendation is notably missing.
Remarks
Applications should use IsWow64Process2 instead of IsWow64Process to determine if a process is running under WOW. IsWow64Process2 removes the ambiguity inherent to multiple WOW environments by explicitly returning both the architecture of the host and guest for a given process. Applications can use this information to reliably identify situations such as running under emulation on ARM64. To compile an application that uses this function, define _WIN32_WINNT as 0x0501 or later. For more information, see Using the Windows Headers.
Unless you test it on an ARM machine, I wouldn't trust the code you provided to work on that platform. Succinctly, without testing, you're just hoping it works (it may or may not, like you, I don't know.)
D:\fpc\git\fpctests>tiswow64-a64.exe
Machines: Process = 0000, Host = AA64
D:\fpc\git\fpctests>tiswow64-i386.exe
Machines: Process = 014C, Host = AA64
Machines: Process = 8664, Host = AA64
Machines: Process = 01C4, Host = AA64
Apparently we're not reading the same documentation (https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process#remarks) then (emphasis mine):
RemarksYou are right. My mistake. Thank you for point it out. Lesson: I should read the whole thing instead of stopping.
Applications should use IsWow64Process2 instead of IsWow64Process to determine if a process is running under WOW. IsWow64Process2 removes the ambiguity inherent to multiple WOW environments by explicitly returning both the architecture of the host and guest for a given process. Applications can use this information to reliably identify situations such as running under emulation on ARM64. To compile an application that uses this function, define _WIN32_WINNT as 0x0501 or later. For more information, see Using the Windows Headers.
This I have run on Windows on ARM64 once compiled as aarch64-win64 and once as i386-win32:Did you happen to test the method I recommend on ARM64 ? ... if the answer is yes, I'd like to know what the result was. Thank you.
This I have run on Windows on ARM64 once compiled as aarch64-win64 and once as i386-win32:Did you happen to test the method I recommend on ARM64 ? ... if the answer is yes, I'd like to know what the result was. Thank you.
I have not. Will try to fit that in some time this week.Thank you.
This I have run on Windows on ARM64 once compiled as aarch64-win64 and once as i386-win32:Did you happen to test the method I recommend on ARM64 ? ... if the answer is yes, I'd like to know what the result was. Thank you.
I have not. Will try to fit that in some time this week.
Anyway, your example seems to work. At least it shows that the Windows on ARM64 is a 64-bit one.Thank you. I appreciate your confirming that it works on other CPUs as well (ARM64 in this case.)
Running "e:\tiswow64.exe "
Machines: Process = 0000, Host = 014C
0x14c
Intel 386 or later processors and compatible processors
MACHINE_IA64
0x200
Intel Itanium processor family
MACHINE_ARM64
0xaa64
ARM64 little endian
MACHINE_AMD64
0x8664
x64
Is there any other list?
I ran TISWOW64.pas on my machine and get:It's one thing to determine the CPU Windows is running under and another thing to determine if a program is running under Wow64. The presence of a 64 bit CPU does not imply that a 64 bit O/S is installed.QuoteRunning "e:\tiswow64.exe "
Machines: Process = 0000, Host = 014C
Difficult to say without knowing which list you're looking to, but the one for Image File Machine Constants (https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants) (as returned by e,g, IsWow64Process2) contains the following Intel-related constants:Note that while in your list MACHINE_IA64 is taken to mean Itanium family, in this one it's used for any Intel IA64 processor.
IMAGE_FILE_MACHINE_I386 = 0x014c = Intel 386 IMAGE_FILE_MACHINE_IA64 = 0x0200 = Intel 64
It's one thing to determine the CPU Windows is running under and another thing to determine if a program is running under Wow64. The presence of a 64 bit CPU does not imply that a 64 bit O/S is installed.
......The intel/AMD 64 bit CPUs are identified as an IMAGE_FILE_MACHINE_AMD64.
It's also important to note that depending on the API used, Windows may report different results. For instance, if a 32 bit program uses GetSystemInfo on a 64 bit processor (and running under Wow64), Windows will report the processor architecture as being PROCESSOR_ARCHITECTURE_INTEL and processor type as PROCESSOR_INTEL_PENTIUM (which is a 32 bit processor), whereas a 32 bit program that uses GetNativeSystemInfo will return a processor architecture of PROCESSOR_ARCHITECTURE_AMD64 and a processor type of PROCESSOR_AMD_8664.
For some reason, MS explicitly discourages using GetNativeSystemInfo to determine if a program is running under Wow64. The reason why is still unclear.
Then I think Process is the Windows and Host is the CPU?The "process" is the container Windows creates to run an executable. The process' bitness is always determined by the bitness of the executale. IOW, a 32 bit executable runs in a 32 bit process and a 64 bit executable in a 64 bit process.
This is an additional information. I am not sure how .NET detects Windows bitness although I believe there is a simpler way (than IsWow64)?I have no idea how .NET goes about detecting the Windows bitness. Based on MS' documentation, I would guess it uses the APIs IsWow64Process(2) but, personally, I prefer checking csrss.exe's bitness because that eliminates the possibility that an API may lie to the program (which some Windows APIs seem a bit too fond of doing and seems to be quite acceptable to MS in general.)
I ran TISWOW64.pas on my machine and get:QuoteRunning "e:\tiswow64.exe "
Machines: Process = 0000, Host = 014C
From MS docs, I found 0x014C is:Quote0x14c
Intel 386 or later processors and compatible processors
Then I think Process is the Windows and Host is the CPU?
GetSystemWow64DirectoryA
Retrieves the path of the system directory used by WOW64. This directory is not present on 32-bit Windows.
I have modified the previous TIsWow64Process.pas with this one. Please help to rectify it if not correct.. :PInteresting idea. Only you forgot to allocate memory for the buffer.
I just need to replace plus sign with comma on my FPC 3.2.0:
Writeln('64-bit ', Buffer)
Have you tested it? Not sure what is the result if running on 64-bit Windows (both ARM64 and AMD64).
64-bit C:\WINDOWS\SysWOW64
Just an observation, you probably don't need to GetProcAddress the function since it is implemented in Windows XP and above......
Tested on 64 bit Windows and 32 bit Windows XP, not tested on any ARM cpu..
You need to compile with {$H+}.
The output is the following on both x86_64 and aarch64:Code: [Select]64-bit C:\WINDOWS\SysWOW64
Please note however that you can not detect whether you're running on Windows on ARM64 this way, only that you're running on a 64-bit system which is where IsWow64Process2 comes in if one doesn't want to parse an important PE file like csrss.exe as 440bx is doing.
public static bool Is64BitOperatingSystem { get; }
Good catch. And thanks for the testing.You're welcome.
Can I say we have third method to check for Windows Bitness? 8)The method you've proposed looks quite reasonable but, the fact that MS does not acknowledge it could be used to determine the O/S bitness creates some doubt about its reliability. The same can be said about GetNativeSystemInfo, at first glance, it would also seem to be a reasonable alternative but, given the fact that MS can muck around with either leaves open some room for discomfort.
It is intriguing if System.Runtime.dll has some access to Win32 APIs, or has direct access to the operating system? Of course this is not in the scope of this series of topic discussion.Access to the API is direct access to the O/S (at least its user mode part) and .NET most definitely has direct access to the API but, it is on the programmer's shoulders to ensure any direct access to the API doesn't violate assumptions the .NET framework makes about a .NET program.