The Windows 95 Easter Egg

In this meandering article, I start from someone else’s tiny observation about the coding of a credits screen for Windows 95 and wander through some thoughts about difficulties with computer history from the 1990s and the planting of easter eggs as a tool for cultivating journalists. There’s some reverse engineering along the way.

Occasional thoughts in late 2021 about my earliest work with DOS and Windows have sometimes got me looking on the Internet. One page by Raymond Chen got my attention and then I remembered another and soon I was looking for more of Raymond’s writing about DOS and about the Windows that runs on DOS. Thus did I come across How to sneak the Windows 95 credits screen into the build without anyone noticing. I doubt Raymond intended it as any more than a passing amusement with an oblique perspective for a bit of fun. Still, it’s dated 24th August 2021 but is about something from as long ago as 1995—and it’s not without novelty and substance. Indeed, with Raymond’s wealth of experience, there’s inevitably more substance in this slight piece than in many larger pages that the Internet has yet turned up for me about retro-computing.

Two points stuck out for me. One was technical, the other personal. First, the technical essence of the article looked to me as if it’s not exactly true:

The code for the credits is the only code in the Windows 95 shell that was written in C++. Aside from a small amount of assembly language, everything else is in C.

That it’s close to true—and even very close to true—was not in doubt for a moment. I remember from my own explorations of the Windows Shell many years ago that large amounts of the code were in C even as late as Windows Vista. Raymond, who has far more experience with real-world programmers than I ever could have (or could want), seems to perceive a wide misunderstanding that programming the Component Object Model (COM) in C “can’t be done.” To say it can may even be what Raymond intends as the serious point to his article. I don’t begin to know how any programmers could miss that Microsoft’s MIDL-generated headers for COM programming provide for COM in C, both to use COM and to implement it, but if there do exist programmers who believe that COM needs C++, then it’s nothing but good that Raymond’s there with a witty way of gently disabusing them.

And yet, for all that I know these shell DLLs were at first written nearly all in C, I couldn’t believe that the only C++ in SHELL32.DLL from Windows 95 was for a bit of fun with credits. If I wanted to make the time for a quick look, how would I find out?

For that point alone, of course, I likely never would make the time. My recent diversions into retro-computing are meant to be just that: diversions. If I do continue with them, I have no end of bigger and better things to write about, especially from concern that much of what readers of Wikipedia might take as a settled history of DOS and Windows differs from what I remember and even looks to be heavily distorted.

Of course, my own perceptions never were everyone’s. Worse, my memory never was perfect and must now be degrading rapidly. This is where the personal comes in. I couldn’t recall what this “Windows 95 credits screen” ever had been! Most likely, it never registered with me as worth remembering, if I ever knew of it at all. But Raymond didn’t recount it for people like me who hadn’t paid attention. Thus did I find myself searching even further into the Internet, at first unproductively—or reproductively, since most of what turned up were repeats of Raymond’s page—until I realised that most computer enthusiasts who ever cared enough about these Windows 95 credits to have left anything in writing would have used the term “easter egg”.

Imagine my surprise at the many links that Google turned up for “Windows 95” and “easter egg” together. Who knew there was such interest!

A Different Easter Egg

To this immediate surprise add that most of the search results were not about Raymond’s credits in SHELL32 but were instead about what was said to be a Windows 95 easter egg that has been undiscovered, hidden or secret for 25 years. The retro-computing hobbyists have got really busy, I thought. Then I started following these links. Soon my thinking changed: it’s more that journalists have got lazy.

First, this other easter egg isn’t specific to Windows 95. Second, it isn’t a recent discovery. Call it a rediscovery if you want, but it was immediately familiar to me because I had myself written about it way back in 1997.

Internet Searches

In fairness to the journalists, I too have been caught out thinking that some topic is unknown to the Internet when instead it’s just that I didn’t choose well for my searches.

The most common occasion for me to use the Internet for my work is that I’ve noticed some Windows functionality that may be worth researching but which I could as easily leave alone if others have covered the subject well enough already. A search through Google may confirm that there’s significant interest but apparently not much substance, and then the subject rises in my priorities. At the other extreme, a search may suggest that nothing remains for me except a boring trawl for overlooked detail that even I wouldn’t bother to remember. Often, a search turns up nothing and I’m left to decide by myself whether the subject should be known better or is obscure for a good reason. Sometimes, I proceed with the study and learn only later that I was not the first. (Then all I have for consolation is that I may yet have done it best.)

A stand-out example is from August 2016. My attention had somehow drifted to some apparently undocumented functions in the Windows kernel which I had started to think expose behaviour that programmers might find useful or be alarmed by but, either way, would better know about. To my way of thinking, since nobody can use any of this programmatically except by calling one or another of the functions, such as KseRegisterShim, anyone who had yet covered this ground and published their results surely would have included at least one of these functions’ names in their writing: searching for them must reveal the current state of public knowledge. Because Google then showed these names only in more or less automated lists of exported functions, I misled myself into thinking the field was fresh ground.

