> Either you add a compatibility hack to the OS or you drop support for that app.

It isn't really a binary choice like this in real life. This really depends on the specifics of what the breakage is. The best way is to not break the caller's expectation to begin with.

Anyway, my point is that patching on the vendor side is way more common than it would be in the days before internet updates were common.

It's still common with modern operating systems. I think the bias may just be from historical blog posts talking about old events than newer ones. The developers adding these are under NDA so they aren't going to be sharing with the world what they are doing.

You are right that it's not a binary choice, they are others like maintaining tech debt forever or paying out of pocket to upgrade people's apps. But it's common for those to not be viable options and operating systems need to keep evolving forward.

The reality that Microsoft discovered decades ago is that "Don't break the callers expectation" doesn't work at all because the callers didn't read the manual, and had blatantly incorrect expectations!.

Windows 1.0 apps that properly follow all the documented caveats still work, often without anything more than the compatibility hacks to emulate "Windows 3" or similar.

But even back in the 90s, Microsoft found that devs would do things that the documentation explicitly said would break things, and ship it as is.

Things like copy/pasting the code the manual said, in big bold letters, DO NOT DO THIS

Most popular computer games in the 90s did things like "try to allocate all virtual memory and crash if that's possible" and "turn off interrupts globally" despite being written against virtual driver systems that were meant to cooperatively manage interrupts!

>https://ptgmedia.pearsoncmg.com/images/9780321440303/samplec...

"How to ensure your Program does not run on Windows 95"

Don't think that I'm naïve about this. In the 2000s I was on the Windows team. I didn't work on app compat but sometimes when I was bored in the office I would read the app compat shims.

The most memorable example of a bad behavior that I recall was a 90s video game. It used the area beyond the stack pointer as some kind of bonus storage area. It worked by coincidence because in 9x, every kernel32 call trapped directly into the kernel and would swap your stack. Suddenly NT's Win32 support sometimes involves bigger user space wrappers to ntdll. FindFirstFile was one. NT's kernel32 needed a lot of stack space to call NtQueryDirectoryFile and copy it over to a WIN32_FIND_DATA. The game's data structures got clobbered. So there was a shim that would swap the stack pointer before doing this.

Even still ... There's something in this thread that I think is missing about all this. You don't need to litter your code base with "if (!strcmp(exename, "SIMCITY.EXE"))"... I did see examples here and there of that sort of thing in the Windows code base, but mostly, that is not how this stuff actually works.

Further, I don't think the Win3.1 era is a fair comparison at all. There was no protection between processes then and it was standard practice to bypass the operating system. By Windows 95, this was starting to be less and less the case.