How to ensure that your program does not run under Windows 95 (1995) [pdf]
ptgmedia.pearsoncmg.com
ptgmedia.pearsoncmg.com
> Sometime after Windows 95 shipped and became a smash hit, a group of prominent game developers visited Microsoft as guests of the DirectX team. At some point, they learned of “this guy” on the Windows 95 team who worked so hard at getting all their games to work that he “officially went insane.” Thus intrigued, they asked to be introduced to this insane guy, and they presented me with a letter, signed by all of them, with the message, “Thanks for going insane.”
> I still have that letter.
This made me curious, so I did a bit of digging, and found https://docs.microsoft.com/en-us/windows/win32/memory/physic... (quoted out of order for simplicity):
> Windows automatically enables PAE if DEP is enabled on a computer that supports hardware-enabled DEP, or if the computer is configured for hot-add memory devices in memory ranges beyond 4 GB. If the computer does not support hardware-enabled DEP or is not configured for hot-add memory devices in memory ranges beyond 4 GB, PAE must be explicitly enabled.
> PAE does not change the amount of virtual address space available to a process. Each process running in 32-bit Windows is still limited to a 4 GB virtual address space.
So, TL;DR, what you said :). But I'm glad I checked!
Unfortunately, PAE on Windows is a sad story. Unlike what the knowledge base said, in practice, you cannot use PAE for this purpose on Windows. Officially, PAE is only supported on Windows Server, and unusable on desktops.
Technically it's supported and almost always activated by Windows (since PAE is needed for the NX bit / DEP). But on desktop systems, Microsoft intentionally crippled PAE by locking the maximum memory to 4 GiB by a software license restriction [0]. Microsoft didn't do it because it wanted to force you to buy licenses, but due to compatibility problems, especially, all types of device drivers are problematic. Using more memory requires patching the kernel to bypass this license restriction, with unpredictable consequences due to incompatibilities.
TL;DR: PAE on Windows is practically useless.
[0] https://en.wikipedia.org/wiki/Physical_Address_Extension#Mic...
* PAE is technically enabled on most machines, but only for side effects like DEP, and there's a software lock on using more than 4GB memory.
* Via either spending lots of money or patching some files, you can get a 32-bit version of windows to use 64GB of memory. As long as your drivers don't explode.
* "4GB virtual address space" is a bit misleading. A normal 32-bit process can only use 2GB on 32-bit windows. (or 3GB if you change some settings) The upper part of the address space has to be reserved for the kernel. If you want the entire 4GB for your process, you have to run it on 64-bit windows.
As long as you can make it work, getting windows to recognize more memory despite per-process caps is a massive improvement and "limited to 4GB RAM" really undersells it.
Some examples are
https://i.imgur.com/r5aQNyJ.png - Smalltalk Express
https://i.imgur.com/W9ES2fg.png - Delphi 1
https://i.imgur.com/VLSglAK.png - Windows 1.0 port of WineMine
https://i.imgur.com/OLq2gLm.jpg - The Exile series of RPGs
https://i.imgur.com/e26mqWP.png - MicroLathe (though that one does a segfault every time it renders... but it catches it and allows continuing use of the program)
While these programs are fun to play around with (especially Smalltalk Express), another use for this is to run the setup of older (32bit) applications that used a 16bit stub (Microsoft does have a few replacement stubs for some very popular installers but there are many other - and other versions - that are not there... and funny enough, AFAIK this project relies on the code Microsoft added to check for 16bit installers to run any 16bit program :-P).
OS/360 would like a word...
;)
(to be honest going from DOS to Windows is a different problem, though that doesn't justify the atrocities shown in the document :) )
But from what little I remember from my intro-to-mainframes day at big blue many years ago, I think it's like some sort of multi-layered emulation now, to run code that's that old. But your "Hello World" program built on OS/360 released in 1964 will still run on modern Z/OS, or so I'm told.
Of course they're not desktop systems! (I'd hate to see the desk...)
But no, as I said below, I'd hate to see the desk!
> Example 36: One program deserves a special award for the code that gets executed when you save a large scenario. It frees a data page, then allocates and frees bunches of more memory, and then a while later, goes back and touches the data page that it freed a long time ago.
> (Ironically, after writing this program, the author came to work for Microsoft on the Windows 95 team! When he learned that the application compatibility team had discovered and worked around his bug, he apologized to me in person.)
Some weren't directly Microsoft's fault. I remember there was a printer driver that would change the current directory of processes that it wasn't even being used in. I had to update the media code in the game to use absolute paths.
It often felt like I was being paid by my company to work for Microsoft, which felt very clever of Microsoft at the time!
Windows works because everyone, at Microsoft and outside, put in a lot of work to make it work.
Maybe that’s a general property of platforms and operating systems, it would explain why people get so attached to them.
The second appendix is titled "Tales of Application Compatibility" http://ptgmedia.pearsoncmg.com/images/9780321440303/samplech...
1. The more confusing the error message, the better.
2. If it doesn’t run under Windows, then it’s Windows’fault.
3. Detect Windows, and crash.
4. Manuals are a waste of time.
5. Words in boldface don’t count.
6. Just because you’re a Windows application doesn’t mean that you have to be compatible with Windows.
7. Performance degradation is acceptable in the greater interest of not running on Windows 95.
8. If you’re going to do something wrong, do it wrong in as many different ways as possible.
9. Find a rule and break it as blatantly as possible.
10. The weirder your code, the harder it will be for the operating system to detect that you are about to do something stupid and rescue you.
11. Always look for the weirdest, most convoluted way of doing something. That way, you stand a good chance of doing it wrong.
12. It is better to be lucky than good.
13. Multitasking is for wimps.
14. Persistence may not help, but it’s fun.
15. Thrashing is good. It reminds the user that the computer is on.
16. Random addresses are harmless.
17. If you’re going to fail, do so as subtly as possible.
18. Do something that is supported only under Windows, and do it wrong.
19. Second-guess the specification whenever possible.
20. Knowledge of the English language is optional.
21. Well-behaved programs are for wimps.
22. Bite the hand that feeds you.
23. Words in italics don’t count.
24. If you can’t be subtle, then be blatant.
25. Intel will never release a new CPU.
26. Slower is better.
27. If you can’t convince the operating system to screw you up, take matters into your own hands.
28. Microsoft will never release a new version of the operating system.
29. The high words of 32-bit registers are always zero.
30. Even business applications can benefit from a boot disk.
31. Error checking is for wimps.
32. Don’t bother testing the error paths. The game is already over.
33. When faced with the unusual, self-destruct.
After a certain Windows release, Microsoft had a Windows App Certification checklist of features you had to use if you wanted various levels of support, or sales to brick and mortar stores (they required that to reduce support calls and returns.)
At first I found the checklists irritating, as they required essentially a major application release for each Windows version - your application bit-rotted essentially.
But in the end, it was worth it as the application was more polished, with standardized paths, help, etc.
Makes me wonder if Windows 95 should have just rebooted into DOS for older games. Alt-tab was always sketchy anyway when a have was running.
And the preceding example is just hilarious. But hey "it works on my machine! it must be your fault!!11"
It was similar shenanigans when a lot of Windows 95/98 "stopped working" when Windows 2000/XP worked. "What do you mean I can't write to C:/Windows whenever I want? What do you mean I can't put my config option in some hidden corner of the system registry?"
sigh
This one is more hilarious.
pushf
cli
... five instructions later ...
popf ; BUG! Does not enable interrupts
> What makes this noteworthy is not that it contains exactly the forbidden code sequence, it is noteworthy because this is not an MS-DOS application but rather a Windows application. It’s a Windows application doing something that doesn’t work under Windows. That takes nerves. A certain network driver does essentially the same thing.And,
> Maxim 18: Do something that is supported only under Windows, and do it wrong.
> Memory lock calls are ignored in the absence of virtual memory, so make sure to abuse lock functions as much as possible. That way, when you are run in a virtual memory environment, strange and wondrous things start happening that never happened in real mode.
> Since none of the standard DOS extenders use virtual memory by default, this is an excellent opportunity to begin behaving randomly. This is so important it’s worth restating.
What I find ironic is that while some people go on and on about gatekeeping programming and "you're not a real programmer if..." some people are just doing that kind of thing (and they're usually the ones making more money)
I was satisified when I found out that Vista, amongst the many things it did wrong, did something right: started naming programs that were misbehaving (for example, taking too long to shutdown)
Nevermind the fact that if you really want to touch another process's memory there IS a way to do it...
Really odd to see those things "out there"!
In real mode, the interrupt enable/disable status is controlled by the global CPU flag, in bit 9. If you saved the entire FLAGS register when interrupt was enabled with "pushf", and later you use "popf" to restore the flags, there's no reason to use "sti", since the interrupt bit was already restored, it was perfectly legal in real-mode DOS. However, in protected mode under an OS, it's unacceptable for a single program to disable interrupts of the entire CPU, so the global CPU interrupt flag is always enabled and controlled by the OS, but each program had its own virtual interrupt state controlled by "sti" and "cli", and cannot be changed by "pushf" and "popf" anymore.
What actually happened: This problem was already recognized in the beginning, documentation contains multiple warnings and examples of correct code, but developers ignored all the warnings and instructions, continued misusing "popf" and doing it wrong in as many different ways as possible.
I've also not written any asm in a couple decades...
so, thank you very much for explaining this to me. It makes total sense now!
It would be amusing to think that developers would have to take extra steps to ensure their program does not in fact run on older windows versions.