What I had needed to know instead was that Microsoft’s name for the feature is the Kernel Shim Engine. As far as I know, Microsoft never has documented this as the name. Evidence for it in the binary and in public symbol files is at best indirect, except for KernelShimEngineProvider as the symbolic name of the GUID for the event provider that traces what use the feature is put to. But from that and the occurrence of shim and engine here and there, especially in user mode (which has a Shim Engine DLL), you can at least suspect that the Kse in the functions’ names stands for Kernel Shim Engine. Had I searched for that, I would have learnt that Alex Ionescu had already mined the subject. Instead, his (then) recent conference presentation Abusing the NT Kernel Shim Engine hadn’t turned up in my searches for relevant functions by name because none of the presentation’s audio-visual content had yet been posted as any sort of text that Google knew how to parse and index.

Only Apparently Hidden

A sort of opposite may have affected any number of journalists who contemplated building a story out of a tweet, with video, on 26th March 2021 by someone named Albacore:

It's never too late to find easter eggs. Happened to notice what looks like a never before seen easter egg in Windows 95's / IE4's Internet Mail. You have to open its About window, select one of the files, and type MORTIMER. Names of the program's developers will start scrolling.

I stress that I mean no criticism of Albacore. I picture him—or her—looking at some old software, possibly for reasons unrelated to easter eggs, but noticing one anyway. Not recalling it from experience, reading, gossip or whatever, not finding it on any of the extant lists of easter eggs that have been compiled by enthusiasts, you’d naturally wonder whether you’ve stumbled on some small discovery. Twitter is no bad medium for bringing such a thing to attention. No claim is made. There’s even some suggestion of inviting the Twitter-verse to confirm that it’s old news or to assure that it’s not.

Of course, I may be reading into this from my own experience. My records have me looking at Internet Mail and News (though from Internet Explorer 3.02) on 19th August 1997 for the very particular purpose of seeing what its parsing of time stamps in emails might add to what I had written a month before about Microsoft’s knowledge that a different Internet Mail Misreads Time Zone. Just from preparing a disassembly, I got the unexpected diversion of an instant write-up about Credits for Internet Mail and News, which I actually did write up on 22nd August once I had dealt with my first purpose.

Back then, there was no Twitter to ask quickly whether anyone already knew of these credits. Though the newsgroups of the day might be seen as an early form of social media, I didn’t regard them as somewhere to ask questions, certainly not about something so slight, and anyway my website was still so new that I was glad to have a page to add for so little effort. Though I, like Albacore, must have wondered if blindly typing mortimer to see a scrolling list of multi-coloured credits may be news outside Microsoft, I don’t recall ever claiming it was, and I didn’t give the page enough importance to bother transferring it to this new website until March 2019 when I noticed it while looking through my own archive of the old website for some other old thing that a reader had asked about. Though the old website was discontinued in 2011, the original Credits for Internet Mail and News somehow survived all the while at a third-party archive—which is where it was cited among the replies that Albacore got on Twitter within a few days.

Diligent Fact-Checking

Now that we know which easter egg supposedly stayed hidden for 25 years, let’s think again about the journalists. Imagine you write about computer technology, much as you might have once upon a time for a printed magazine funded by a cover price and advertising, but now for a website funded by advertising and data collection. You learn of the tweet and see the possibility of fleshing it out for your website. Apparently you were not alone. Of the numerous reports, some similar to one another but many with enough variety to suggest independent writing, I pick out Windows 95 easter egg discovered after being hidden for 25 years from Bleeping Computer in part because it’s among the earliest and is referred to by many of the others, but mostly because its author, Lawrence Abrams, is pleased to call himself the site’s “Editor in Chief” (and to list Windows as an “area of expertise”). If you call yourself an Editor in Chief, you invite some expectation of journalism with diligent fact-checking.

But just what is a diligent search for concluding that an easter egg in software from 25 years ago has only just been found—indeed, for making it your headline?

As with my example, there are broadly two styles of publication to search for. Written directions might be found by searching for names: which program must you run, what must you do with it, including especially any magic incantation? Other publications may have to be searched by guessing a title or other general description because the directions are presented in sound or pictures.

The reported easter egg can only be seen by running a program that is named Internet Mail or Internet News, activating a dialog box that’s captioned “About Microsoft Internet Mail and News” but which is often described just as the program’s About dialog, selecting one of the items in the dialog’s list-view control, and blindly typing until you’ve progressed through the keys of “mortimer”. Ask Google for pages that contain all of “Internet Mail“, “about” and “mortimer”, and you’ll get Albacore’s tweet and my old page (albeit here at its new website) and a clutch of articles, including Bleeping Computer’s, about a previously unknown easter egg.

Plainly, a clutch of journalists who developed Albacore’s tweet into a story (or reworded Bleeping Computer’s) did not search Google for terms that would be needed for any written directions. At best, they searched instead for descriptions of what was found—perhaps “easter egg” in “Windows 95”, thus biasing their search to writers who thought of their topic in a very particular way. Though the term “easter egg” may be common among the sorts of users who take pride in knowing of such things, it’s not obviously universal among those who study software or even among those who write easter eggs. See, for instance, that Raymond’s note about writing a credits screen in Windows 95 never uses the term “easter egg”. To search the Internet for pages that contain “easter egg” but not for pages that contain the necessary names for revealing the easter egg is certainly not diligent. But this is to get too far ahead: much too likely is that some journalists didn’t search at all, but contented themselves just with glancing through one or two lists of the Internet’s collected knowledge of easter eggs.

