Microsoft KB Archive/30590

INF: What EMS Means to Developers ID Number: Q30590

2.03 2.10 3.00 WINDOWS

Summary:

This article describes how using Windows expanded memory affects application development.

Please note that when expanded memory is mentioned in this article, it also means extended memory. Extended memory is used as expanded memory by Windows.

More Information:

In Windows versions 2.x and 3.0, expanded memory can be used by the Windows memory manager. In enhanced mode Windows 3.0, the memory manager can emulate expanded memory by using extended memory. All Windows applications are run in one virtual machine, but each DOS application receives its own virtual machine in which to run.

In real mode Windows, expanded memory presents the following problems:


 * 1) Applications cannot share memory through global handles
 * 2) The efficient use of available EMS (expanded memory specification) in a small frame

The only way applications can share global data is through the dynamic data exchange (DDE) protocol or through the clipboard. When large frame EMS is used, global objects are allocated above the EMS line and are available only to one application. For example, in large frame EMS, task A allocates some global memory and passes the handle to task B. When task B attempts to access the memory object, it will not be in memory. Instead, task B will access the corresponding location in its own EMS memory.

DDE and clipboard objects can be shared because the Windows memory manager will copy the contents of these objects to the currently running application’s EMS bank. The application must check the return value from GlobalLock because the memory manager may not be able to successfully copy the object in a low memory situation. Clipboard objects should be copied by the receiving application before the clipboard is closed because the memory manager may delete the global object.

Applications can share data through dynamic-link libraries (DLLs), as well as through DDE and clipboard objects; however, only data located in the DLL data segment can be shared. Global objects allocated by DLLs are allocated above the EMS line, just like objects allocated by an application.

There is one exception to the rule of not sharing global memory handles. If the GMEM_NOT_BANKED flag is used, the object will be allocated below the EMS bank line, making it available to all applications. This should not be done because there is only a limited amount of memory below the EMS line when the system is using large frame EMS. This flag is available for device drivers that require this kind of shared memory; applications should be designed using one of the other methods to share memory objects.

The second issue regards the most effective use of small frame EMS by applications. In small frame EMS, code and resources are the only EMS items available to applications. Once code and resources are loaded into EMS, they will not be discarded. However, they are banked out when another task is running.

The Windows loader fills EMS before it loads code or resources into conventional memory. For this reason, the DEF file for each application should list the segments that are important throughout the life of an application at the top of the list of segments in the SEGMENTS statement, and these segments should be marked as PRELOAD. List the segment that contains the application’s main window procedure first. The segments for code that is used and discarded, such as initialization code, should be listed toward the bottom of the list. By the same reasoning, mark resources that are important throughout the life of the application as PRELOAD.

For small applications, the LimitEmsPages function allows an application to limit the amount of EMS that is allocated on its behalf. The argument passed to this function is the maximum number of kilobytes of EMS that Windows will allocate for the application. A small application can call this function to keep 400-500K of EMS from being allocated when the application can run reliably with 100K of EMS.

When LimitEmsPages is used, it is important to note that in large frame EMS (where DLL code is located above the EMS line), a small application will require more space than the sum of its segments because library code shares the EMS allocated for the application.

Note: Hook callback functions must be placed in FIXED DLL code so the code will always be present regardless of EMS state. The same is true for GlobalNotify callback functions.

Additional reference words: 2.03 2.10 3.00