HOWTO: Share Memory Between 32-Bit and 16-Bit Code on Win32s

ID: Q105762

The information in this article applies to:

SUMMARY

This article discusses many of the issues involved in sharing memory across the process boundary under Win32s.

MORE INFORMATION

Memory allocated by a Win32-based application using GlobalAlloc() can be shared with a 16-bit Windows-based application on Win32s. If the memory is allocated with GMEM_MOVEABLE, then GlobalAlloc() returns a handle and not a pointer. The 16-bit Windows-based application can use the low word of this handle. The high word is all zeros. Make sure to lock the handle using GlobalLock() in the 16-bit Windows-based application to get a pointer.

NOTE: GlobalAlloc (GMEM_FIXED...) is not the same as GlobalFix(GlobalAlloc(GMEM_MOVEABLE...)). GMEM_FIXED will allocate locked pages, which is most often not what you want.

Memory allocated by a 16-bit Windows-based application via GlobalAlloc() must be fixed via GlobalFix() and translated before it can be passed to a Win32-based application. Whenever a Windows object is passed to a Win32-based application by its 32-bit address, the memory must be fixed, because the address is computed from the selector base only once. If Windows moves the memory, the linear address used by the Win32-based application will no longer be valid.

If you are using the Universal Thunk, you can also pass a buffer from a Win32-based application to a 16-bit dynamic-link library (DLL) in the UTRegister() call. The address is translated for you. Another alternative is the translation list passed to the callable stubs. Addresses passed in the translation list will be translated during the thunking process. For more information on the Universal Thunk, please see the "Win32 Programmer's Reference."

NOTE: The ability to share global memory handles under Win32s is a result of the implementation of Windows 3.1, in which all applications run in the same address space. This is not true of existing Win32 platforms and will not be true of future Win32 platforms.

Allocating memory with GlobalAlloc() gets you tiled selectors. However, you can only tile 255 selectors at a time and there is an overall limit of 8192 selectors in the system. If you allocate memory using new, malloc(), HeapAlloc(), LocalAlloc() or VirtualAlloc, your allocated memory does not automatically get you tiled selectors. However, because you don't automatically get tiled selectors, whenever you pass memory to 16-bit code, selectors must be synthesized for you. There's currently a limit of 256 selectors that Win32s maintains for select synthesis. Also note that each block of memory that you pass is limited to 32K in size due to the way that Win32s tiles selectors.

REFERENCES:

For more information on the limitations of sharing memory between 16-bit and 32-bit code under Win32s, please refer to the following Knowledge Base articles:

  ARTICLE ID: Q126708
  TITLE     : HOWTO: Pass Large Memory Block Through Win32s Universal Thunk

  ARTICLE ID: Q100833
  TITLE     : INFO: Win32s Translated Pointers Guaranteed for 32K
Keywords          : kbprg kbWin32s kbThunk 
Version           : 1.3 1.3a 1.3c
Platform          : WINDOWS
Issue type        : kbhowto

Last Reviewed: June 12, 1997