So cursory a search couldn’t sensibly be counted as diligent even for something recent, but it’s arguably negligent when what’s to be found is from the early days of web browsing. For information about DOS and Windows from the 1980s and 1990s, you must expect to think carefully (and even imaginatively) about your search. For all it may seem that the world’s collected knowledge is at our fingertips to be recalled from the Internet through search engines, the reality is that very much from the 1990s has not survived—at least, not in its original form or at its original location or anywhere else that Google indexes. Websites come and go. Resources for archiving aren’t inexhaustible. Large amounts even of what Microsoft published online about its own products in the 1990s are long gone from Microsoft’s websites, and what little remains has mostly been reworked as if history began with Windows 2000, though on both these points the kindest thing to say about the reason is that it won’t have been a lack of resources.

Raymond’s Easter Egg

However obscure may have been the credits for Internet Mail and News until recent revelations on the Internet, the “Windows 95 credits screen” of Raymond’s article turns out to have been well-circulated even in the days of printed magazines. As will be examined towards the end of this article, directions for the Windows 95 credits were reported in a popular magazine whose cover date was barely two weeks after Windows 95 went on sale.

Another contrast with the credits for internet Mail and News is that the credits Raymond writes about truly are a Windows 95 easter egg. They are coded into the operating system’s shell. Neither the credits themselves nor the technique for revealing them is known in any formally released software except Windows 95.

For concreteness, it may be as well to spell out the usual directions for what Raymond means as the Windows 95 credits screen. Right-click in empty space on the desktop to get a context menu and create a new folder. It will be named initially as New Folder. Rename it three times by editing its label, completing each edit by pressing Enter. The sequence of names to pass through, each with exactly this mixture of case and punctuation (omitting the double-quotes), is:

Finally, open the folder. For your troubles, you get a repeating instrumental accompaniment to a multi-minute display of names floating left and right over a light blue background that’s vaguely suggestive of clouds.

Egg Hunting

If only to me, these two easter eggs that turned up in my Google search for “Windows 95” and “easter egg” have a bigger contrast that is specially instructive (and is our path to the technical meat you’ve been waiting for). For both, especially if your approach to one of them is that it was undiscovered for 25 years, there is the natural question of how these things ever get found by outsiders except with the help of insider knowledge. These two easter eggs are almost opposites on this question.

MAILNEWS

For the easter egg in Internet Mail and News, the answer is simply that the presence of some sort of easter egg in this program is in plain sight to anyone who looks even casually at hex dumps. Literally: the credits are plain text at the beginning of the .rdata section of MAILNEWS.DLL.

The only question from there is whether anyone who ever does think that this particular DLL is worth their time to look at will then be curious or idle enough to bother with finding how to get the easter egg revealed. For this particular easter egg, not only is its presence in plain sight but finding its trigger is also about as plain as any deduction about software’s possible behaviour ever is. The credits are addressed from only one routine which can in turn be called only from the handling of the WM_NOTIFY message by the dialog procedure for the DLL’s dialog number 1. That the routine actually does get called happens when multiple messages with the notification code LVN_KEYDOWN have progressed through a particular sequence of virtual key codes. These are defined by an array back in the .rdata section (immediately after the credits). Thus are the bytes of the magic incantation MORTIMER in plain sight too.

The dialog resource numbered 1 is titled “About Microsoft Internet Mail and News”. It has a list-view control. If you can’t at least guess from here that the trigger is to call up this dialog and then to set the keyboard focus on the list-view control and blindly type “mortimer”, then reverse engineering is not for you—or, more precisely, reverse engineering of Windows programs is not for you until you learn more of how Windows operates windows. Even if you want to dot the I and cross the T—and I, of all people, do not mean to dissuade you—then deducing the steps with certainty is again as straightforward as these things ever are. If you were marking the reverse engineering of this as a student exercise, you might give bonus points for noticing that the progression through the keys for “mortimer” doesn’t get reset if interrupted by other keys and is unaffected by the various shift keys. It works not only if you type MxoyrzTxiyMzexR but even if you close the About dialog part way through, reopen it and resume the sequence.

The serious side to the bonus points is that although an easter egg’s trigger may allow wide variation, descriptions that circulate as folklore can be curiously specific. For example, the unattributed directions in the BetaWiki page on Outlook Express are to “click in the version table on comctl32.dll and type MORTIMER while holding the SHIFT key.” Perhaps selecting this particular list-view item and typing in capitals really was necessary for some other version than I studied (or possess for study), but it’s at least possible that such directions record what someone was told about the software, not what anyone discovered from the binary. Though I, a reverse engineer, can show you that an easter egg can be discovered without insider knowledge, I cannot tell you that reverse engineering is how easter eggs first become known to outsiders—even for as simple an easter egg as this.

