Microsoft KB Archive/33264

Shared Memory and DLLs using GMEM_NOT_BANKED/GMEM_DDESHARE

PSS ID Number: Q33264 Article last modified on 11-05-1993

2.03 2.10 3.00 MS-DOS

= QUESTION =

How do applications share memory between themselves, and how does this relate to the use of GMEM_NOT_BANKED and GMEM_DDESHARE?

= RESPONSE =

Applications share memory between themselves through dynamic data exchange (DDE), the Clipboard, or library data segments (DS’s). They may not pass handles back and forth in any other manner. If they use DDE, the blocks to be shared must be allocated with the GMEM_DDESHARE flag so that the KERNEL may do the necessary work of copying blocks from one set of banks to another. In addition, they must follow the DDE specifications with regard to reading and writing to such blocks. The GMEM_NOT_BANKED and GMEM_DDESHARE flags are used in special circumstances where more precise control of memory placement is needed. For example, some printer drivers use the GMEM_NOT_BANKED flag to allocate blocks that must be accessible at all times by all applications. A more detailed description of the actions of these flags follows.

Detailed Descriptions: Calling GlobalAlloc with the GMEM_NOT_BANKED flag places the block below the bank line so that it is resident at all times. The GMEM_NOT_BANKED flag controls the banking of a block. If a block is banked (“above the line”), it is only available when its bank is active and loaded into real memory. A bank is active when the application that owns the bank is the current task. Note that multiple instances of an application all share the same bank. Since multiple instances share a bank, they can all use any block in the bank. If a block is not banked (“below the line”), it is always in “real” memory and therefore always accessible no matter what the current task is. You cannot allocate DISCARDABLE, GMEM_NOT_BANKED memory if large-frame EMS is being used by Windows. Note that GMEM_NOT_BANKED uses SCARCE below-the-line memory and should not be used without good reason. Usually DDE can be used instead. You cannot GlobalRealloc with GMEM_MODIFY | GMEM_NOT_BANKED. Once a block is allocated either above or below the line, it stays there forever. The GMEM_DDESHARED flag is what allows interbank copying. Let us say that one application allocated a DDESHARE block. This block is allocated above the line. Data is written to the block, and the handle is passed to another application through a DDE message. When the second application does the GlobalLock on the handle, Windows makes a COPY of the block into the second application’s bank. The second application can then read the data. When GlobalUnlock is called with this handle, the copy is destroyed. GMEM_DDESHARE also has an interesting side effect. Calling GlobalAlloc with the GMEM_DDESHARE flag sets the owner of the block to be the owner of the code segment that made the GlobalAlloc call, instead of setting it to the current task (instance of an application). The side effects of GMEM_DDESHARE become apparent when an instance of an application, the last instance of an application, or a DLL (dynamic-link library) terminates. When an instance terminates, all global blocks belonging to it are freed. When the last instance of an application terminates, all global blocks belonging to that application’s code and all memory in that bank is freed. When a DLL is freed, all global blocks belonging to it are freed. In summary, GMEM_NOT_BANKED affects when a block is available, since it implies the block is never banked out, and GMEM_DDESHARE allows interbank copying of blocks for DDE. As a side effect, it also controls when the block is destroyed by changing the owner. These flags are then used to control passing and sharing of memory between instances and applications. DLLs come into play because they are code, (that is, a module capable of ownership), that is shared between applications. This allows blocks to be allocated that will be shared and not destroyed with the termination of any given instance or application. Note that if a DLL is loaded by IMPLIB reference from one or more applications, it will be freed when the last referencing application terminates. An IMPLIB reference is when an application links to a .LIB created by IMPLIB from the DLL’s .DEF file. This causes the DLL to be loaded when the application is loaded. Note that calling GlobalRealloc with GMEM_MODIFY | GMEM_DDESHARE, although possible, does not make much sense and is not guaranteed to have the desired effect. The following are the four possible types of memory blocks: 1. Banked, not DDEshared This is the default case where the block is freed when the instance of the application that caused the allocation terminates. This is true even if the block was allocated while in a call to a DLL. 2. Banked, DDEshared If allocated from an application, this allows the block to remain until the last instance of the application terminates, regardless of which one allocated it. If allocated from within a DLL, the block can exist until either the bank is destroyed with the last instance of the application, or the DLL is freed. 3. Not banked, DDEshared If allocated from within a DLL, the block will remain until the DLL is freed, and will be available to all instances of all applications. If allocated from within an application, the block will be available to all instances of all applications, but the block will be destroyed with the last instance of the application. 4. Not banked, not DDEshared This is an unusual case with only two known uses. From an application, it is used for blocks involved in message broadcasts. From printer drivers, it is used for data (such as font directories) maintained between calls. The lifetime of a DLL can be extended by using LoadLibrary and FreeLibrary to increment and decrement the reference count. Note that local blocks are allocated from within a DS that is destroyed in its entirety when that application or DLL is terminated. The GMEM_* flags do not apply. To reiterate, an application cannot just pass a global memory handle around. It must do so using DDE, the Clipboard, or a library DS. For more detailed information about EMS support, please refer to Paul Yao’s EMS article in the January 1988, (Volume 3, No. 1), issue of the “Microsoft Systems Journal.”

Additional reference words: GMEM_NOT_BANKED GMEM_DDESHARE global memory GlobalAlloc 2.03 2.10 3.00 KBCategory: KBSubcategory: KrMmSharedmem Copyright Microsoft Corporation 1993.