2 * Win32s Universal Thunk API
4 * Copyright 1999 Ulrich Weigand
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "wine/winbase16.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(thunk
);
55 typedef struct _UTINFO
66 static UTINFO
*UT_head
; /* head of Universal Thunk list */
68 typedef DWORD (CALLBACK
*UTGLUEPROC
)( LPVOID lpBuff
, DWORD dwUserDefined
);
70 BOOL WINAPI
UTRegister( HMODULE hModule
, LPSTR lpsz16BITDLL
,
71 LPSTR lpszInitName
, LPSTR lpszProcName
,
72 FARPROC
*ppfn32Thunk
, FARPROC pfnUT32CallBack
,
75 VOID WINAPI
UTUnRegister( HMODULE hModule
);
78 /****************************************************************************
79 * UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
81 DWORD WINAPI
UTGlue16( LPVOID lpBuff
, DWORD dwUserDefined
, SEGPTR
*translationList
,
86 /* Convert arguments to flat pointers */
88 if ( translationList
)
89 for ( i
= 0; translationList
[i
]; i
++ )
91 LPVOID flatPtr
= MapSL( translationList
[i
] );
92 *(LPVOID
*)flatPtr
= MapSL( *(SEGPTR
*)flatPtr
);
95 /* Call 32-bit routine */
97 return target( lpBuff
, dwUserDefined
);
100 /****************************************************************************
103 static DWORD WINAPI
UTGlue32( FARPROC16 target
, LPVOID lpBuff
, DWORD dwUserDefined
,
104 LPVOID translationList
[] )
106 SEGPTR segBuff
, *segptrList
= NULL
;
111 /* Convert arguments to SEGPTRs */
113 if ( translationList
)
114 for ( nList
= 0; translationList
[nList
]; nList
++ )
119 segptrList
= HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR
)*nList
);
122 FIXME("Unable to allocate segptrList!\n" );
126 for ( i
= 0; i
< nList
; i
++ )
127 segptrList
[i
] = *(SEGPTR
*)translationList
[i
]
128 = MapLS( *(LPVOID
*)translationList
[i
] );
131 segBuff
= MapLS( lpBuff
);
133 /* Call 16-bit routine */
135 args
[3] = SELECTOROF(segBuff
);
136 args
[2] = OFFSETOF(segBuff
);
137 args
[1] = HIWORD(dwUserDefined
);
138 args
[0] = LOWORD(dwUserDefined
);
139 WOWCallback16Ex( (DWORD
)target
, WCB16_PASCAL
, sizeof(args
), args
, &retv
);
141 /* Free temporary selectors */
147 for ( i
= 0; i
< nList
; i
++ )
148 UnMapLS( segptrList
[i
] );
150 HeapFree( GetProcessHeap(), 0, segptrList
);
156 /****************************************************************************
159 static UTINFO
*UTAlloc( HMODULE hModule
, HMODULE16 hModule16
,
160 FARPROC16 target16
, FARPROC target32
)
162 static FARPROC16 UTGlue16_Segptr
= NULL
;
165 if ( !UTGlue16_Segptr
)
167 HMODULE16 hModule
= GetModuleHandle16( "KERNEL" );
168 UTGlue16_Segptr
= GetProcAddress16( hModule
, "UTGlue16" );
169 if ( !UTGlue16_Segptr
) return NULL
;
172 ut
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(UTINFO
) );
173 if ( !ut
) return NULL
;
175 ut
->hModule
= hModule
;
176 ut
->hModule16
= hModule16
;
178 ut
->ut16
.popl_eax
= 0x58;
179 ut
->ut16
.pushl
= 0x68;
180 ut
->ut16
.target
= (DWORD
)target32
;
181 ut
->ut16
.pushl_eax
= 0x50;
182 ut
->ut16
.ljmp
= 0xea;
183 ut
->ut16
.utglue16
= (DWORD
)UTGlue16_Segptr
;
185 ut
->ut32
.popl_eax
= 0x58;
186 ut
->ut32
.pushl
= 0x68;
187 ut
->ut32
.target
= (DWORD
)target16
;
188 ut
->ut32
.pushl_eax
= 0x50;
190 ut
->ut32
.utglue32
= (DWORD
)UTGlue32
- ((DWORD
)&ut
->ut32
.utglue32
+ sizeof(DWORD
));
198 /****************************************************************************
201 static void UTFree( UTINFO
*ut
)
205 for ( ptr
= &UT_head
; *ptr
; ptr
= &(*ptr
)->next
)
212 HeapFree( GetProcessHeap(), 0, ut
);
215 /****************************************************************************
218 static UTINFO
*UTFind( HMODULE hModule
)
222 for ( ut
= UT_head
; ut
; ut
=ut
->next
)
223 if ( ut
->hModule
== hModule
)
230 /****************************************************************************
231 * UTRegister (KERNEL32.@)
233 BOOL WINAPI
UTRegister( HMODULE hModule
, LPSTR lpsz16BITDLL
,
234 LPSTR lpszInitName
, LPSTR lpszProcName
,
235 FARPROC
*ppfn32Thunk
, FARPROC pfnUT32CallBack
,
240 FARPROC16 target16
, init16
;
242 /* Load 16-bit DLL and get UTProc16 entry point */
244 if ( (hModule16
= LoadLibrary16( lpsz16BITDLL
)) <= 32
245 || (target16
= GetProcAddress16( hModule16
, lpszProcName
)) == 0 )
248 /* Allocate UTINFO struct */
251 if ( (ut
= UTFind( hModule
)) != NULL
)
254 ut
= UTAlloc( hModule
, hModule16
, target16
, pfnUT32CallBack
);
259 FreeLibrary16( hModule16
);
263 /* Call UTInit16 if present */
266 && (init16
= GetProcAddress16( hModule16
, lpszInitName
)) != 0 )
268 SEGPTR callback
= MapLS( &ut
->ut16
);
269 SEGPTR segBuff
= MapLS( lpBuff
);
273 args
[3] = SELECTOROF(callback
);
274 args
[2] = OFFSETOF(callback
);
275 args
[1] = SELECTOROF(segBuff
);
276 args
[0] = OFFSETOF(segBuff
);
277 WOWCallback16Ex( (DWORD
)init16
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
282 UTUnRegister( hModule
);
287 /* Return 32-bit thunk */
289 *ppfn32Thunk
= (FARPROC
) &ut
->ut32
;
294 /****************************************************************************
295 * UTUnRegister (KERNEL32.@)
297 VOID WINAPI
UTUnRegister( HMODULE hModule
)
300 HMODULE16 hModule16
= 0;
303 ut
= UTFind( hModule
);
306 hModule16
= ut
->hModule16
;
312 FreeLibrary16( hModule16
);
315 /****************************************************************************
316 * UTInit (KERNEL.493)
318 WORD WINAPI
UTInit16( DWORD x1
, DWORD x2
, DWORD x3
, DWORD x4
)
320 FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1
, x2
, x3
, x4
);