SHELL32

The easter egg in the Windows 95 shell works at a whole extra level of sophistication—and with the elegance of showing off features that were new for Windows 95. None of its parts are in what most would consider plain sight. Though some certainly are open to the curious, I argue below that the magic incantations that set the whole into action, roughly corresponding to the blind typing of mortimer, could never in practice be deduced by any amount of inspection. That this easter egg was ever reported publicly, especially within mere weeks of release, can have come about only through disclosure from within Microsoft.

Disguised Resource

A first tip-off to the presence of an easter egg in SHELL32.DLL from Windows 95 might be picked up by perusing the file’s resources. Among the usual accelerators, bitmaps, cursors, dialogs, icons, menus, string table and version information are RCDATA types named AVI, BIN and BYN. That the AVI resources have the form of audio-visual files would not attract a hacker’s attention. That the BIN and BYN types have only one resource each, curiously both with the same number (144), might. The BYN resource, starting with the signature MThd, has the format of a MIDI file. The BIN resource, however, fits no obvious file or data format. If you were of the mind to look for things that are out of place among the resources, then this is where you’d start.

The BIN resource has the look of something disguised. All its bytes have the high bit set. There are many occurrences of 0x95, including in pairs, and the byte that follows tends to a narrow range. It wouldn’t be at all fanciful to expect that practised cryptographers could recognise by sight that the file makes sense as plain text after an xor of every byte with 0x95. If you’re not so well-practised a cryptographer, then you can search the SHELL32.DLL binary for code that would access this resource, which it would most likely do by passing 144 and "BIN" to the FindResource function. From there you’re not far from finding—or, if you are a well-practised cryptographer, from confirming—that SHELL32 does indeed xor with 0x95 when interpreting this resource’s data.

Thus can a reverse engineer learn soon enough that the BIN resource 144 is a null-terminated sequence of null-terminated sequences of null-terminated strings, starting as

0000  50 72 65 73 65 6E 74 69-6E 67 00 00 54 68 65 20  Presenting..The 
0010  70 65 6F 70 6C 65 00 62-65 68 69 6E 64 20 74 68  people.behind th
0020  65 20 6D 61 67 69 63 00-6F 66 20 57 69 6E 64 6F  e magic.of Windo
0030  77 73 20 39 35 00 00 22-4D 69 73 73 69 6F 6E 20  ws 95.."Mission 
0040  43 6F 6E 74 72 6F 6C 22-00 00 42 72 61 64 20 53  Control"..Brad S
0050  69 6C 76 65 72 62 65 72-67 00 44 61 76 69 64 20  ilverberg.David 
0060  43 6F 6C 65 00 4A 6F 68-6E 20 4C 75 64 77 69 67  Cole.John Ludwig
0070  00 42 72 61 64 20 43 68-61 73 65 00 42 69 6C 6C  .Brad Chase.Bill

passing through Raymond Chen at offset 0x0298, and ending with what may have seemed like a cheesy sign-off

2554              53 70 65 63-69 61 6C 20 54 68 61 6E      Special Than
2560  6B 73 20 74 6F 2E 2E 2E-00 00 59 4F 55 2C 20 6F  ks to.....YOU, o
2570  75 72 20 63 75 73 74 6F-6D 65 72 73 2E 00 54 68  ur customers..Th
2580  61 6E 6B 73 20 66 6F 72-20 75 73 69 6E 67 20 57  anks for using W
2590  69 6E 64 6F 77 73 20 39-35 21 00 00 00           indows 95!...

except that we didn’t appreciate back then our good fortune of having a Microsoft that strived to give us an ever more usable user interface to an operating system that existed to support our choice of software for using our computers as things we own rather than as devices that Microsoft manages (poorly). But enough of that, lest I succumb to the nostalgic attractions of retro-computing!

Trigger

Addressing Microsoft’s customers at the end suggests that the credits were not left in the binary for Microsoft’s private purposes. They’re not like a copyright notice that’s asserted for lawyers but is never shown during use. Even if the credits’ first purpose was to be an in-joke to help with staff morale—indeed, as a surprise to be sneaked in to the code without the other programmers noticing—they were meant all along to be seen by end users too, perhaps not immediately or easily, but eventually.

But it’s one thing to know the credits are present, and are meant to be seen, another to know what magic will get them shown. Finding this is, as with MAILNEWS, an exercise in recreational reverse engineering—but a much larger one that requires much more knowledge of Windows, particularly of the Windows Shell.

Depending on how you go about it, you may find code along the way that saves the BYN resource 144 as a file named Clouds.mid in a directory specified by a registry value named MediaPath, and plays it as musical accompaniment to the credits. There’s also code that prepares the bitmap resource 144 as the visual background in the window that shows the credits. Both these uses of resources are more than incidental to the credits’ presentation but they do not themselves have anything to do with what steps a user must take to arrange that the credits are shown at all.

