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):
- File Type Association: When a user interacted with
a file (for example, a
.txtfile), Explorer queriedHKCR\.txtto find its associated ProgID (such astxtfile). - Shell Extension Handlers: Explorer then inspected
the
shellexsubkey under the ProgID or generic classes (such asHKCR\*\shellexorHKCR\Folder\shellex). - Handler Types: Specific subkeys represented
different extension types, including
ContextMenuHandlers,PropertySheetHandlers,CopyHookHandlers, andDragDropHandlers. - 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:
- Calling
CoCreateInstance: Explorer invoked COM API functions (primarilyCoCreateInstanceorCoGetClassObject) using the target CLSID. - Loading into Address Space: The COM subsystem
called the Win32
LoadLibraryAPI to map the extension DLL directly into theexplorer.exeprocess space. - Initialization via
IShellExtInit: Most file-specific handlers were required to implement theIShellExtInitinterface. Explorer calledIShellExtInit::Initialize, passing anIDataObjectpointer containing the list of files or folders selected by the user. - 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 theIPersistFile::Loadmethod.
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, orIContextMenu3. It calledQueryContextMenuto let the DLL inject custom menu verbs, followed byGetCommandStringfor status bar help text, and finallyInvokeCommandif the user clicked the extension's menu item. - Custom Icons: Explorer queried
IExtractIconto determine custom icons or overlay badges dynamically based on file contents. - Property Pages: Explorer queried
IShellPropSheetExtto append new tabs to the file properties dialog viaAddPages. - 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.