Purpose |
LIBMAIN (or its synonym DLLMAIN) is an optional user-defined function called by Windows each time a DLL is loaded into, and unloaded from, memory. The PBLIBMAIN function performs a similar task to LIBMAIN, but takes no parameters. | ||||||||
Syntax |
FUNCTION { LIBMAIN | DLLMAIN } ( _ BYVAL hInstance AS DWORD, _ BYVAL lReason AS LONG, _ BYVAL lReserved AS LONG ) AS LONG
| ||||||||
Remarks |
The LIBMAIN / DLLMAIN function provides the following parameters: | ||||||||
hInstance |
The unique instance handle of the DLL. This handle is used by the calling application to identify the DLL. The instance handle value is commonly used to load resources embedded within the DLL, and to obtain the actual file name of the DLL (via the GetModuleFilename API function). In these cases, it is common to copy the hInstance value to a global variable, allowing the instance handle value to be utilized elsewhere in the DLL. | ||||||||
lReason |
This flag indicates why the DLL entry-point is being called. It can be one of the following values (as defined in WIN32API.INC):
| ||||||||
lReserved |
The lReserved parameter specifies further aspects of the DLL initialization and cleanup. If lReason is %DLL_PROCESS_ATTACH, lReserved is zero (0) for explicit (dynamic) loads and non-zero for implicit loads. If lReason is %DLL_PROCESS_DETACH, lReserved is zero if LIBMAIN has been called by using the FreeLibrary API call, and non-zero if LIBMAIN has been called during process termination. | ||||||||
Return value |
If LIBMAIN is called with %DLL_PROCESS_ATTACH, your LIBMAIN function should return a zero (0) if any part of your initialization process fails, or a one (1) if no errors were encountered. If a zero is returned, Windows will abort and unload the DLL from memory. When LIBMAIN is called with any other value than %DLL_PROCESS_ATTACH, the return value is ignored. | ||||||||
Restrictions |
Note that Windows does not guarantee that LIBMAIN will be called in a "balanced" manner. For example, a %DLL_PROCESS_ATTACH is not followed by a %DLL_THREAD_ATTACH for the primary thread. In some conditions, %DLL_THREAD_DETACH may not occur at all. Further discussion on these Windows traits are beyond the scope of this documentation; however, an excellent source of information can be found in "Win32 Programming", Rector/Newcomer, ISBN 0-201-63492-9. At the point where a DLL is loaded into memory during process startup, Windows only guarantees that the KERNEL32.DLL system library will be loaded in memory. On this basis, API calls made from within LIBMAIN must be restricted to the range of API functions present in KERNEL32.DLL, with the exception of the LoadLibrary, LoadLibraryEx, and FreeLibrary API functions. In addition, code within LIBMAIN must not call API functions in any other DLL (for example, USER32.DLL, SHELL32.DLL, ADVAPU32.DLL, GDI32.DLL, etc), because some API functions in those DLLs may attempt to load other libraries via LoadLibrary, etc. For example, never call the MessageBox API function from within LIBMAIN, nor use the related MSGBOX function or MSGBOX statement. Failure to observe these restrictions will result in Access Violation or General Protection Faults (GPFs), typically caused by the execution of code in DLLs that has yet to be initialized. | ||||||||
See also |
|||||||||
Example |
#DIM ALL #COMPILE DLL "LIBTEST.DLL" #INCLUDE "WIN32API.INC"
GLOBAL gNumOfTimes AS DWORD
FUNCTION LIBMAIN(BYVAL hInstance AS DWORD, _ BYVAL lReason AS LONG, _ BYVAL lReserved AS LONG) AS LONG
INCR gNumOfTimes
SELECT CASE AS LONG lReason
CASE %DLL_PROCESS_ATTACH ' This DLL has been mapped into the memory context of ' the calling program, and can be initialized as required. ' Here we return a non-zero LIBMAIN result to indicate success. LIBMAIN = 1 EXIT FUNCTION
CASE %DLL_PROCESS_DETACH ' This DLL is about to be unloaded EXIT FUNCTION
CASE %DLL_THREAD_ATTACH ' A [New] thread is starting (see THREADID) EXIT FUNCTION
CASE %DLL_THREAD_DETACH ' This thread is closing (see THREADID) EXIT FUNCTION
END SELECT
' Theoretically execution should never get to this point. ' However, if the DLL is being implicitly linked then return ' Zero (0) and the process (program) will fail to start ' running. For Explicit linking, returning Zero (0) will ' simply cause the LoadLibrary/LoadLibraryEx API call to fail. LIBMAIN = 0 ' Indicate failure to initialize the DLL! END FUNCTION
SUB TestIt ALIAS "TestIt" () EXPORT MSGBOX "TestIt" + $CRLF + _"gNumOfTimes =" + STR$(gNumOfTimes) END SUB |