The routine that shows the credits executes as its own thread. The routine that creates this thread executes as the handling of message 0x8000 by the window procedure for a window class that’s named CloudedShellView. This message is posted from the same window’s handling of WM_TIMER. The timer is set soon after the window’s creation and when handling the WM_SIZE message. The only creation of the window is from the CreateViewWindow method of some (first) COM class’s IShellView interface. This COM class’s constructor can be called only from the CreateViewObject method of another (second) COM class’s IShellFolder interface. This CreateViewObject method overrides that of yet another (third) COM class’s IShellFolder interface. This last COM class is the shell’s modelling of an arbitrary file-system folder.

With this COM class, we not only connect with shell functionality that has nothing to do with the credits, but we also get to pick up some of Microsoft’s naming. Microsoft’s helpful publication of DBG files for the slightly later Windows NT 4.0 and of PDB files starting with Windows 2000 has no equivalent for WIndows 95 (as far as I ever knew), but the SHELL32 from Windows NT 4.0 is similar enough to the SHELL32 from Windows 95 that much binary code—though none that’s specific to the credits—can be matched between the two. Symbols for Windows NT 4.0 then label the matching code in Windows 95 with good confidence. For this COM class that models an arbitrary file-system folder, symbol files for later SHELL32 versions give the name CFSFolder for the C++ implementation in Windows XP and higher, and suggest it for the earlier implementation in C.

To show the credits, two conditions must be met. First, this second COM class must get instantiated instead of the basic CFSFolder. Second, this override class’s CreateViewObject method must call the first class’s constructor instead of falling through to the CreateViewObject of the basic CFSFolder.

The only circumstance in which the second COM class can be instantiated instead of the basic CFSFolder is when binding to a folder that has the specific CLSID {869DADA0-42A0-1069-A2E7-08002B30309D}. This CLSID is hard-coded in SHELL32—in a procedure that the symbol files for SHELL32 from Windows NT 4.0 name as FSBindToFSFolder—as an alternative for when the folder has a CLSID that is not in the registry as defining a folder type. This CLSID seems never to have been documented by Microsoft nor defined in any header from a programming kit. Though it does not appear in the SHELL32 binary from Windows NT 4.0, the DBG file retains the symbol CLSID_Clouds in a sequence that so closely matches the arrangement of similar data in the Windows 95 binary that I would be astonished if this was not Microsoft’s symbol for this CLSID. (The hypothesis is that it is in the DBG file because the compiler picked it up from source code that defines many GUIDs, but when the linker optimised it away as unreferenced it remained in the optimisation map as having been mapped to zero.)

There are two ways that a file-system folder can have a CLSID. The more immediately simple is to append the CLSID in string form as a file extension. For instance, create the folder as a subdirectory named Credits.{869DADA0-42A0-1069-A2E7-08002B30309D}. The other, more complex but in some sense neater, is with a “desktop.ini” file in the folder. This lets the folder keep a simple name such as Credits at the price of needing either the read-only or system attribute. The CLSID goes into the “desktop.ini” file, again in string form, as the value of a key named CLSID in a [.ShellClassInfo] section:

[.ShellClassInfo]
CLSID={869DADA0-42A0-1069-A2E7-08002B30309D}

Both techniques produce a folder whose view object will be handled by the CreateViewObject method of the override class rather than of the basic CFSFolder. But without the preparation of the second condition noted above, this method will do nothing special. It will fall back to the same method of the CFSFolder, leaving the folder’s view as just that of a basic folder. To get the view that shows the credits, a particular variable must have changed from its initial value of 0xFFFFFFFF. This can happen in two places. At one it is set to zero. This is the necessary way to get the credits started. The other place is at the exit from showing the credits: the variable marks roughly how far the showing had got, so that it can be picked up roughly this far in when the credits are next shown. Such are the bells and whistles of Raymond’s easter egg!

The one place where this keep-place variable gets set to zero is in a routine that is called only from the exported function SHFileOperationA, apparently as a special edit just for the credits. The setting to zero happens if and only if the file operation is specifically a rename and another variable is exactly 5. This other variable is a counter. It can be incremented or reset in this routine, and it can be incremented or reset in one other routine. That this other routine is ever called is apparently another special edit, in this case into the handling of LVN_ENDLABELEDITA notifications for list-view items in windows whose window class is SHELLDLL_DefView. These windows are created from the CreateViewWindow method of yet another COM class’s IShellView interface. Symbol files for later SHELL32 versions name this class’s C++ implementation as CDefView. Instances are created by the exported SHCreateShellFolderViewEx function.

For all practical purposes then, the one routine executes when a file-system object (whether a file or a directory) is renamed and the other when a list-view item in a default shell folder view is finished with getting its label renamed. For the counter to get to 5, the two routines must execute in an alternating sequence:

Counter Before Expected Occurrence Counter After
0 an item’s label is edited from name1 to name2 1
1 a file is renamed through the shell 2
2 an item’s label is edited from name2 to name3 3
3 a file is renamed through the shell 4
4 an item’s label is edited from name3 to name4 5
5 a file is renamed through the shell 0

