ID Number: Q66360
3.00 3.10
WINDOWS
docerr
Summary:
The Windows Exit Procedure (WEP) is designed to be the last function
called in the last reference to a dynamic-link library (DLL) before
the DLL is removed from memory. WEPs were introduced in version 3.0 to
allow each DLL that hooked interrupts and/or modified I/O ports to
clean up when the DLL was unloaded. Under Windows version 3.0, this
cleanup should be the WEP's only task.
In Windows version 3.0, some details regarding the WEP are not completely
documented. This article addresses issues and provides guidance for
using a WEP.
More Information:
In Windows version 3.0, the WEP is called on a Kernel stack that is too
small to process almost any Windows API call. These calls must be
avoided in the WEP. The prohibition includes calls to the global memory
routines. MS-DOS calls go through a Kernel intercept and can also
overflow the stack.
In some low memory situations, the WEP can be called before the
library initialization routine and before the library's DGROUP has
been created. WEP code that relies on the library initialization
function should verify that the initialization has been called. Also,
WEP code that relies on the DGROUP being valid needs to check for
this. The following three-step procedure is recommended for this type
of situation:
1. Verify that the DS is present by issuing a LAR instruction and
checking the present bit. This will indicate that the DS has been
loaded (the DS register will always contain a valid selector).
2. Add code in the library initialization code to set a flag in the
data segment when it is executed. Once the WEP code has verified
that the DS exists, it should test this flag to determine if the
initialization code has been run.
3. A WEP must be declared in the EXPORTS section of the DEF file for
the DLL. The following is an example declaration:
WEP @1 RESIDENTNAME
The keyword RESIDENTNAME makes the name of the function (WEP)
resident at all times. It is NOT necessary to use the ordinal
reference 1. This clarifies information presented on pages 20-25
through 20-27 of the "Microsoft Windows Software Development Kit
Guide to Programming."
When it is time for the Windows Kernel to remove the DLL, it calls the
WEP function by name. In low memory situations, it is possible for the
DLL's nonresident name table to be discarded from memory. If this
happens, the Kernel must load the table to determine if a WEP function
was declared for the DLL. Under low memory conditions, this may fail
and cause the system to FatalExit (also known as a RIP). Using the
RESIDENTNAME option forces Windows to keep the name entry for the WEP
in memory at all times that the DLL is in use.
Similarly, the WEP must be placed in a fixed code segment. If,
instead, it is placed in a discardable segment, in low memory
situations, Windows must load the WEP segment back from disk so that
the WEP function can be called before the DLL is discarded. Under
certain low memory conditions, attempting to load the segment
containing the WEP may cause the system to RIP. This would not happen
if the WEP is in a fixed segment. One word of warning, since fixed DLL
code is also page locked, keep the amount of fixed code to a minimum.
The following is the proper declaration of a WEP in a DLL:
int FAR PASCAL WEP (int iParam)
{
return 1;
}
In the "Microsoft Windows Software Development Kit Guide to
Programming," the WEP declarations in section 20.3.1 on page 20-20 and
section 20.6.3 on page 20-41 are incorrect. Change "VOID" to "int" and
each WEP procedure returns the value of 1.
If a DLL is explicitly loaded by the LoadLibrary function, its WEP will
be called when the DLL is freed, by the FreeLibrary function. If the DLL
is implicitly loaded, the WEP will be called; however, CodeView for
Windows (CVW) will indicate that the application has been terminated
before the WEP is called.
However, if an application that uses a DLL closes properly, and leaves
Windows in an unstable state, there may be a problem with the way the
WEP is declared. As stated above, the WEP should be placed in a fixed code
segment. If the WEP is discarded under low memory conditions, the
application may fail with an unrecoverable application error (UAE).
In the DEF file for the DLL, the name listed in the LIBRARY statement
must be in uppercase letters and must match the name of the DLL file.
No assumptions may be made concerning the order in which the WEPs of
dependent DLLs are called. It is unlikely to be either the order in
which the DLLs were loaded or the reverse of this. It is completely
dependent upon the order in which the DLLs usage counts go to zero.
In summary, DLLs for Windows version 3.0 require that a WEP be present.
Not providing a WEP may cause the DLL to function improperly under
certain low memory situations.
In Windows version 3.1, the WEP will be called on the stack of the
application that is terminating. This will allow the WEP access to
Windows APIs. However, it is still necessary to place the WEP in a
fixed segment.
Additional reference words: 3.00 3.10 3.x