How Windows 98 Explorer Processed Shell Extensions

In Microsoft Windows 98, shell extensions were dynamic-link libraries (DLLs) that integrated into the operating system to extend the functionality of the Windows Explorer graphical interface. Windows Explorer handled these extensions by utilizing the Component Object Model (COM) architecture, dynamically loading third-party or system DLLs into its own virtual address space (explorer.exe). This article explains the exact technical flow Windows 98 used to discover, load, and execute shell extensions, along with the implications of hosting these extensions inside the primary desktop process.

The Component Object Model (COM) Architecture

Shell extensions in Windows 98 were implemented as COM in-process servers. Unlike standalone executables, an in-process server is compiled as a 32-bit DLL that runs inside the memory space of the calling application. Windows Explorer acted as the COM client, while the extensions acted as the servers providing implementations of standardized COM interfaces.

Discovery via the Windows Registry

Before Explorer could interact with a shell extension, it had to query the Windows Registry to determine which extensions applied to specific file types, folders, or system objects.

The registry lookup followed a defined hierarchy under HKEY_CLASSES_ROOT (HKCR):

  1. File Type Association: When a user interacted with a file (for example, a .txt file), Explorer queried HKCR\.txt to find its associated ProgID (such as txtfile).
  2. Shell Extension Handlers: Explorer then inspected the shellex subkey under the ProgID or generic classes (such as HKCR\*\shellex or HKCR\Folder\shellex).
  3. Handler Types: Specific subkeys represented different extension types, including ContextMenuHandlers, PropertySheetHandlers, CopyHookHandlers, and DragDropHandlers.
  4. Class Identifier (CLSID): The values inside these subkeys contained Globally Unique Identifiers (GUIDs) pointing to HKCR\CLSID\{GUID}\InProcServer32, which defined the exact filesystem path to the extension's DLL and its threading model.

Initialization and Loading Flow

Once Explorer identified the required CLSID for an interaction, it initiated a multi-step loading sequence:

  1. Calling CoCreateInstance: Explorer invoked COM API functions (primarily CoCreateInstance or CoGetClassObject) using the target CLSID.
  2. Loading into Address Space: The COM subsystem called the Win32 LoadLibrary API to map the extension DLL directly into the explorer.exe process space.
  3. Initialization via IShellExtInit: Most file-specific handlers were required to implement the IShellExtInit interface. Explorer called IShellExtInit::Initialize, passing an IDataObject pointer containing the list of files or folders selected by the user.
  4. Alternative Initialization via IPersistFile: For handlers operating on a single file rather than a multi-selection (such as icon handlers), Explorer instead initialized the object via the IPersistFile::Load method.

Interface Querying and Execution

After successful initialization, Explorer queried the extension for specific interfaces using COM's QueryInterface method. The requested interface depended directly on the user's action:

  • Context Menus: Explorer requested IContextMenu, IContextMenu2, or IContextMenu3. It called QueryContextMenu to let the DLL inject custom menu verbs, followed by GetCommandString for status bar help text, and finally InvokeCommand if the user clicked the extension's menu item.
  • Custom Icons: Explorer queried IExtractIcon to determine custom icons or overlay badges dynamically based on file contents.
  • Property Pages: Explorer queried IShellPropSheetExt to append new tabs to the file properties dialog via AddPages.
  • Namespace Extensions: For virtual folders (like Network Neighborhood or custom devices), the extension implemented IShellFolder, allowing Explorer to browse non-filesystem hierarchies as if they were physical directories.

Stability and Execution Context

Because Windows 98 lacked process isolation between explorer.exe and its loaded shell extensions, all extension code executed with the same privileges and in the same memory space as the desktop environment.

A null-pointer dereference, infinite loop, or memory corruption inside a third-party extension DLL directly affected explorer.exe. In Windows 98, this architecture frequently led to the termination of the desktop and taskbar, forcing Explorer to crash or restart entirely. Memory allocated by poorly written shell extensions also contributed directly to the degradation of GDI and user system resources during extended operating system runtimes.