The table shows the state changes in the expected sequence. The particular renaming that is expected for each label edit is explained some distance below, but here the old and new names that are required at each step are left as the placeholders name1 through name4. Left as understood for each transition is that an unexpected label edit or file operation resets the counter to zero, as does an edit that does not cause a rename.

Among the subtleties—or possibly oversights—in the implementation is that although each label edit is expected to cause one renaming of some file-system object, it is not necessary that all three label edits be of the same list-view item. An acceptable (though cumbersome) way to complete the sequence is to create three list-view items named name1, name2 and name3, in three separate file-system folders, even viewed concurrently through three separate Windows Explorer windows (all in the one process), and rename them to name2, name3 and name4, respectively, in this order. Another subtlety is that the sequence proceeds even if the list-view items are files not folders.

What matters about the sequence is what’s done on reaching the last step. Whatever renaming occurs as presumably the consequence of the preceding edit of a label, the routine that is specially called from SHFileOperationA changes the operation so that it proceeds as if the new name has {869DADA0-42A0-1069-A2E7-08002B30309D} appended. If indeed the renaming is of a folder, then the effect of the whole sequence is to have created a folder that has the desired CLSID. Whether the renaming was of a folder or file, it sets the keep-place variable to zero. The first view window that gets created for any folder that has the desired CLSID will show the credits from the beginning. Subsequent view windows for any such folder will show the credits but possibly starting some distance in.

Thus does the curious Windows 95 user who has some reverse-engineering skill learn the mechanism for the intended presentation of the credits. Put aside the subtle variations that perhaps were not intended. Stick instead to the simple and straightforward. Create or choose a folder that’s accessible as a list-view item in a default shell folder view. Repeatedly edit the label to proceed through a sequence of names: to name1 (if this isn’t what you started with) to name2 to name3 to name4. Open or browse the result. The shell’s view of it will be a showing of the credits.

Egg Hashing

But what are the magic names! They are not stored whole, not even disguised, not in SHELL32 and apparently not in any file supplied with Windows 95. All that the SHELL32 binary has of them are three 32-bit hashes. What’s required of the four names is that

Concatention of x and y here means that the characters of x are immediately followed by those of y, with no space or other separation. The hashing algorithm is simple but may have been invented specifically for this use:

int Hash (char const *Input)
{
    int result = 0;
    char ch;
    for (int n = 0; (ch = *Input ++) != '\0'; n ++) {
        int x = n - ch;
        result = (result << 3) ^ (result >> 0x17) ^ x ^ (x << 5) ^ (x << 11) ^ (x << 17);
    }
    return result;
}

This representation is not an attempt at reconstructing Microsoft’s source code, only at describing the algorithm: it is important to use signed arithmetic for the bytes of the input string and for the result. I leave it to cryptographers to ponder about the algorithm’s quality for hashing and about the ease of discovering collisions, but I suspect that even if finding relatively short strings for any given output is easy, finding a set of strings that meet the concatention conditions is much less so. My guess is that short solutions do exist and it would be naive to think that no enthusiasts would ever go to the effort, but with the typical computational resources of 1995 the necessary effort would have been substantial and even prohibitive. Would the following, which are the well-known solutions, ever have been discovered by inspection?

Unintended Behaviour

Even if the reverse engineer gives up at solving for the four names, do not miss that picking through the code gives working alternatives to the well-known directions and explains why some proposed alternatives are non-starters or cannot work reliably. Such alternatives acquire some interest beyond curiosity because of the later history of easter eggs. For all their value as fun, easter eggs became unacceptable as security risks. Not only does the sneaking into code of a surprise for colleagues pervert an orderly scheme of code review but there is inevitably some chance, however small, that the code allows unintended behaviour that turns out to be a nuisance for someone else’s code or even to be exploitable.

Even this Windows 95 credit screen, despite being written to a high standard, whether by Raymond himself or by others of Microsoft’s best and brightest, can be operated in ways that may have been unintended. The following alternative directions suggest some of this.

First, prepare a persistent folder for the credits. Open an MS-DOS Prompt. In Windows 95, this starts at the Windows directory. We'll create a subdirectory for the credits. Just to be different, we’ll set this up by using the “desktop.ini” technique. At the MS-DOS Prompt, run

md Credits
echo [.ShellClassInfo] > Credits\desktop.ini
echo CLSID={869DADA0-42A0-1069-A2E7-08002B30309D} >> Credits\desktop.ini
attrib +s Credits

As further demonstration of the options that the SHELL32 code allows us, possibly inadvertently, we’ll set up the renaming sequence so that we work on an empty file, not a folder. To create this file, run

rem > "Credits\empty.txt"

Assuming you haven’t yet gone through the renaming sequence, if you now Explore the Credits folder, the view you’ll get in the right pane is much like that of any other folder. Just as expected from the analysis above, you’re shown a folder that contains two files.

Whether the items in the right pane show as icons, a list or details, work through the renaming sequence. Depending on options, the “empty.txt” may show with or without the file extension. However it shows, rename it all to “New Folder" and continue through the sequence. On reaching “The Microsoft Windows 95 Product Team!”, the icon will change to that of a folder—but check at the Prompt and see that what you have is still a file, not a directory. While there, see that your renaming appended {869DADA0-42A0-1069-A2E7-08002B30309D} to the filename even though it doesn’t show in a Windows Explorer that’s configured not to hide file extensions. Back in the Windows Explorer, see that although the list-view item is presented as a folder, double-clicking it will not get you any sort of folder view. 

