What was the registry like in 16-bit Windows?

Commenter Niels wonders when and how the registry was introduced to 16-bit Windows and how much of it carried over to Windows 95.

The 16-bit registry was extremely simple. There were just keys, no values. The only hive was HKEY_CLASSES_ROOT. All it was used for was COM objects and file associations. The registry was stored in the REG.DAT file, and its maximum size was 64KB.

It is my recollection that the registry was introduced in Windows 3.1, but Niels says it's not in a plain vanilla install, so I guess my memory is faulty.

None of the 16-bit registry code was carried over to Windows 95. Windows 95 extended the registry into kernel mode, added support for values and non-string data types, increased the maximum registry size (though if some people are to be believed, not by enough), and added a bunch of other hives, like added the HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, and the HKEY_DYN_DATA, The old 16-bit registry code was woefully inadequate for all these new requirements (especially the kernel mode part), so it was all thrown out and a brand new registry written.

In the early days of the Windows 95 registry, the in-memory signature value to identify the data structures which represent an open registry key were four bytes which corresponded to the ASCII values for the initials of the two programmers who wrote it.

Comments (22)
  1. Anonymous says:

    regedit is in Windows For Workgroups 3.11.  Run "regedit /v" to see the "advanced" interface.  The structure of file extensions mapping to types and types containing "shellopencommand" subkeys was the same then as it is now.

  2. Anonymous says:

    There's no-one called "Niels" in the comments for that other post, so I can't find the claim that it's not in a vanilla installation of 3.1.

  3. Dan Bugglin says:

    I can confirm @laonianren's comment, last time I fooled around with WfW 3.11 regedit.exe was in there.  Didn't know about the /v switch though, I'll have to try that…

  4. So…. I don't remember… if file associations are for sure stored in WIN.INI, and maybe in the registry for newer programs…  how do file associations work?  What takes precedence?  I assume Win16 used both WIN.INI and the registry?

  5. Anonymous says:

    It was there. Incidentally, Win 3.1's regedit.exe worked on Win95 (well for some definition of worked).

  6. I suspect the registry was introduced with OLE 2.0/COM, which was only introduced after Windows 3.10, but before Windows 3.11.

  7. Anonymous says:

    @Niels: That would explain it. My Win3.1 install has OLE2 (it was a redistributable component). It is also a prerequisite for Win32s, which I have.

  8. Anonymous says:

    I kinda wish they hadn't added "values" to the registry. Keys should just have one value (plus any number of child keys). Just "key", "key's value", and "subkeys". It's confusing to keep track of "Key", "subkeys", "default value", "default value's value", "named value", and "named value's value".

    The idea of "values" seems to have been implementation detail leakage. Keys were more expensive to track than name-value pairs, since keys have ACLs and an arbitrary number of subkeys. The solution of optimizing a special-case (no ACLs, no subkeys) is just fine, but there was no need to make this solution visible at the API layer. The optimization could have simply been done for any key that had no special ACLs and no subkeys.

    Oh well, no good crying over spilt milk.

  9. Anonymous says:

    Doug, I agree. The key + values model introduces a lot of complexity that isn't really inherent in the fundamental structure.

    I also think that the registry keys (and values) should be normal files in the file system. I can see that would be impractical in the FAT days, but there are downsides to having a sub-file-system that cannot be browsed easily by Explorer or most backup utilities, and in the present I think it would be better to make NTFS support an optimization for tiny files and use the registry sub-file-system only when it must for some reason be stored on a FAT volume.

  10. Anonymous says:

    Doug, I'm going to guess that the whole point of keys having multiple values isn't a filesystem optimization, but rather a runtime optimization. For every key, you have to make a minimum of 3 system calls: call CreateKey (which creates a handle, performs an SD check, etc.), QueryValueKey, and then CloseHandle.

    The way it is now you just have to perform a single system call for each value, skipping any need to create objects, create handles, or perform security checks. It probably doesn't even have to allocate any memory or hit the disk. This may seem trivial, but recall that the registry is an integral part of system start-up, and back in 1993 the average system was a 25MHz 386 with 8MB of RAM.

  11. Anonymous says:

    @niels: That also explains why I've seen it first used by MS Office 4.3

    [Ca. 1993, we tried to clone PC installations for faster install, and found we had to update  not only INF files but also this new "registry" thing. ;-) ]

    Funny detail: that old regedit would happily export a 120kB text file, but after some 'interesting' tests we found it would only import 64k at a time.

    So we had to split the reg files into two before importing on a new machine.

  12. xpclient says:

    I like the keys+values model but just wish I could set permissions on values too, not just on keys. Because there can be many values in a key and I may want only one value to not be modified.

  13. Anonymous says:

    Don't forget Windows NT.  I am 99% sure that NT 3.1 had a similar registry system to what you see in Windows 7 today.


  14. Anonymous says:

    @xpclient: We've talked about this: blogs.msdn.com/…/9371831.aspx

  15. Anonymous says:

    Random832: You might have found it already: Niels' comment is number 10040370 in Suggestion Box 4: blogs.msdn.com/…/10040074.aspx

  16. Medinoc says:

    The "registration database" name is still plaguing us French users, because we can never decide on the right name:

    * "Le Registre" is probably the most accurate translation of "The Registry" (and the official one since circa Win98se), but it's also the French word for "the register", which sounds ambiguous to developers.

    * "La Base de Registre(s)" is unambiguous, but it's the old name.

  17. xpclient says:

    @Raphael, I know that :) but that's the technical explanation. It will give more flexibility if common sense is given some thought. One key can hold multiple values and it is not always desirable to set permissions on all of them.

  18. Anonymous says:

    If you want to fix the API, then fix the API. Add a "ReadKeyValue" API that gets the subkey value without the extra 2 API calls. That's easier than adding a whole new multi-value scheme.

  19. Anonymous says:

    2Doug RegQueryValue was such an API. But problem here is that when you access key – OS need to perform security check against DACL of key (and may also generate audit events etc) ad such check is always much slower than one bitwise AND that peformed by value-access operations when they using already opened handle and no way to make it same fast.

    Another performance issue is a parsing. Parsing string (gived key path) is also always slower than do not parsing it (and choosing from 10 value strings always faster than from 10k path elements).

    And if you think that nowadays systems much faster and we can forget about such performance issues – try to do whole registry search in regedit.

    So is same reason why we have to do CreateFile()/ReadFile()/CloseHandle() instead of single ReadFileByNameAndOffset() or even ReadFileByteByNameAndOffset()

  20. Anonymous says:

    The string parsing bit can be alleviated by allowing the paths to be relative to open keys (pseudo code alert, using dots for indent):

    ]with Registry.openKey(pathToApplicationSettings)

    ]. . with .openKey("window")

    ]. . . . MainWindow.Move .readKey("left", 0), .readKey("top", 0)

    ]. . end with

    ]. . with .openKey("display")

    ]. . . . Editor.Font.Name = .readKey("font", "Tahoma")

    ]. . . . Editor.TabIndent = .readKey("indent", 4)

    ]. . end with

    ]end with

    (Note that adding complicated branches in case a key doesn't exist or permission isn't granted is cumbersome, in most cases covering only a remote contigency, and potentially bug prone, so most applications simply use a default value. I think this is a sensible default, hence no need for error checking in the above code.)

    The performance issues of an ACL test for former ‘values’ could be avoided by making the ACL optional. If you have a parent key open and the key you request has no ACL, no test. Avoiding hitting the disk on every key read/write is also an optimisation that shouldn't affect the API.

    [Um, the registry already supports relative keys. And there is no such thing as an object with an optional ACL. You can give a key an ACL of "everybody has free and total access" but that's still an ACL. (And you still have to check if an ACL is there.) -Raymond]
  21. Anonymous says:

    Raymond, I'm pretty sure what AC meant by "has no ACL" was an ACL with an empty set of rules but the "inherit from parent" bit set.  In contrast to "NULL ACL", which gives unrestricted access to everyone, or "empty ACL", which gives permission to no-one.

    [But that doesn't save you an access check. You're still checking against the ACL of the parent. (Remember, directory traversal bypass lets you access a child object directly despite not having access on the parent.) -Raymond]
  22. Anonymous says:

    Internet Explorer 4.x and 5.x for Windows 3.1 added another registry to Windows 3.1. Any words about that?

Comments are closed.