Translating 16:16 Pointers

You may occasionally need to translate 16:16 pointers to 32-bit pointers. The GetVDMPointer32W and WOWGetVDMPointer functions accomplish this. Call GetVDMPointer32W from 16-bit code and WOWGetVDMPointer from 32-bit code to translate 16:16 pointers to 32-bit pointers. In addition, GlobalFix, GlobalUnfix, GlobalWire, and GlobalUnwire must be called from 16-bit code. For more information about these functions, see the 16-bit Windows SDK documentation.

Windows 95 and Windows 98:

If you use GetVDMPointer32W or WOWGetVDMPointer and the affected 16:16 pointer represents a movable global memory manager block, it is important that you first call the GlobalFix or GlobalWire function on the segment portion of the pointer. If you do not, the 16-bit global memory manager can move the block while your process is executing 32-bit code. If this happens, the linear address returned by GetVDMPointer32W or WOWGetVDMPointer will become invalid. The debugging version of the system generates warnings about calls to GetVDMPointer32W on unfixed segments.

The WOWGetVDMPointerFix function is similar to WOWGetVDMPointer, but ensures that the memory pointed to will not be moved by the global memory compacter until the WOWGetVDMPointerUnfix function has been called. WOWGetVDMPointerFix performs an implicit GlobalFix operation on the selector, if necessary. If the selector is allocated as a fixed block or if it is not from the global memory manager, no special action is taken. You should use this function instead of calling GlobalFix separately, because it is easier to use and is faster than calling both GlobalFix and WOWGetVDMPointer.

WOWGetVDMPointerUnfix takes a 16:16 address and undoes the effect of WOWGetVDMPointerFix on the segment (the offset portion is ignored). This function should be called once the linear address is no longer needed to avoid fragmentation. It is faster than the GlobalUnfix function and correctly handles (that is, ignores) selectors that are not from the 16-bit global memory manager.

Windows NT:

While you are executing 32-bit code called through a generic thunk, the 16-bit side of the thunk is completely blocked until you return or yield. Therefore, in most cases, you do not need to fix or wire the memory. Therefore, WOWGetVDMPointerFix is identical to WOWGetVDMPointer (it does not call GlobalFix) and WOWGetVDMPointerUnfix has no effect under Windows NT.

If you are targeting only Windows NT and your 32-bit code yields the message system (by calling functions such as SendMessage, BroadcastSystemMessage, GetMessage, PeekMessage, MessageBox, or DialogBox), you should either call GlobalFix or GlobalWire ahead of time on the 16-bit side or refresh your 32-bit pointers after the yielding function call has completed by calling WOWGetVDMPointer.

If you are targeting Windows NT, Windows 95, and Windows 98, there are two approaches that you can use. The easiest approach is to have the 16-bit side of the thunk first fix all of the segments in memory using GlobalFix or GlobalWire. In the 32-bit code, use WOWGetVDMPointer, rather than WOWGetVDMPointerFix, because the segments are already fixed in memory. After the 32-bit code returns, call GlobalFix or GlobalUnwire in the 16-bit code. This guarantees that your 32-bit pointers remain valid, regardless of the platform, even if the 16-bit global memory manager compacts the global heap. The drawback to this approach is that many segments can be left fixed in memory for extended periods of time, potentially causing out-of-memory conditions due to memory fragmentation.

The most efficient approach that still works on both platforms requires that you use WOWGetVDMPointerFix and WOWGetVDMPointerUnfix. On Windows NT, the 32-bit pointers can still be affected by 16-bit memory movement if the 32-bit code yields the message system. After each call that might yield the messaging system, discard your 32-bit pointers using WOWGetVDMPointerUnfix. If you continue to use the pointer, repeat the original call to WOWGetVDMPointerFix to refresh the pointer. The drawback to this approach is that it cannot be used if the called function that yields the messaging system uses 32-bit pointers that you provide after yielding the messaging system. If you cannot determine if this will be a problem, the first approach would be a safer choice.