INFO: Win32s Translated Pointers Guaranteed for 32K

ID: Q100833

The information in this article applies to:

SUMMARY

Translated pointers are guaranteed to be valid only for 32K, rather than 64K, which selectors are usually limited to. This limitation is for performance reasons.

Selectors are tiled every 32K. A 0:32 pointer can be quickly translated into a 16:16 pointer, which will be valid for a minimum of 32K. In other words, the offset portion of the 16:16 pointer is not guaranteed to be 0 (zero) when translated. As a result, even though the translated selectors have a limit of 64K, the offset passed to the 16-bit side may be as large as 32K-1.

Selectors are created on a 32K alignment so that if you pass several pointers to the same range, the Universal Thunk (UT) uses the same selector. Selectors are freed when application terminates.

The alternative is to create a selector for each and every translation, which is very slow.

MORE INFORMATION

For any given address, there are two selectors that point to it, but only one has a limit less than 32K:

           +-------+-------+-------+-------+-------+-------+
           |Selector 2(64K)|Selector 4(64K)|Selector 6(64K)|
   +-------+-------+-------+-------+-------+-------+-------+
   |Selector 1(64K)|Selector 3(64K)|Selector 5(64K)|       |
   +-------+-------+-------+-------+-------+-------+-------+
   |  32K  |  32K  |  32K  |  32K  |  32K  |  32K  |  32K  |
   +-------+-------+-------+-------+-------+-------+-------+

Under Win32s, 16-bit and 32-bit applications share the same global data space; therefore, it is possible to share a buffer of up to 64K in size with a far pointer or more than 64K with a huge pointer by doing the following:

1. Do a GlobalAlloc() on the 32-bit side. Be sure to use GMEM_MOVEABLE. 2. Copy the data. 3. Send the handle to the 16-bit side. 4. Get a pointer to the data on the 16-bit side by using GlobalLock().

   If the buffer in more than 64K in size, make sure to type cast the
   return value from GlobalLock() to a huge pointer.

When you pass a pointer to a block that was allocated via GlobalAlloc() from the 32-bit side, it costs no selectors. The translated pointer is valid until the memory is freed.

For more information on how to share large amounts of data between the 16-bit and 32-bit side of an Universal Thunk under Win32s, please refer to the following Knowledge Base article:

  ARTICLE ID: Q126708
  TITLE     : HOWTO: Pass Large Memory Block Through Win32s Universal Thunk
Keywords          : kbprg kbWin32s kbThunk 
Version           : 1.0 1.1 1.2 1.3 1.3a 1.3c
Platform          : WINDOWS
Issue type        : kbinfo

Last Reviewed: June 12, 1997