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