Some small corrections to the ExtTextOut function.
[wine] / relay32 / utthunk.c
1 /*
2  * Win32s Universal Thunk API
3  *
4  * Copyright 1999 Ulrich Weigand 
5  */
6
7 #include "wine/winbase16.h"
8 #include "windef.h"
9 #include "heap.h"
10 #include "module.h"
11 #include "selectors.h"
12 #include "callback.h"
13 #include "process.h"
14 #include "debugtools.h"
15 #include "debugstr.h"
16
17 DEFAULT_DEBUG_CHANNEL(thunk)
18
19 #include "pshpack1.h"
20
21 typedef struct
22 {
23     BYTE    popl_eax;
24     BYTE    pushl;
25     DWORD   target;
26     BYTE    pushl_eax;
27     BYTE    ljmp;
28     DWORD   utglue16;
29
30 } UT16THUNK;
31
32 typedef struct
33 {
34     BYTE    popl_eax;
35     BYTE    pushl;
36     DWORD   target;
37     BYTE    pushl_eax;
38     BYTE    jmp;
39     DWORD   utglue32;
40
41 } UT32THUNK;
42
43 #include "poppack.h"
44
45 typedef struct _UTINFO
46 {
47     struct _UTINFO    *next;
48     HMODULE            hModule;
49     HMODULE16          hModule16;
50     
51     UT16THUNK          ut16;
52     UT32THUNK          ut32;
53
54 } UTINFO;
55
56 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL, 
57                         LPSTR lpszInitName, LPSTR lpszProcName,
58                         FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack, 
59                         LPVOID lpBuff );
60
61 VOID WINAPI UTUnRegister( HMODULE hModule );
62
63
64 /****************************************************************************
65  *              UTGlue16     (WPROCS.*)
66  */
67 DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR translationList[], 
68                        DWORD (CALLBACK *target)( LPVOID lpBuff, DWORD dwUserDefined ) )
69 {
70     INT i;
71
72     /* Convert arguments to flat pointers */
73
74     if ( translationList )
75         for ( i = 0; translationList[i]; i++ )
76         {
77             LPVOID flatPtr = PTR_SEG_TO_LIN( translationList[i] );
78             *(LPVOID *)flatPtr = PTR_SEG_TO_LIN( *(SEGPTR *)flatPtr );
79         }
80
81     /* Call 32-bit routine */
82
83     return target( lpBuff, dwUserDefined );
84 }
85
86 /****************************************************************************
87  *              UTGlue32
88  */
89 static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined, 
90                               LPVOID translationList[] )
91 {
92     SEGPTR segBuff, *segptrList = NULL;
93     INT i, nList = 0;
94     DWORD retv;
95
96     /* Convert arguments to SEGPTRs */
97
98     if ( translationList )
99         for ( nList = 0; translationList[nList]; nList++ )
100             ;
101
102     if ( nList )
103     {
104         segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
105         if ( !segptrList )
106         {
107             FIXME("Unable to allocate segptrList!" );
108             return 0;
109         }
110
111         for ( i = 0; i < nList; i++ )
112             segptrList[i] = *(SEGPTR *)translationList[i] 
113                           = MapLS( *(LPVOID *)translationList[i] );
114     }
115
116     segBuff = MapLS( lpBuff );
117
118     /* Call 16-bit routine */
119
120     retv = Callbacks->CallUTProc( target, segBuff, dwUserDefined );
121
122     /* Free temporary selectors */
123
124     UnMapLS( segBuff );
125
126     if ( nList )
127     {
128         for ( i = 0; i < nList; i++ )
129             UnMapLS( segptrList[i] );
130
131         HeapFree( GetProcessHeap(), 0, segptrList );
132     }
133
134     return retv;
135 }
136
137 /****************************************************************************
138  *              UTAlloc
139  */
140 static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
141                         FARPROC16 target16, FARPROC target32 )
142 {
143     static FARPROC16 UTGlue16_Segptr = NULL;
144     UTINFO *ut;
145
146     if ( !UTGlue16_Segptr )
147     {
148         HMODULE16 hModule = GetModuleHandle16( "WPROCS" );
149         int       ordinal = NE_GetOrdinal( hModule, "UTGlue16" );
150         if ( hModule && ordinal )
151             UTGlue16_Segptr = NE_GetEntryPoint( hModule, ordinal );
152
153         if ( !UTGlue16_Segptr ) return NULL;
154     }
155
156     ut = HeapAlloc( SegptrHeap, HEAP_ZERO_MEMORY, sizeof(UTINFO) );
157     if ( !ut ) return NULL;
158
159     ut->hModule   = hModule;
160     ut->hModule16 = hModule16;
161
162     ut->ut16.popl_eax  = 0x58;
163     ut->ut16.pushl     = 0x68;
164     ut->ut16.target    = (DWORD)target32;
165     ut->ut16.pushl_eax = 0x50;
166     ut->ut16.ljmp      = 0xea;
167     ut->ut16.utglue16  = (DWORD)UTGlue16_Segptr;
168
169     ut->ut32.popl_eax  = 0x58;
170     ut->ut32.pushl     = 0x68;
171     ut->ut32.target    = (DWORD)target16;
172     ut->ut32.pushl_eax = 0x50;
173     ut->ut32.jmp       = 0xe9;
174     ut->ut32.utglue32  = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));
175
176     ut->next = PROCESS_Current()->UTState;
177     PROCESS_Current()->UTState = ut;
178
179     return ut;
180 }
181
182 /****************************************************************************
183  *              UTFree
184  */
185 static void UTFree( UTINFO *ut )
186 {
187     UTINFO **ptr;
188
189     for ( ptr = &PROCESS_Current()->UTState; *ptr; ptr = &(*ptr)->next )
190         if ( *ptr == ut )
191         {
192             *ptr = ut->next;
193             break;
194         }
195
196     HeapFree( SegptrHeap, 0, ut );
197 }
198
199 /****************************************************************************
200  *              UTFind
201  */
202 static UTINFO *UTFind( HMODULE hModule )
203 {
204     UTINFO *ut;
205
206     for ( ut = PROCESS_Current()->UTState; ut; ut =ut->next )
207         if ( ut->hModule == hModule )
208             break;
209
210     return ut;
211 }
212
213
214 /****************************************************************************
215  *              UTRegister (KERNEL32.697)
216  */
217 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL, 
218                         LPSTR lpszInitName, LPSTR lpszProcName,
219                         FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack, 
220                         LPVOID lpBuff )
221 {
222     UTINFO *ut;
223     HMODULE16 hModule16; 
224     FARPROC16 target16, init16; 
225
226     /* Load 16-bit DLL and get UTProc16 entry point */
227
228     if (   (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
229         || (target16  = WIN32_GetProcAddress16( hModule16, lpszProcName )) == 0 )
230         return FALSE;
231
232     /* Allocate UTINFO struct */
233
234     EnterCriticalSection( &PROCESS_Current()->crit_section );
235     if ( (ut = UTFind( hModule )) != NULL )
236         ut = NULL;
237     else
238         ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
239     LeaveCriticalSection( &PROCESS_Current()->crit_section );
240
241     if ( !ut )
242     {
243         FreeLibrary16( hModule16 );
244         return FALSE;
245     }
246
247     /* Call UTInit16 if present */
248
249     if (     lpszInitName
250          && (init16 = WIN32_GetProcAddress16( hModule16, lpszInitName )) != 0 )
251     {
252         SEGPTR callback = SEGPTR_GET( &ut->ut16 );
253         SEGPTR segBuff  = MapLS( lpBuff );
254
255         if ( !Callbacks->CallUTProc( init16, callback, segBuff ) )
256         {
257             UnMapLS( segBuff );
258             UTUnRegister( hModule );
259             return FALSE;
260         }
261         UnMapLS( segBuff );
262     }
263
264     /* Return 32-bit thunk */
265
266     *ppfn32Thunk = (FARPROC) &ut->ut32;
267     
268     return TRUE;
269 }
270
271 /****************************************************************************
272  *              UTUnRegister (KERNEL32.698)
273  */
274 VOID WINAPI UTUnRegister( HMODULE hModule )
275 {
276     UTINFO *ut;
277     HMODULE16 hModule16 = 0;
278
279     EnterCriticalSection( &PROCESS_Current()->crit_section );
280     ut = UTFind( hModule );
281     if ( !ut )
282     {
283         hModule16 = ut->hModule16;
284         UTFree( ut );
285     }
286     LeaveCriticalSection( &PROCESS_Current()->crit_section );
287
288     if ( hModule16 ) 
289         FreeLibrary16( hModule16 );
290 }
291
292 /****************************************************************************
293  *              UTInit16     (KERNEL.494)
294  */
295 WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
296 {
297     FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
298     return 0;
299 }
300