More Global Memory Functions

Although the four global memory functions shown above are the ones you'll use most often, Windows also provides several others. Before using GlobalAlloc, you may want to determine the amount of global memory currently available:

dwAvailable = GlobalCompact (dwRequested) ;

GlobalCompact causes Windows to move moveable blocks and to calculate the area of free memory that could be obtained by also discarding discardable blocks. If the function cannot generate dwRequested bytes, it returns the largest block of free memory available. Discarding doesn't take place until you call GlobalAlloc using the size returned from GlobalCompact.

After you allocate a memory block, you can determine its size using:

dwBytes = GlobalSize (hGlobalMemory) ;

You can also change the size of the memory block or change its attributes using GlobalReAlloc. This function is a little tricky, because it can be used in one of three ways. Here's the general syntax:

hGlobalMemory = GlobalReAlloc (hGlobalMemory, dwBytes, wFlags) ;

First, you can change the size of a global memory block (either increasing or decreasing it) using:

GlobalReAlloc (hGlobalMemory, dwNewBytes, wFlags) ;

The data already stored in the block are preserved. The function returns NULL if it cannot increase the block to the requested size.

The wFlags parameter is used in the same way as the wFlags parameter for GlobalAlloc: GMEM_NODISCARD and GMEM_NOCOMPACT place restrictions on what Windows will do to satisfy the allocation request. GMEM_ZEROINIT zeroes out additional bytes if you are expanding the block. When calling GlobalReAlloc, you don't have to include the GMEM_FIXED, GMEM_MOVEABLE, or GMEM_DISCARDABLE flags. Windows preserves the attribute specified when the block was allocated. However, you may want to use the GMEM_MOVEABLE flag for reallocating a fixed block. Doing so gives Windows permission to move the block in memory to satisfy the allocation request. In this case, GlobalReAlloc returns a new global memory handle to the fixed block:

hGlobalMemoryNew = GlobalReAlloc (hGlobalMemoryOld, dwNewBytes,

GMEM_MOVEABLE) ;

If GlobalReAlloc returns NULL, the request for memory was refused, and the original hGlobalMemoryOld value passed to GlobalReAlloc is still valid for the fixed block.

The second way to use GlobalReAlloc is to change the discardable attribute of moveable blocks. The dwNewBytes value is ignored. You can change a moveable block to a discardable one:

GlobalReAlloc (hGlobalMemory, 0L, GMEM_MODIFY | GMEM_DISCARDABLE) ;

or change a discardable block to a moveable (but nondiscardable) one:

GlobalReAlloc (hGlobalMemory, 0L, GMEM_MODIFY | GMEM_MOVEABLE) ;

The third use of GlobalReAlloc is to discard a discardable memory block. This requires dwNewBytes to be 0 and the wFlags parameter to be GMEM_MOVEABLE:

GlobalReAlloc (hGlobalMemory, 0L, GMEM_MOVEABLE) ;

You can do the same thing using:

GlobalDiscard (hGlobalMemory) ;

In fact, GlobalDiscard is a macro defined in terms of GlobalReAlloc.