Windows Multiple Segment DLL Skeleton Sample -------------------------------------------- Copyright (c) 1991, 1992 Microsoft Corporation. All rights reserved. Description ----------- This sample Windows program demonstrates how to create a medium model dynamic link library. Although this sample demonstrates how to implicitly load the DLL, it can be easily modified to explicitly load the DLL. This sample is composed of two parts: 1) a Windows application and 2) a multiple-segment DLL. The application works like GENERIC that comes with the Windows SDK, but features two menu items that select functions exported by the DLL. The DLL functions put up a message box to tell the user that the function belongs to the DLL. One function uses the C calling convention and the other uses the Pascal calling convention. In this sample, the DLL is composed of multiple code segments so that the functions can be placed in a moveable discardable segment and the WEP may be placed in a fixed code segment. WEPs must reside in fixed code segments so that they can always be called even when there is very little free memory. WEPs were designed to allow DLLs that hooked interrupts to unhook them before termination. WEPs were not designed for general purpose DLL clean-up. As such, in Windows 3.0, they are called off of a small stack in the Windows kernel that will overflow if they call Windows APIs. There is enough stack space for unhooking interrupts, however. In Windows 3.1, WEPs are called off a 4K stack in the Windows kernel, which allows them to call Windows API functions. An implictly loaded DLL is loaded into memory before the application that uses it gets fully loaded and so LibMain(), analogous to WinMain(), may get called before the application's message queue is initialized. Thus, do not call APIs that send messages to the application in LibMain(). Also, an implicitly loaded DLL is terminated after the application that uses it has been completely removed from the system. This means that you cannot perform any actions in a WEP that rely on the application's existence. Example classes of functions that cannot be called from a WEP include file manipulation functions, message boxes, and dialog boxes. To write a DLL that is compatible with both Windows 3.0 and 3.1, follow these rules: 1) The DLL's module name in LIBRARY statement of the DLL's module definition file must be all caps. If this is not done, the DLL will not be properly unloaded in Windows 3.0. This is a limitation for Windows 3.0 only. 2) Because Windows 3.0 calls WEPs on a very small stack in the kernel, WEPs cannot call any Windows API function. DLLs designed for Windows 3.1 only can call Windows APIs, however. Please see the discussion above. 3) Use the /30 resource compiler switch to mark the DLL as a Windows 3.0 DLL. To convert this sample so that the application explicitly loads the DLL, you need to call LoadLibrary() to load the DLL; to unload the DLL, call FreeLibrary(). The makefile needs to be slightly modifed so that it 1) does not call IMPLIB to make an import library for the DLL and 2) does not link the import library, DLLSKEL.LIB to the application. Finally, to access the function exported by the DLL, you will have to call GetProcAddress() to locate the function just before calling it. Files ----- This sample is divided into the following files: appskel.c - The main program file for the application. about.c - The dialog procedure for the About box. init.c - The initialization code for the application. mainwnd.c - The main window procedure for the application. appskel.rc - The resource script file that contains the resource definitions for the application. appskel.def - The module definition file for the application. dllskel.c - The main program file for the DLL. wepcode.c - The program file that contains the WEP. dllskel.def - The module definition file for the DLL. makefile - The NMAKE file that specifies the build commands for both the DLL and the application. appskel.exe - Executable application file. dllskel.dll - Dynamic link library. Credits ------- Development team: Dan Ruder