Jump to content

Thunking with DOSCALL1: Difference between revisions

From EDM2
Created page with "DOSCALL1.DLL is an external extension of the OS/2 kernel that provides several translations for standard Dos* API calls. The following entry points are probably useful for pe..."
 
Ak120 (talk | contribs)
No edit summary
Line 1: Line 1:
DOSCALL1.DLL is an external extension of the OS/2 kernel that provides
DOSCALL1.DLL is an external extension of the OS/2 kernel that provides several translations for standard Dos* API calls.
several translations for standard Dos* API calls.


The following entry points are probably useful for people who have to
The following entry points are probably useful for people who have to deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice versa.
deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice
versa.
 
 
Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather
simple job. Some clever programmers invented a fast mechanism to convert
pointers between 16 and 32 bit, by use of the local descriptor table (LDT).
The LDT was initialized to contain direct translations for the first 512MB
of memory, i.e. the first 64K were mapped to LDT entry 0 (invalid, though!),
the second 64k to entry 1, third to 2 and so on. Since there are 8192 LDT
entries, this sums up to 8192 * 64K = 512MB of addressable memory. The
following formulae applied:
 
 
<pre>
flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset
 
</pre>


Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather simple job. Some clever programmers invented a fast mechanism to convert pointers between 16 and 32 bit, by use of the local descriptor table (LDT).
The LDT was initialized to contain direct translations for the first 512MB of memory, i.e. the first 64K were mapped to LDT entry 0 (invalid, though!), the second 64k to entry 1, third to 2 and so on. Since there are 8192 LDT entries, this sums up to 8192 * 64K = 512MB of addressable memory. The following formulae applied:
flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset
and
and
selector = (flataddr >> 3) >> 16
offset = flataddr & 0xffff


<pre>
The formulae are written here for readability, in assembler they turn out to be pretty efficiently codeable.
selector = (flataddr >> 3) >> 16
offset = flataddr & 0xffff
 
</pre>
The formulae are written here for readability, in assembler they turn out
to be pretty efficiently codeable.
 
 
Unfortunately, this no longer works with newer kernels which allow user
processes to get more than 512MB of memory; thus some sort of compatibility
to old 16 bit apps has been dropped. It is now no longer guaranteed to
32 bit apps that there is a 1:1 relation between used 32 bit
and 16:16 addresses through LDT, so simple arithmetics probably will no
longer apply. This is particularly difficult if some 32 bit application
has to transfer data to some legacy 16 bit app. This is what the following
API functions are good for.
 


An application for these functions is described in the DDK header
Unfortunately, this no longer works with newer kernels which allow user processes to get more than 512MB of memory; thus some sort of compatibility to old 16 bit apps has been dropped. It is now no longer guaranteed to 32 bit apps that there is a 1:1 relation between used 32 bit
file <code>ddkx86\inc\thkmacs.inc</code> which explains how to
and 16:16 addresses through LDT, so simple arithmetics probably will no longer apply. This is particularly difficult if some 32 bit application has to transfer data to some legacy 16 bit app. This is what the following API functions are good for.
create handcoded thunks.


An application for these functions is described in the DDK header file <code>ddkx86\inc\thkmacs.inc</code> which explains how to create handcoded thunks.


== List of functions ==
== List of functions ==
 
{|class="wikitable"
{| border="1"
!Name||Ordinal||Type
|-
|Name
|Ordinal
|type
 
|-
|-
|DOSFLATTOSEL
|DOSFLATTOSEL
|423
|423
|16bit
|16bit
|-
|-
|DOSSELTOFLAT
|DOSSELTOFLAT
|424
|424
|16bit
|16bit
|-
|-
|Dos32FlatToSel
|Dos32FlatToSel
|425
|425
|32bit
|32bit
|-
|-
|Dos32SelToFlat
|Dos32SelToFlat
|426
|426
|32bit
|32bit
|}


|}
== DOSFLATTOSEL ==  
== DOSFLATTOSEL ==
=== Synopsis ===
=== Synopsis ===
void far* DOSFLATTOSEL(ULONG eax)
void far* DOSFLATTOSEL(ULONG eax)


=== Description ===
=== Description ===
 
This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 16 bit code. The result is returned in eax (selector=high word, offset=low word).
This converts a 32 bit flat address to a 16:16 far pointer to be usable by
16 bit code. This routine is callable from 16 bit code. The result is
returned in eax (selector=high word, offset=low word).


=== Parameters ===
=== Parameters ===
Line 95: Line 50:
   
   
== DOSSELTOFLAT ==
== DOSSELTOFLAT ==
=== Synopsis ===
=== Synopsis ===
ULONG DOSSELTOFLAT(void far* eax)
ULONG DOSSELTOFLAT(void far* eax)


