Date: | February 1, 2005 / year-entry #28 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050201-00/?p=36553 |
Comments: | 46 |
Summary: | To detect programmatically whether your 32-bit program is running on 64-bit Windows, you can use the IsWow64Process function. Do not do as some people do and hard-code the list of 64-bit processors. You'd think that after the hard-coded list of 64-bit processors changed the first time (when x64 was added to ia64), people would have... |
To detect programmatically whether your 32-bit program is running on 64-bit Windows, you can use the IsWow64Process function. Do not do as some people do and hard-code the list of 64-bit processors. You'd think that after the hard-coded list of 64-bit processors changed the first time (when x64 was added to ia64), people would have learned their lesson. But how do you detect programmatically from your 64-bit process whether you are running on 64-bit Windows? Easy. BOOL Is64BitProcessRunningOn64BitWindows() { return TRUE; } The fact that your 64-bit program is running at all means that you are running on 64-bit Windows! If it were a 32-bit machine, your program wouldn't be able to run. It's like asking the question, "Is the power on?" If there were no power, your program wouldn't be able to ask the question. Of course, if you want a single source code base that can be compiled both as a 32-bit program and as a 64-bit program, you have a tiny amount of work to do. BOOL Is64BitWindows() { #if defined(_WIN64) return TRUE; // 64-bit programs run only on Win64 #elif defined(_WIN32) // 32-bit programs run on both 32-bit and 64-bit Windows // so must sniff BOOL f64 = FALSE; return IsWow64Process(GetCurrentProcess(), &f64) && f64; #else return FALSE; // Win64 does not support Win16 #endif } I threw in a branch for 16-bit programs if you're crazy enough to be still writing 16-bit Windows programs. |
Comments (46)
Comments are closed. |
I noticed yesterday the reason codes for the InitiateSystemShutdown (and ExitWindowsEx, SHUTDOWN.EXE etc… ) there is this code:
SHTDN_REASON_MINOR_CORDUNPLUGGED
umm, if the code is unplugged how does any process get the chance to use this flag??
Maybe some type of UPS? I dunno, but I thought it was somewhat funny.
I suggest this one:
SHTDN_REASON_MINOR_CRUSHEDBY_50TON_WEIGHT
Oops, my point about the shutdown code above was in reference to Raymond’s comment about "asking if the power is on?"!
Not sure if I made that clear!!
IsWow64Process is unsupported on Windows 9x/ME/NT4/2000, so don’t forget to link dynamically.
SHTDN_REASON_MINOR_CORDUNPLUGGED might also be the reason code used when "Power failure (cord unplugged)" is selected as the reason for an unexpected shutdown. There’s also "Power failure (environmental)".
Just imagine if Win16 had included a function called something like GetSystemWordSize(). When Win95 came out, half-a-dozen crucial widely-distributed 16-bit apps would have promptly broken because this function was now returning 32. And a dozen more Win32 apps when it went to 64…
My hands down favorite weird code is the IRQL in Windows kernel mode: POWER_LEVEL. It’s set way up at 30 (with only one more level above it). Masks pretty much all hardware IRQs.
I really wonder what can trigger that IRQ, and what goes on when it does in fact get raised.
Of course, having a other things to do, I’ve never actually investigated.
Anyone care to shed some light on the issue?
Ah, but then what happens if the server is crushed by a 51-ton weight? I suggest a whole new field in the shutdown API to specify the exact weight that did the crushing…
The BeOS kernel (http://www.tycomsystems.com/beos/BeBook/The%20Kernel%20Kit/System.html) exports two very useful system calls:
– is_computer_on returns 1 if the computer is turned on. If the computer is not turned on, the result is undefined.
– is_computer_on_fire returns the temperature of the motherboard if the computer is currently on fire. If the computer isn’t on fire, the function returns some other value.
Out of curiosity, why would a 32-bit process care if it’s running on WOW or not? Is there special action it might have to take?
Plum –
Well, one reason would be so that you could go to your online update site, see that there’s a 64-bit version of the DLLs available for download, push them to the user, and then fixup everything to run that instead of the old 32-bit version next time they launch it.
Just an idea, mind you.
Not to brag or anything, but one of our apps still ships 32/16 thunk DLLs for interop with some 16 bit apps which our customers still use. We haven’t had to rebuild them in a while though. Luckily a couple of 16 bit apps owned by our group were finally EOL’ed last year. Even though I’m a pack rat, I’m ready to get rid of my win31 SDK manuals….
Why not use wrap something like below in the ifdefs?
No need for dynamic imports as IntPtr.Size is available on all platforms.
Too C#’ish?
public static bool IsRunningOnWin64()
{
return (IntPtr.Size == 8);
}
–jeroen
Ah, but that version erroneously returns TRUE for a 32-bit program running on 64-bit Windows under the emulator.
In response to Windows running on laptops. Ummm, are you sure!?!? ;)
The full use to that "cord unplugged" flag is: SHTDN_REASON_MAJOR_POWER (combined with) | SHTDN_REASON_MINOR_CORDUNPLUGGED.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/system_shutdown_reason_codes.asp
If the intention was this to be used for powering off in a low battery situation (UPS, laptop) it could be worded a bit better!
Anyway the BeOS kernal calls are great! Thanks Tim!
I wonder how many computers had to be destroyed during QA of the is_computer_on_fire function…
Note that you should not call IsWow64Process directly. Use GetProcAddress if you want this code to run on 32-bit XP.
We’ve got a lot of 32-bit processes running on 64-bit Windows, but unfortunately they’re things like WSH that don’t have access to API calls such as IsWow64Process. I wish they did, though, because some of the registry and system directory fakeouts performed by the 64-bit OS causes confusion when we start launching 64-bit utilities (or use something like WMI) that are not subject to the fakeouts. At times like those, I need to know if I’m running on 64-bit Windows so I can tell my 64-bit utility and/or WMI where to look for something.
for WSH and CMD files you can check the environment variable PROCESSOR_ARCHITEW6432
Well, write a program to call IsWow64Process() for you and call that through WMI.
"Is the power on ?"
Why nope ?
http://msdn.microsoft.com/library/en-us/power/base/getsystempowerstatus.asp
As well – there can be some kind of crazy BIOS code that will keep track of current time or Wake-on-XXX events. This code definitely requere "IsPowerOn()" method – as there can be several different "Off" states – "Soft Off" and "Mechanical Off".
http://msdn.microsoft.com/library/en-us/power/base/system_power_states.asp
Never trust in common logic. Always read documentation ;-)
"The full use to that "cord unplugged" flag is: SHTDN_REASON_MAJOR_POWER (combined with) | SHTDN_REASON_MINOR_CORDUNPLUGGED.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/system_shutdown_reason_codes.asp
If the intention was this to be used for powering off in a low battery situation (UPS, laptop) it could be worded a bit better!"
The intention is to prompt the first administrator that logs onto the server after it comes up for the reason that the server was unexpectedly shutdown [how does it know the shutdown was unexpected? by using a heartbeat service]. In this scenario, it’s perfectly reasonable for the [sheepish] administrator to say it was because the cord was unplugged. I suspect that the reason the "reason code" is available for an API initiating a shutdown is just to have all the reason codes listed, even if it doesn’t make sense to say: "I’m trying to shutdown because the cord is about to be unplugged." I would think that the reason code for power failure (environment) would be more likely to be used for UPS/laptop shutdowns than "cord unplugged."
This was asked earlier in the thread but noone replied:
BOOL Is64BitProcessRunningOn64BitWindows()
{
return TRUE;
}
Will there never be such a thing as 128 bit windows?
You’re asking people to predict the future; no surprise nobody has taken you up on it.
Besides, even if your program detected 128-bit Windows, what can you do in response? Are you going to start passing undefined flags in the hopes that one of them suddenly means something on 128-bit Windows?
Yes, it’s the purpose of the emulator, but some people want to know that they are running inside an x86 emulator (for example, maybe they want to pass the REG_WOW64_64KEY flag to RegOpenKeyEx in order to open the 64-bit registry) – that’s the purpose of this exercise.
Hiya. Can someone explain the &f64 and f64 literals/variables/constants in the code snippet in the initial post?
I don’t have access the API or docs from where i am, and google isn’t helping.
thanks
ah, i see now. i was just being a fool and missing the declation of f64 as a local var in the function. (kinda hard to miss, you’d think!)
a little bird (MSDN) told me you also had to check for the presence of the IsWow64Process function. another one of those migration problems we all hate.
I have one maybe simple question.
Can I run 32-bit version of Windows on 64-bit systems? Just like in the days of 80386 I can run Windows 3.1 standard mode on a 386 machine? And does it have any impact on programs running on it?
Why "wow"?
Vorn
Vorn: Windows on Windows.
Dean Harding: I’m quite sure the SX was also capable of i386 protected mode, but it had a cheaper 16-bit bus. But, I think the original 386s of all flavors (where I think the DX was introduced first) had some bugs that made them impossible to use in that mode, after all.
wow means "Windows on Windows" afaik. 32bit windows uses wow to run 16bit code on 32bit windows, and 64bit windows uses wow to run 32bit code on 64bit windows. I could be wrong but its kinda like an emulator for the 32bit subsystem on the 64bit operating system.
Raymond wrote:
> You’re asking people to predict the future; no surprise nobody has taken you up on it.
This is not what I initially asked. My original question was:
Is it already known that there will be no Win128 within foreseable future ?
Slightly different ! If the future cannot be predicted in this matter then the answer to the question is : No. And back to the problem at hand: Why then is there no Is64BitProcessRunningOn64BitWindows() API today to ensure further compatibility in non excluded future scenarios ?
What I would do with it if it existed ? I don’t know. Neither do I know what to do with IsWow64Process() today. And Simon Cooke’s suggestion remains valid for a possibly upcoming Win128 as well.
Hey, let’s just add a "RunningOnNBitWindows" function call, with "n" passed in by the process…
"n" should be the return value of RunningOnNBitWindows(), else you have to call it several times to get the "width" of the current os.
"But how do you detect programmatically from your 64-bit process whether you are running on 64-bit Windows? Easy.
BOOL Is64BitProcessRunningOn64BitWindows()
{
return TRUE;
}"
LOL! Thanks Raymond, that and your reply to the original blogger made my morning … keep em coming …
"However, Intel’s Itanium 64-bit architecture is not backwards compatible with the x86 architecture and so you can only run 64-bit Windows on it. "
Not true. Not only does it have x86 emulation performed in hardware (albeit slowly), it also has (in Win2K3SP1 and up) software emulation (which I believe does fancy tricks like profiling and essentially recompile) which runs considerably faster than the hardware support.
> Why then is there no Is64BitProcessRunningOn64BitWindows() API today?
Because until there *is* a 128-bit Windows, then knowing that you’re running on a 128-bit windows in 64-bit emulation mode is meaningless. You only ever need to know you’re a 32-bit process running on 64-bit Windows if you want to take advantage of 64-bit features (e.g. like accessing the 64-bit registry as opposed to the WoW 32-bit registry). So without an actual 128-bit platform to take advantage of, you can’t gain anything by knowing whether you’re running on it or not.
Of course, if 128-bit Windows ever does come out, then you’re going to have to modify your code to take advantage of it’s features anyway, so putting the call to Is64BitRunningOn128Bit is no problem.
CN: Yes, 80386SX was able to run 32-bit protected mode programs, including 3.1 enhanced mode provided sufficient (extended) memory. Of course, it also could execute 32-bit instructions in 16-bit program too.
80386DX was a name put back (much like Win16), originally this processor was simply 80386.
The first released steps of this chip (B1 and prior, that is before 1997-04) had a 32-bit multiply bug, but AFAIK it did not prevent to use 32-bit mode, it "just" requires to replace a 32-bit MUL with (several) 16-bit ones (remember the Pentium bug, anyone?) Of course, it was much easier to explaine the customers they should not install 32-bit softwares and let softwares use 32-bit MUL without worrying!
And a very good problem I have no definitive answer to is how to detect if you are running on a 80286 or a 80386+, if you are in protected mode and do not want/can change the illegal instruction handler (one way to have 99% certainity is to check the upper word of SGDT, it is 0xFF with 80286; but this is a possible yet unlikely value for a 80386 too).
So here again, the solution is to rely to an API, exactly as Raymond highlighted. My best candidate is the DPMI function 0400h.
Btw: Win16 is not supported within Win64/x64, even if the processor allows execution of 16-bit protected mode code in long mode. I conjectured this is because the V86 mode is not available, and far too much Win16 programs may rely on it or on similar DOS-related things (such as allocating ‘real-mode’ memory, or PSP). Any insight?
<quote>"n" should be the return value of RunningOnNBitWindows(), else you have to call it several times to get the "width" of the current os.</quote>
Yes, but at least then we can tell by the startup delay which programmers were daft enough to use it. ;-)
"0-bit? no. How about 1-bit? No, okay, maybe 2-bit?…"
It’s what you’re compiling for.