PRB: Why Thunking to 16-bit MAPI Will Fail Under Win32s
ID: Q149710
|
The information in this article applies to:
-
Microsoft Win32s versions 1.30, 1.30c
SUMMARY
This article discusses the details on why a Win32s client (a 32-bit thunk
DLL) cannot thunk to the 16-bit MAPI DLL. It also suggests several
workarounds for this situation.
SYMPTOMS
The MAPI interface is not supported under any version of Win32s. In
addition, a Win32s client (a 32-bit application or a DLL) cannot directly
thunk down to 16-bit MAPI APIs in Windows 3.x. There are several
resolutions for this scenario.
CAUSE
When the 16-bit MAPI DLL allocates a buffer on behalf of a call from the 32-
bit thunk DLL, your 16-bit code will have to call
UTSelectorOffsetToLinear() on the returned 16:16 address. The result is a
flat 32-bit address that can then be passed back to the 32-bit DLL. But
when the 32-bit code is ready to call the 16-bit MAPIFreeBuffer() function
by way of the thunk, the flat 32-bit address needs to be converted back to
the original 16:16 address that the 16-bit code can use. The normal
solution is that the 16-bit code would call UTLinearToSelectorOffset() on
the 32-bit address passed from the 32-bit client before making a call to
MAPIFreeBuffer().
But the problem is that in the following nested function call where x is a
segmented (16:16) address, Win32s does not guarantee to return the original
value of x (16:16 address) back. Hence, when MAPIFreeBuffer is called with
this bogus 16:16 address, it fails.
UTLinearToSelectorOffset( UTSelectorOffsetToLinear(x) )
Note that this address translation problem described here is not specific
to the MAPI allocation and de-allocation routines. It applies to all 16-bit
MAPI functions that use 16:16 segmented addresses.
RESOLUTION
Here are three approaches you can use to resolve this situation:
- Correct the address translation problem that is inherent to Win32s. For
each 16-bit MAPI function that would use or return a 16:16 segmented
address and that needs to be converted to a 32-bit address to be passed
on to the 32-bit side, you need to maintain a global lookup table or
array on the 16-bit side that associates the new 32-bit address with the
corresponding 16:16 address. When the 32-bit code calls into 16-bit code
passing a valid 32-bit address, instead of calling
UTLinearToSelectorOffset() on this 32-bit address, you will have to
fetch the corresponding 16:16 address from the lookup table. This 16:16
address can be used with all the MAPI functions on the 16-bit side.
- Write a separate 16-bit client (a 16-bit DLL) that would implement the
MAPI functionality by linking to the 16-bit MAPI DLL. The Win32s client
(a 32-bit DLL) would then thunk to the 16-bit client DLL that makes the
MAPI calls. The address translation problem does not exist in this
scenario because all MAPI functionality is implemented and executed on
the 16-bit side by the 16-bit client DLL linking to the 16-bit MAPI DLL.
- Write a separate 16-bit client (a 16-bit application) that implements
the MAPI functionality by linking to the 16-bit MAPI DLL. Then the
Win32s client (either a 32-bit application or DLL) can communicate with
this 16-bit client by way of the documented IPC (interprocess
communication) methods that are available to Win32s. For more
information on IPC mechanisms under Win32s, please see the following
article in the Microsoft Knowledge Base:
Q95900 Interprocess Communication on Windows NT,
Windows 95, & Win32s
Note that Visual Foxpro version 3.0b includes a DLL called Foxmapi.fll that
implements the second workaround, allowing 32-bit Visual Foxpro
applications to communicate with 16-bit MAPI functions under Win32s.
These three approaches are only suggestions; Microsoft cannot provide
support if you decide to implement them in your Win32s-based application.
STATUS
This behavior is by design.
Additional query words:
kbinf ipc mapi thunk win16 win32
Keywords : kbWin32s
Version : 1.30 1.30c
Platform : WINDOWS
Issue type :