To get the credits, go to the Credits folder in the left pane and ask to Explore it again. This gets the shell to create a new view, which you will now see in the right pane. Though the renaming sequence didn’t make a credits folder of the file you renamed, just going through the sequence even to rename an empty file enabled the shell to show the credits in any view it now creates of any folder that has the expected CLSID, whether this folder existed before or is created later. This behaviour will persist until you exit from the Windows Explorer or restart Windows.

In Windows 95 you can easily (and cleanly) exit from the Windows Explorer by calling up the Shut Down Windows dialog from the Start Menu and holding down all three of the Ctrl, Alt and Shift keys while clicking on the No button. Restart the Windows Explorer from your MS-DOS Prompt. See that if you now Explore the Credits folder, the view you get of it is again like any other folder. Work through the renaming sequence for the empty file and your next Explore of the folder will again show you the credits.

If you want to try such things but don’t already have a computer or virtual machine that runs Windows 95, then you may find, as I did, that Microsoft Windows 95: First Retail Release is very helpful. This is an emulation that works through most web browsers. Especially welcome is that it continues to work even if you disconnect from the Internet. It was created by Jeff Parsons, who is at offset 0x0255 in the credits.

Cultivated Disclosure

The sequence of names to work through in anticipation of the credits seems to have been published first by Robert X. Cringely for the Notes From The Field column of InfoWorld, 4th September 1995, under the heading Let a million brain cells die. See how quick off the mark this was. The executables for Windows 95 are dated 11th July and the official release date was 24th August.

Two weeks later, Brian Livingston, also writing for InfoWorld but in a column named Windows Manager, referred to it under the headline Hunting for the Windows 95 Easter Egg? Here are some fun-filled shortcuts as “the most sought-after piece of trivia connected with the massive launch of the new operating system.”

Sarcasm perhaps cannot be discounted—from either writer—but at a time when computer magazines ran eagerly read columns on tips and tricks, and books on such things plausibly sold by the hundred thousand, one might be forgiven for thinking that the Windows 95 easter egg actually was a subject of anticipation. From there it’s not far to wondering whether being thrown this morsel by Microsoft was some sort of encouragement or reward—or that being overlooked for it was a subtle reminder to journalists of where their information comes from.

If so, it may be that Cringely was in and Livingston out, if only for a while at just that time. Livingston’s column reads as faintly competitive, starting as a catch-up but pleased to overtake with simpler directions from superior knowledge. What’s interesting about this is that the “fun-filled shortcuts” are incorrect. They were seized on for quick publication, having presumably been seen to work in cases that were looked at, but without much concern for whether they also work in other cases or even for whether there are other cases. Checking folklore is hard. Even programmers who might check don’t. Journalists are mostly not equipped to and anyway aren’t paid enough to. This too is a small lesson for anyone who tries now to gather a history of the early days of personal computing.

Whatever the disposition of these two particular writers to the easter egg, others certainly treated it as having wide interest. Directions were repeated even in Newsweek, a general magazine for news and current affairs, as early as 1st October 1995 by Adam Rogers in a column titled Click This. This online presentation discards the orginal context in favour of modern news and advertising. There evidently was enough newsworthiness to justify the space taken for the directions, but some element of annoyance may have been intended by the opening sentence: “Well, this didn’t take long.”

Egg Waste

As late as 11th June 1996, a question-and-answer column named User-to-User by Neil J. Rubenking for PC Magazine has an exchange about The Windows 95 Easter Egg which is there said to have “been the subject of much debate.” One strand to this debate figures in many analyses of the fad for easter eggs. As Rubenking writes: “as for those who despise the frivolous waste of resources, I checked with Microsoft to see just how much is consumed.” What Microsoft answered, as far as Rubenking reports, is:

Variables within SHELL32.DLL indicate whether the renaming ritual has been performed. These variables use a piddling 8 bytes of memory. The code that creates the credits folder is under 2K, and it resides in memory only when the credits are running. And the MIDI file that provides the background music is compressed to under 8K and stored inside SHELL32.DLL. When the Easter egg is invoked, this file is decompressed and stored as the 36K CLOUDS.MID in the Media directory below the main Windows 95 directory. You can freely delete the file, but it will be re-created if you display the Easter Egg again.

Rubenking wouldn’t be the first, even among trade journalists, to think that the only way—or at least the easiest way—to learn about Microsoft’s software is to ask Microsoft, but we might hope that a journalist of any sort could notice that what came from checking with Microsoft is not credibly complete. If nothing else, the essence of the easter egg is the credits, but although these run to many hundreds of names, and thus certainly to a few KB to compete with the “piddling 8 bytes”, the “under 2K” or even the “under 8K”, they don’t figure at all in Microsoft’s accounting.