=== Description ===
=== Description ===
 
This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 16 bit code. The result is returned in eax.
This converts a 16:16 far pointer to a 32 bit flat address to be usable
by 32 bit code. This routine is callable from 16 bit code. The result is  
returned in eax.


=== Parameters ===
=== Parameters ===
Line 112: Line 62:
   
   
== Dos32FlatToSel ==
== Dos32FlatToSel ==
=== Synopsis ===
=== Synopsis ===
ULONG Dos32FlatToSel(ULONG eax)
ULONG Dos32FlatToSel(ULONG eax)


=== Description ===
=== Description ===
 
This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 32 bit code. The result is returned in eax (selector=high word, offset=low word).
This converts a 32 bit flat address to a 16:16 far pointer to be usable by
16 bit code. This routine is callable from 32 bit code. The result is
returned in eax (selector=high word, offset=low word).


=== Parameters ===
=== Parameters ===
Line 127: Line 72:
   
   
== Dos32SelToFlat ==
== Dos32SelToFlat ==
=== Synopsis ===
=== Synopsis ===
ULONG Dos32SelToFlat(ULONG eax)
ULONG Dos32SelToFlat(ULONG eax)


=== Description ===
=== Description ===
 
This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 32 bit code. The result is returned in eax.
This converts a 16:16 far pointer to a 32 bit flat address to be usable
by 32 bit code. This routine is callable from 32 bit code. The result is  
returned in eax.


=== Parameters ===
=== Parameters ===
Line 142: Line 82:
This argument is not passed on the stack.
This argument is not passed on the stack.
   
   
[[Category:]]
[[Category:Miscellaneous Articles]]

Revision as of 16:08, 19 August 2016

DOSCALL1.DLL is an external extension of the OS/2 kernel that provides several translations for standard Dos* API calls.

The following entry points are probably useful for people who have to deal with thunking, i.e. translation of 0:32 pointers to 16:16 and vice versa.

Back in the old days of OS/2 2.x/3.x, this pointer conversion was a rather simple job. Some clever programmers invented a fast mechanism to convert pointers between 16 and 32 bit, by use of the local descriptor table (LDT). The LDT was initialized to contain direct translations for the first 512MB of memory, i.e. the first 64K were mapped to LDT entry 0 (invalid, though!), the second 64k to entry 1, third to 2 and so on. Since there are 8192 LDT entries, this sums up to 8192 * 64K = 512MB of addressable memory. The following formulae applied:

flataddr = ((((selector&0x1fff) << 3) | 0x0007) << 16) | offset

and

selector = (flataddr >> 3) >> 16
offset = flataddr & 0xffff

The formulae are written here for readability, in assembler they turn out to be pretty efficiently codeable.

Unfortunately, this no longer works with newer kernels which allow user processes to get more than 512MB of memory; thus some sort of compatibility to old 16 bit apps has been dropped. It is now no longer guaranteed to 32 bit apps that there is a 1:1 relation between used 32 bit and 16:16 addresses through LDT, so simple arithmetics probably will no longer apply. This is particularly difficult if some 32 bit application has to transfer data to some legacy 16 bit app. This is what the following API functions are good for.

An application for these functions is described in the DDK header file ddkx86\inc\thkmacs.inc which explains how to create handcoded thunks.

List of functions

Name Ordinal Type
DOSFLATTOSEL 423 16bit
DOSSELTOFLAT 424 16bit
Dos32FlatToSel 425 32bit
Dos32SelToFlat 426 32bit

DOSFLATTOSEL

Synopsis

void far* DOSFLATTOSEL(ULONG eax)

Description

This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 16 bit code. The result is returned in eax (selector=high word, offset=low word).

Parameters

eax (register)

The flat address to be converted. This argument is not passed on the stack.

DOSSELTOFLAT

Synopsis

ULONG DOSSELTOFLAT(void far* eax)

Description

This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 16 bit code. The result is returned in eax.

Parameters

eax (register)

The pointer to be converted (selector=high word, offset=lowword). This argument is not passed on the stack.

Dos32FlatToSel

Synopsis

ULONG Dos32FlatToSel(ULONG eax)

Description

This converts a 32 bit flat address to a 16:16 far pointer to be usable by 16 bit code. This routine is callable from 32 bit code. The result is returned in eax (selector=high word, offset=low word).

Parameters

eax (register)
The flat address to be converted. This argument is not passed on the stack.

Dos32SelToFlat

Synopsis

ULONG Dos32SelToFlat(ULONG eax)

Description

This converts a 16:16 far pointer to a 32 bit flat address to be usable by 32 bit code. This routine is callable from 32 bit code. The result is returned in eax.

Parameters

eax (register)
The pointer to be converted (selector=high word, offset=lowword).

This argument is not passed on the stack.