I wish Ford were here to explain it; he knew this stuff pretty well.
But of course we know that Win16 wasn't a real operating system anyway. Win16 programs were basically just MS-DOS programs that had access to a rudimentary GUI and some extra libraries.
I think Win16, like, the original Win16, didn't have a concept of multiple users or anything. It expects a single-user environment. When Win32 came along, it created a kind of emulation layer for the Win16 environments that segregated them into different environments.
But...
... because Win32/Win64 have a single kernel, and the way that kernel works, yadda yadda, the different Win16 environments are really only separated by the way memory gets managed, not by the functions that enable this segregation.
So, if you compromise the kernel just so, you could pretty well do heinous things within the different win16 spaces.
Now, I forget how DLLs play into all of this. It feels like there's only ever one DLL in the environment, shared by everyone else, until the last process unloads it, but then, I don't think that's quite accurate, because I recall hooking a dll in one process but not having it hooked in another. OTOH, hooking would just mean for this process, call these functions instead of the DLL functions, so maybe that still makes sense... you'd probably have to figure out how to trick the kernel into interpreting the dlls function locations or something. I forget. It's been a while since I had to know this stuff.
because Win32/Win64 have a single kernel, and the way that kernel works,yadda yadda, the different Win16 environments are really only separated by the way memory gets managed
This is as true for Linux as it is for Win16 too. It just takes more work to compromise the system, but it's definitely doable. Both with and without virtualization (easier without, of course). Escalate to root, take control of your target process by way of ptrace, and have all the fun in the world.
Or, take subtle advantage of virtio handlers to break out of your jail, ... viola! A musical instrument!
Win16, as of Windows 3.0, sat inside a VM, just as DOS VMs did. So while you could compromise KERNEL.EXE or GDI.EXE, you would only end up compromising that Win16 instance. They never used VMMs to enforce protection; but nothing fundamentally *prevented* it from happening.
The way I remember if was that Windows 3.1 was where they introduced what they called "386 Enhanced" mode, and that's where they started putting each process into a hardware-enforced VM (including legacy MS-DOS programs, which ran in the "DOS box" VM containers available on the 80386). At that point, a rogue process would throw a protection fault if it tried to access memory outside of its own address space ... at the expense of the operating system no longer being capable of running on an 80286.
I never understood why it was such a big problem for them to solve, when I ran various flavors of unix on 8086 and 80286 based machines for years without having those problems.
Memory protections were weak to nonexistent even in Windows 3.11 running in 386 Enhanced mode. Features of the 386 processor were used in order to implement virtual memory, but processes could easily write to shared state in DLL's, and I believe another Win16 process's data segment if you had the right pointer.
I believe that basically, the Win16 runtime environment was mapped onto one single 386-mode memory space. Processes in virtual DOS boxes would have had to have their own spaces, but all Win16 processes shared the same space.
All problems would have been solved (including reliably running multiple DOS programs).
So sad. Xenix would have ruled the world and no one would really have complained much about it.
Thu Jul 12 2018 18:15:29 EDT from kc5tja @ UncensoredYep, I totally agree. Xenix was a great system once. They were fools to ditch it.
Except for the filesystem...if you didn't properly shut down a Xenix system, the filesystem would unravel like a cheap sweater.