I don’t say that my accounting which follows is comprehensive, but the definition it works from is that the overhead for the credits is all the code and data that has no other use. It’s what could be shed from SHELL32 without consequence if the credits were not implemented. Contributions are listed in increasing order of their position within the loaded SHELL32 image. The start and end of each range are respectively inclusive and non-inclusive, i.e., the range is from the start up to but not including the end.

Category Range Purpose Size in SHELL32
code 0x000035A2 to 0x000035C4
insert into FSBindToFSFolder 0x22 bytes
0x00004422 to 0x00004433
0x000044A0 to 0x000044A5
inserts into LVN_ENDLABELEDITA handling 0x16 bytes
0x000219BB to 0x000235A9 main code (possibly all in C++) ≤ 7KB (0x1BEE bytes)
0x00035C80 to 0x00035C86
insert into SHFileOperationA six bytes
0x0004CDED to 0x0004CE44
allocator of second COM class 0x57 bytes
read-only data 0x0005B9B0 to 0x0005BA84 strings and hashes 0xD4 bytes
0x000606D8 to 0x00060758 virtual function table for first COM class 0x80 bytes
0x000608F8 to 0x0006092C virtual function table for second COM class 0x34 bytes
0x000609FC to 0x00060A0C CLSID_Clouds 0x10 bytes
data 0x00062000 to 0x00062014 miscellaneous state 0x14 bytes
resources BIN 144 disguised credits ≥ 9KB (0x259D bytes)
BYN 144 Clouds.mid ≥ 36KB (0x9023 bytes)
Bitmap 144 background ≥ 5KB (0x14C6 bytes)

In listing the items of code and data at byte granularity, I do not attempt to account for alignment effects on the size of SHELL32 as a file on disk or as an image loaded into memory. The SHELL32 from Windows 95 has its sections aligned to 0x0200 bytes in the file and 0x1000 in the image. Any number of small items might be added without affecting either measure of the binary’s size. Conversely, adding even one byte can mean the loaded image is a 4KB page larger. I doubt that this explains anything of the difference between Microsoft’s accounting and mine, else Microsoft need not even have mentioned the “piddling 8 bytes” which look to me as if they must be among the 20 that I identify as miscellaneous state.

I similarly don’t attend to what (few) extra bytes must be added to the resource directory to point the way to the three resources that support presenting the credits. Rubenking’s informant at Microsoft doesn’t either, and anyway counts only one of the three resources. What can be meant by claiming that this resource “is compressed to under 8K” for storage inside SHELL32 is anyone’s guess. The whole 36KB is in plain sight in the binary at offset 0x00073AA4.

Rubenking might not have realised it or had the means ever to know, but the informant at Microsoft must have been very particular about “code that creates the credits folder”, meaning precisely this work and nothing else about showing the credits. I cannot discount that the very nearly 7KB of contiguous code for the totality of the work, such as loading and interpreting the credits, writing the MIDI file and asking other code to play it, etc., etc., is in two or more source files from which the informant selected just one for a very narrow interpretation of overhead.

Does it matter that the total space in SHELL32 for the credits is 58KB instead of the “roughly 10KB” that Rubenking was told by Microsoft? Rubenking doesn’t put a figure to the cost that “most readers expected”, but many a computer that ran Windows 95 had only the minimum 4MB of RAM. A waste in the high tens of KB would have been no small concern back then. That Microsoft so blatantly under-counted is some measure of that concern.

C/C++

It’s almost an after-thought to return to Raymond’s recollection that the only C++ code in the Windows 95 SHELL32.DLL was for the credits. Of course you will have known all along that there is other C++ code in this shell.

Immediately before the C++ code for the credits is most of an implementation in C++ of a class that implements the ISequentialStream interface. This class has wide use throughout the shell, and does not look to be used at all for the credits. The code and data that is specific to this class is at offsets:

Again, the start and end of each range are respectively inclusive and non-inclusive: the range is from the start up to but not including the end.

For the slightly later SHELL32.DLL from Windows NT 4.0, the published DBG file names this class as FileStream. Names for the methods, the constructor and destructor all have C++ decorations. The extern "C" function is named as OpenFileStream. The coding is not exactly the same—where Windows 95 uses such functions as _lopen and _lclose, Windows NT 4.0 uses CreateFileW and CloseHandle—but it is unmistakably from the same source file. This is named in the DBG file as fstream.cpp. The DBG file even gives line numbers. For instance, code for the constructor is on lines 64 to 78 inclusive. There can be no debate that the whole of this class’s code was in C++ by the time of Windows NT 4.0.

For Windows 95, only a year earlier, the balance of probabilities easily favours that it too is in C++ for the whole, but a mixed coding is not impossible. Without the constructor and destructor, nothing in the binary code would distinguish C from C++ for this implementation. Even with them, all but one of the methods could be in C. That the whole class could be in C, however, is not possible. The constructor and destructor, the OpenFileStream function (which calls the constructor) and the Release method (which calls the destructor) certainly are in C++. It’s only one small class. Even if it’s all in C++ there’s barely 1KB to it. Still, though it’s not much, it’s code that Raymond misremembered.