The long and sad story of the Shell Folders key


When you are attempting to architect an operating system, backwards compatibility is one of the ones you just have to accept. But when new programs rely on app hacks designed for old programs, that makes you want to scream.

Once upon a time, in what seems like a galaxy far far away (a Windows 95 beta release known as "M3"), we documented a registry key called "Shell Folders" that programs could read to obtain the locations of various special folders like the Fonts folder or the My Documents folder.

The developers who received Windows 95 M3 Beta followed the documentation and used that key.

In the meantime, Windows 95 work continued, and we realized that a registry key was the wrong place to store this information. In part, because a lot of things (like the Control Panel) aren't disk directories so they wouldn't be expressible there. And in another part, because we had forgotten to take into account a feature of Windows NT called roaming user profiles, where your user profile can move around from place to place, so a hard-coded path in the registry is no good.

So we created the function SHGetSpecialFolderLocation, and updated the documentation to instruct developers to use this new function to obtain the locations of various special folders. The documentation on the old "Shell Folders" key was removed.

But to ease the transition from the M3 documentation to the RTM documentation, we left the old "Shell Folders" registry key around, "temporarily", but it was no longer the location where this information was kept. It was just a shadow of the "real" data stored elsewhere ("User Shell Folders").

We shipped Windows 95 RTM with this "temporary" key, because there were still a small number of programs (let's say four) that hadn't finished converting to the new SHGetSpecialFolderLocation function. But the support for this registry key was severely scaled back, so it was just barely good enough for those four programs. After all, this was just a backwards compatibility hack. All new programs should be using SHGetSpecialFolderLocation.

In other words, the "Shell Folders" key exists solely to permit four programs written in 1994 to continue running on the RTM version of Windows 95.

You can guess what happened next.

Windows 95 came out and everybody and their brother wanted to write programs for it. But reading documentation is a lot of work. So when there's some setting you want to retrieve, and you don't want to read documentation, what do you do? You search the registry! (Sound familiar? People still do this today.)

So now there were hundreds, thousands of programs which didn't call SHGetSpecialFolderLocation; they just went directly for the "Shell Folders" key. But they didn't realize that the support for "Shell Folders" was only barely enough to keep those four original programs working.

For example, did you know that if you never open your Fonts folder, and if no program ever calls SHGetSpecialFolderLocation(CSIDL_FONTS), then there will not be a "Fonts" entry in the "Shell Folders" key? That's because those entries are created only if somebody asks for them. If nobody asks for them, then they aren't created. No point setting up an app hack until it is needed.

Of course, when you're testing your program, you don't reformat your hard disk, install Windows 95 clean, then run your program. You just put your program on a Windows 95 machine that has been running for months and see what happens. And what happens is that, since at some point during all those months you opened your Font folder at least once, the "Fonts" entry exists and you are happy.

And then back in our application compatibility labs, your program gets a "Fail" grade because our lab reformats the computer before installing each application to make sure there is nothing left over from the previous program before installing the next one.

And then the core development team gets called in to figure out why this program is getting a "Fail" grade, and we find out that in fact this program, when faced with a freshly-formatted machine, never worked in the first place.

Philosophical question: If a program never worked in the first place, is it still a bug that it doesn't work today?

Now there are those of you who are licking your lips and saying, "Wow, there's this 'User Shell Folders' key that's even cooler than the 'Shell Folders' key, let me go check it out." I implore you to exercise restraint and not rely on this new key. Just use the function SHGetFolderPath, which returns the path to whatever folder you want. Let the "User Shell Folders" key rest in peace. Because in Longhorn, we're doing even more stuff with user profiles and I would personally be very upset if we had to abandon the "User Shell Folders" key as "lost to backwards compatiblity" and set up shop in a new "Real User Shell Folders" key.

I strongly suspect that of those four original programs for which the "Shell Folders" key was originally created, not a single one is still in existence today.

Comments (43)
  1. Centaur says:

    So which is worse — when they try to find out the right location the wrong way, or when they just hardcode the wrong location?

  2. Jordan Russell says:

    I have to admit, at one time I did read from the Shell Folders key directly. I think I was aware of SHGetSpecialFolderLocation but found it too clumsy to use, unaware that it didn’t simply read the values but also created them. Perhaps it would be wise to mention this in the docs for SHGetSpecialFolderLocation and friends.

  3. Catatonic says:

    I would say hardcoding the location is worse, because then it will be correct for only one language. This bit me once when I hardcoded the "Programs" folder on the start menu.

  4. Jordan Russell says:

    By the way, how did the four programs which read the "Shell Folders" key ever work, since the values in the key aren’t created until SHGetSpecialFolderLocation is called? Were a select few values pre-created when Windows was installed?

  5. KC Lemson says:

    Fascinating! I confess that as a user, I’ve long been setting the Personal/My Documents shell folders reg key to a fileshare (on my laptop). I also muck with the desktop and Favorites ones to have them point to a separate location on the drive. Unfortunately an API just doesn’t work for me. But thus far, I haven’t had a problem with it – crossing my fingers.

  6. meme says:

    The whole error was in allowing those four programs’ programmers to be lazy in the first place. That key should just be done away with since windows was still in testing anyway. Also, I’d like to point out that many developers don’t have access to documentation and have to search the registry as a last resort. At least in 1995.

  7. On my XP system, the Shell Folders key includes values for all kinds of new shell folders such as CD Burning and My Pictures. I’m curious why these are present if the registry key exists only to take care of four ancient programs.

  8. runtime says:

    Those four naughty programs were using a new feature introduced in a Windows 95 BETA. Presumably those four programs were released AFTER Windows 95 RTM. If that feature was removed before RTM, then the programs could have been fixed without breaking backwards compatibility. Sometimes Microsoft tries a little TOO hard to maintain backwards compatibility..

  9. Raymond Chen says:

    Those four programs shipped on the same day as Windows 95 RTM – they were part of the "Wow, isn’t Windows 95 so awesome, look at all these apps written for it ALREADY!" So it was important that they continue to run. I suspect that we just told them "Stick this call to SHGetSpecialFolderLocation into your setup program, and that will seed the registry key for your main program, which you don’t have time to fix before Windows 95 RTM." The fact that other registry values also get auto-generated (beyond the handful needed by those four apps) was more an artifact of the compatibility hack than a design feature.

  10. And if you’re using the Windows Installer to install your application, you shouldn’t need to call ::SHGetSpecialFolderLocation() because the Installer creates a whole slew of "standard Properties" that point to the correct location on the machine, no matter if its in the user profile that was redirected when on a Terminal Services machine or a per-machine location when installing as such.

    Per-user/per-machine stuff is tricky and using the standard APIs instead of trying to reverse engineer data out of private data stores (like the Registry) is always going to provide a better experience for the end user (especially when your app is installed on the "next OS" where it was probably never tested).

  11. Mike Dunn says:

    How about the feature that was done so one app ran on Win 95 gold? msdos.sys has some junk at the end that reads
    ;The following lines are required for compatibility with other programs
    ;Do not remove them (MSDOS.SYS needs to be >1024 bytes).
    ;xxxxxx
    and so on. That junk was added for Norton AntiVirus, which still expected msdos.sys to be executable code (like in DOS 6) and it had a hard-coded size check of >= 1K for whatever reason. If the file was smaller, NAV assumed it had been corrupted by a virus.
    We removed that size check in the following rev, but the junk comments in msdos.sys stuck around.

  12. Jordan Russell says:

    I love how Mike names names. ;)

  13. Michael Wexler says:

    Thanks, this was a fun read…

  14. Guy Gervais says:

    Since many programmers won’t take the time to search the documentation before using those registry entries, would it not make sense to add a "(ReadMe!)" key saying "Do not use these keys in your applications, see SHGetSpecialFolderLocation in the Shell API" or something to that effect?

  15. Guy Gervais says:

    Since many programmers won’t take the time to search the documentation before using those registry entries, would it not make sense to add a "(ReadMe!)" key saying "Do not use these keys in your applications, see SHGetSpecialFolderLocation in the Shell API" or something to that effect?

  16. Raymond Chen says:

    Hey, Guy, how did you get access to my ToDo list? I plan to do exactly that for Longhorn!

  17. Anonymous says:

    Huh, actually opened comments to post exactly what Guy Gervais already wrote. Raymond, your ToDo list seems to be known to everyone :-)

  18. Centaur says:

    And then someone smart finds it and starts discussing with his neighbor how Microsoft is again bloating everything :) Next week everyone starts writing small utilities to find and delete all such readmes, and they screw up their registries in the process. Or they see that some registry keys are documented and demand that for all keys, and that, as we all know, is impossible.

  19. Nekto says:

    Isn’t it better to patch regedt32 and rededit utilites just to show some more help on registry keys? Most of people will use these utils and this info will not be deleted as a key. You could even include big red sign near that keys – "Warning – deprecated!" :)

    Or may be some addition to VC++ – "scan code for deprecated fucntion calls and registry keys" wich will be turned on by default.

  20. Ken says:

    I can’t imagine why so many people opted to use the registry key other than the delightfully elegant and easy-to-use "SHGetSpecialFolderLocation" API call.

    In case you can’t tell I’m being sarcastic.

  21. GMan says:

    Well, I just installed VC++.NET. I search for shortcut (trying to find out how to read a link to see what it points to) and guess what I find

    ms-help://MS.VSCC/MS.MSDNVS/dnmgmt/html/msdn_shellnk1.htm

    The example PROVIDED BY MICROSOFT IN VC++.NET READS THE REGISTRY!!!!!

    So I guess you could say nobody is following any hacks, they are following the instructions Microsoft is STILL GIVING.

  22. Raymond Chen says:

    The page appears to have been removed from MSDN in the meantime, at least I can’t find it. I think the article you refer to is from Nancy Cluts, who did much of her work based on Windows 95 betas (back when the registry key was the valid way to get the information).

    Note that not all content on microsoft.com was tech-reviewed by the people responsible for the technology the article is about. For example, magazine articles are just magazine articles. I’ve seen magazine articles reprinted on MSDN that tell people to do the most horrible unsupported things…

  23. GMan says:

    Microsoft does a great job of having lots of documentation. Maybe if these kinds of issues effect Microsoft’s bottom line, like maybe if continuing to support that registry location costs money, then maybe it should be someone’s job to fix/remove old bad docs and articles distrubuted by ms regardless of the original author. You could setup an internal (and external?) special mail address or form where internal (and external?) people could send in fixes, revisions, corrections and MS could fix this stuff faster and make it less likely that people would continue to get bad info. It could be at the bottom of each page on MSDN (and in the offline help as well)

    Just a suggestion.

  24. Henk Devos says:

    I sympathize with you, raymond…
    This is an example of something that should not have been kept compatible.
    A good solution would have been to write a little utility that creates the registry values, and ask the 4 programmers to call this utility at setup.
    I realize how hard all this stuff is.
    But some things should absolutely be kept compatible, while some other things should not.
    As an example, i agree that the folder tasks should not be kept compatible. It’s only some bad guys like me who use this and we should live with the consequences.
    However when i hear the fixed icon indices that have been around since Win95 will change this sounds like a very bad idea to me. I know lots of developers depending on this.
    Maybe it would be a good idea to talk to some developers when trying to decide if something should be kept compatible or not.

  25. Norman Diamond says:

    Here’s an example of an application that uses a hard-coded pathname instead of calling SHGetSpecialFolderLocation(). The application is Visual Studio .Net 2003 Prerequisites. The installation program for Visual Studio .Net 2003 requires the Prequisites CD to be inserted early in the installation sequence. It creates a shortcut in the "Programs" folder in the Start Menu, with "Programs" named in English. (Fortunately the rest of Visual Studio gets shortcuts installed into the normal Programs folder with whatever name it really has in whatever language version of Windows.)

    Here are a few other examples, though less recent. Windows 98 with either W98 SP1 or an IE SP, I forgot which. Windows anything with Office 97 and an upgrade to Word 2000. Etc. These would put multiple entries in the main Start Menu itself and/or in names of folders in it. One entry would be a word written in zenkaku (full-width) katakana and one entry would be a word written in hankaku (half-width) katakana. Unlike case insensitivity, Windows has no such thing as width-insensitivity, so these installers created new entries instead of overwriting existing entries.

    ‘Course this garbage isn’t as bad as time bombs and other mass data destroyers (an example of a time bomb being Windows 95 FDISK creating overlapping logical drives on SCSI disks). But still, some of this stuff is laughable. No matter how much we read about Microsoft doing massive amounts of testing, we see that Microsoft obviously never even tested the thing once. Install an upgrade, do a reboot, what’s the first thing you do? Click on the Start Button and see this new garbage. How could anyone miss it? Obviously by never even having tested it once.

    Anyway, you want people to call SHGetSpecialFolderLocation(), you’d better start by informing your co-workers.

  26. Raymond Chen says:

    I knew about Visual Studio’s setup program, but I don’t name names as a general rule.

  27. Todor says:

    I think I’m going to have to use the registry values… The reason is that I don’t want to link to shell32.dll because it slows down my program and the shared memory that my program has access to due to this call, counts toward my program when viewed with the Windows task manager (and users will think that my program uses more memory than it actually does). So if I can avoid linking to a DLL, I do it.

  28. Raymond Chen says:

    That’s great for you but not good for the future of Windows. So next time you complain that Windows UI never changes radically: Remember, it’s because of you.

  29. Horacio Lopez says:

    It was an interesting story.

    Still, a dependency on shell32.dll is not desirable in some cases.

    What if a particular application needed a different shell other than Windows Explorer ?

  30. Raymond Chen says:

    You can still use shell32.dll if your shell isn’t explorer.exe.

  31. Homer Meyer says:

    Since this seems active, I’ll post here. I’ve got a problem that maybe you can help me with. I need to get the location of the common documents folder under Windows NT SP6. I’ve tried using SHGetSpecialFolderLocation, but that returns an error result saying that the parameter is incorrect. I assume this is talking about the CSIDL_COMMON_DOCUMENTS parameter. This code works fine under Win2k and WinXP, but I need to get it to work for WinNT.

    I noticed that the registry value for the common documents folder under "User Shell Folders" is correct for Windows NT. Would I be ok in reading the value from the registry under Windows NT? I’ll use SHGetSpecialFolderLocation normally, but make a special case for Windows NT to read from the registry.

    This is for a Windows Installer installation, but the properties that Windows Installer sets are no help here because the common documents location isn’t one of those properties.

  32. Raymond Chen says:

    This is what shfolder.dll is for – to provide support for new CSIDL values on older OSs.

  33. Homer Meyer says:

    I tried that too. It returned an error also.

  34. Homer Meyer says:

    Hmm.. what I was trying was using the shfolder.dll that is already on the WinNT system. Is it allowed for me to install a newer shfolder.dll? I’m searching for one that I can distribute on MSDN, but I haven’t found it yet.

  35. Homer Meyer says:

    Thanks.

  36. LK says:

    With a little batch script and reg.exe it’s easy to retrieve the user’s "special folders", so it’s very handy to have this information inside the registry. So I’m very happy about the programmers of these four legacy apps :-)

  37. Burt Harris says:

    One thing that’s caused me additional grief is the fact that the Shell Folders key (no matter how you access it) seems to default to putting temp files (both normal temp files, and internet temporary files) into the user’s profile. This ends up with loads of cached data of little value mixed right in with the users’ most critical documents and settings, making rational backup procedures complicated.

    Sure, you can change it indivdually, but on a machine with multiple users this ends up being a real pain, and I’ve yet to figure how to change the defult setting for new users.

  38. Raymond Chen says:

    Commenting on this article has been closed.

Comments are closed.