Why did every Windows 3.0 DLL have an exported function called WEP?


One of the quirks of Windows 3.0 was this function called WEP, which was exported by every DLL. And yet if you looked at every DLL, you'd see that the function did nothing but return.

What's the deal with this function that everybody has, but which does nothing?

WEP stands for Windows Exit Procedure. Starting in Windows 3.0, Windows would call a DLL's WEP function with a single boolean parameter. It called the WEP function with FALSE immediately before unloading the DLL from memory, and it called the WEP function with TRUE immediately before shutting down. Of course, the DLL's WEP function was called only once per instance, because once you're unloaded, you're not going to be around to receive the shutdown notification.

Since the WEP function was called as part of the unload or shutdown process, you were extremely limited in what you could do. The function itself had to be in a non-moveable segment, and the import entry needed to be in the resident name table. You can't call any function that might result in a call to Load­Module. You can't call into another DLL at shutdown, because the other DLL might have already run its shutdown code.

In practice, everybody just returned without doing anything.

Comments (11)
  1. So essentially it was an ancestor of DllMain? Or was it already present and this was just to cover extra cases (which I guess it’s just “unload due to Windows exiting”)?

    1. Darran Rowe says:

      There was no DllMain, the 16 bit LibMain was simpler and it wasn’t called on unload. So by the looks of it, WEP was the equivalent of DllMain with DLL_PROCESS_DETACH.

  2. xcomcmdr says:

    Was there any example of a DLL that did something, and it was justified ?

  3. Harold H20 says:

    “In practice, everybody just returned without doing anything.”

    So, what was the purpose of this function?

    1. Yukkuri says:

      Some well intentioned attempt at giving a cleanup capability I am sure

    2. Kevin says:

      It is much better to have a hook that you don’t need, than to lack a hook that you do need.

    3. Cool.Boy says:

      It seems initial intention was *noble* (to allow DLLs to do some cleanup before shutdown), as the limitations made it mostly unusable.

    4. Darran Rowe says:

      By the looks of it, it was the precursor DLL_PROCESS_DETACH part of the modern DllMain.
      From the SDK along with VC1.52, the DLL entrypoint was:
      BOOL CALLBACK LibMain(HINSTANCE hinst, UINT wDS, UINT cbHeap, DWORD unused);
      There wasn’t a DllMain as we know it.
      But even with a modern DllMain, you rarely put anything in the DLL_PROCESS_DETACH handler. It is there if you want something to happen during the DLL unload, but most of the time the defaults are good enough.

    5. Joshua says:

      Long time ago I planned on doing things like freeing icons and bitmaps there.

      The documentation for Windows 3.0 said the stack was too short to call into USER. :(

  4. Yuhong Bao says:

    Trivia: in Windows 3.0, WEP was called with a small stack. In Windows 3.1 the stack was made much larger.

    1. Yuhong Bao says:

      Thinking about it, I wonder if part of why WEP was called on a small stack was real mode Windows that was limited to 640K.

Comments are closed.

Skip to main content