Article ID: 195310
Article Last Modified on 7/22/2004
hModKernel = GetModuleHandle ("kernel32.dll");
lpMAPLS = GetProcAddress (hModKernel, "MAPLS");
The following type definition, used in the following documentation to
distinguish between 16-bit far pointers and 32-bit pointers, is not
provided in any header file so you should add it to your project:
typedef DWORD LPFAR16;
LPFAR16 lp16Bit
A 16-bit far pointer that is translated into a pointer that can be used by
a 32-bit process.
If successful, it returns a 32-bit pointer that aliases (points to) the
same location as lp16Bit. If unsuccessful, it returns NULL.
If lp16Bit points to a block of memory with a linear address below 64K, the
return value is equal to lp16Bit because the region below 64K is not
accessible from 32-bit processes. This allows convenient translation of
values that can be either pointers or words (such as atoms).
This API is used by a 32-bit process to translate a 16-bit far pointer
(passed to it from a 16-bit application) into a 32-bit pointer. It should
be used when the 16-bit application has allocated memory and needs to give
a 32-bit process access to that memory.
If the 16-bit application allocated the memory through GlobalAlloc(), it
must fix the block by calling GlobalFix() or GlobalWire() before the 32-bit
process translates the pointer with MapSL(). Allocating memory with the
GMEM_FIXED flag and then locking it with GlobalLock() from a 16-bit
application does not allocate fixed memory. From a 16-bit DLL, GlobalAlloc
with the GMEM_FIXED flag allocates fixed and pagelocked memory. Because the
block does not need to be pagelocked, it is recommended that DLLs allocate
movable memory and then use GlobalFix() or GlobalWire().
Failure to fix the block before translating a pointer to it allows the 16-
bit global memory manager to move the block, which invalidates the 32-bit
pointer that aliases it. If the block remains fixed for a long time, you
should use GlobalWire() instead of GlobalFix() because it moves the block
lower in the heap before fixing it, which helps the 16-bit global memory
manager reduce fragmentation in the 16-bit global heap.
Preferably, instead of calling GlobalFix() on the block, the 16-bit
application should pass the pointer to the 32-bit application, and then the
32-bit application should use MapSLFix() instead of MapSL().
Returns a newly created far pointer that is composed of a single newly-
allocated read-write data selector and an offset that is guaranteed to be
zero. The selector's base address is the linear address specified by
lp32Bit, and its limit is 64K.
The 32-bit application that called MapLS() passes the return value to the
16-bit application or DLL. The 16-bit application or DLL might increase or
decrease the selector's limit with SetSelectorLimit().
If lp32Bit is less than 64K, it is treated as a DWORD, the return value is
the same as lp32Bit, and no selector is allocated. This allows convenient
translation of values that can be either pointers or words (such as atoms).
If this function fails, the return value is NULL.
The returned pointer is global to all 16-bit processes, and its selector is
not automatically freed on process termination. Selectors are a limited
resource, so you must use UnMapLS() to free every pointer allocated with
MapLS().
The 16-bit applications and DLLs can only use the pointer when the 32-bit
process that translated it is in context. This is because each 32-bit
process has its own private address space, which is mapped between 0 and 2
gigabytes (GB) only when one of its threads is running. An example of when
a 16-bit application can use the translated pointer is inside a 32 to 16
thunk.
If successful, it returns a 32-bit pointer that points to the same location
as lp16Bit. If unsuccessful, it returns NULL.
If lp16Bit points to a block of memory with a linear address below 64K, the
return value is equal to lp16Bit because the region below 64K is not
accessible from 32-bit processes. This allows convenient translation of
values that can be either pointers or words (such as atoms).
If the block pointed to by lp16Bit was allocated by the 16-bit global
memory manager, this function fixes the block before doing the translation,
so the 16-bit side does not need to call GlobalFix() on it. Otherwise,
MapSLFix() acts just like MapSL().
Once you finish using the linear address, you should call UnMapSLFixArray()
to unfix the block.
None.
This routine traverses the array of 16-bit far pointers and unfixes each
memory block in succession. If a particular block was not allocated by the
16-bit global memory manager, it is safely ignored by this function.
Once this function has been called, any 32-bit pointers that alias (point
to) these blocks should be considered invalid because the 16-bit global
memory manager can move the blocks again.
This routine preserves the EAX and EDX registers, as well as the registers
all STDCALL functions preserve. This allows it to be used at the end of a
thunking routine without destroying the return value from the thunk target.
None.
If lp16Bit is less than 64K, UnMapLS() does nothing. Otherwise, the high
word of lp16Bit is assumed to be a selector allocated by MapLS(), and the
low word (the offset) is ignored. This selector is freed.
Only selectors allocated by MapLS() should be passed to this function. If a
16-bit application or DLL changed the limit of the selector with
SetSelectorLimit(), you do not need to change it back before calling
UnMapLS().
Keywords: kbinfo KB195310