utthunk.c 8 KB
Newer Older
1 2 3
/*
 * Win32s Universal Thunk API
 *
4
 * Copyright 1999 Ulrich Weigand
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20
 */

21 22
#include <stdarg.h>

23
#include "wine/winbase16.h"
24 25
#include "windef.h"
#include "winbase.h"
26
#include "winternl.h"
27
#include "wownt32.h"
28
#include "wine/debug.h"
29

30
WINE_DEFAULT_DEBUG_CHANNEL(thunk);
31

32
#include "pshpack1.h"
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

typedef struct
{
    BYTE    popl_eax;
    BYTE    pushl;
    DWORD   target;
    BYTE    pushl_eax;
    BYTE    ljmp;
    DWORD   utglue16;

} UT16THUNK;

typedef struct
{
    BYTE    popl_eax;
    BYTE    pushl;
    DWORD   target;
    BYTE    pushl_eax;
    BYTE    jmp;
    DWORD   utglue32;

} UT32THUNK;

56
#include "poppack.h"
57

58
typedef struct _UTINFO
59
{
60
    struct _UTINFO    *next;
61 62
    HMODULE            hModule;
    HMODULE16          hModule16;
63

64 65 66 67 68
    UT16THUNK          ut16;
    UT32THUNK          ut32;

} UTINFO;

69 70
static UTINFO *UT_head; /* head of Universal Thunk list */

71
typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
72

73
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
74
                        LPSTR lpszInitName, LPSTR lpszProcName,
75
                        FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
76 77 78 79 80 81
                        LPVOID lpBuff );

VOID WINAPI UTUnRegister( HMODULE hModule );


/****************************************************************************
82
 *		UTGlue16 (KERNEL.666) (KERNEL Wine-specific export)
83
 */
84 85
DWORD WINAPI UTGlue16( LPVOID lpBuff, DWORD dwUserDefined, SEGPTR *translationList,
		       UTGLUEPROC target )
86 87 88 89 90 91 92 93
{
    INT i;

    /* Convert arguments to flat pointers */

    if ( translationList )
        for ( i = 0; translationList[i]; i++ )
        {
94 95
            LPVOID flatPtr = MapSL( translationList[i] );
            *(LPVOID *)flatPtr = MapSL( *(SEGPTR *)flatPtr );
96 97 98 99 100 101 102 103 104 105
        }

    /* Call 32-bit routine */

    return target( lpBuff, dwUserDefined );
}

/****************************************************************************
 *		UTGlue32
 */
106
static DWORD WINAPI UTGlue32( FARPROC16 target, LPVOID lpBuff, DWORD dwUserDefined,
Patrik Stridvall's avatar
Patrik Stridvall committed
107
                              LPVOID translationList[] )
108 109 110 111
{
    SEGPTR segBuff, *segptrList = NULL;
    INT i, nList = 0;
    DWORD retv;
112
    WORD args[4];
113 114 115 116 117 118 119 120 121 122 123 124

    /* Convert arguments to SEGPTRs */

    if ( translationList )
        for ( nList = 0; translationList[nList]; nList++ )
            ;

    if ( nList )
    {
        segptrList = HeapAlloc( GetProcessHeap(), 0, sizeof(SEGPTR)*nList );
        if ( !segptrList )
        {
125
            FIXME("Unable to allocate segptrList!\n" );
126 127 128 129
            return 0;
        }

        for ( i = 0; i < nList; i++ )
130
            segptrList[i] = *(SEGPTR *)translationList[i]
131 132 133 134 135 136 137
                          = MapLS( *(LPVOID *)translationList[i] );
    }

    segBuff = MapLS( lpBuff );

    /* Call 16-bit routine */

138 139 140 141 142
    args[3] = SELECTOROF(segBuff);
    args[2] = OFFSETOF(segBuff);
    args[1] = HIWORD(dwUserDefined);
    args[0] = LOWORD(dwUserDefined);
    WOWCallback16Ex( (DWORD)target, WCB16_PASCAL, sizeof(args), args, &retv );
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

    /* Free temporary selectors */

    UnMapLS( segBuff );

    if ( nList )
    {
        for ( i = 0; i < nList; i++ )
            UnMapLS( segptrList[i] );

        HeapFree( GetProcessHeap(), 0, segptrList );
    }

    return retv;
}

/****************************************************************************
 *		UTAlloc
 */
static UTINFO *UTAlloc( HMODULE hModule, HMODULE16 hModule16,
                        FARPROC16 target16, FARPROC target32 )
{
165 166 167 168 169
    static FARPROC16 UTGlue16_Segptr = NULL;
    UTINFO *ut;

    if ( !UTGlue16_Segptr )
    {
170 171
        HMODULE16 hModule = GetModuleHandle16( "KERNEL" );
        UTGlue16_Segptr = GetProcAddress16( hModule, "UTGlue16" );
172 173 174
        if ( !UTGlue16_Segptr ) return NULL;
    }

175
    ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
176 177 178 179 180 181 182 183 184 185
    if ( !ut ) return NULL;

    ut->hModule   = hModule;
    ut->hModule16 = hModule16;

    ut->ut16.popl_eax  = 0x58;
    ut->ut16.pushl     = 0x68;
    ut->ut16.target    = (DWORD)target32;
    ut->ut16.pushl_eax = 0x50;
    ut->ut16.ljmp      = 0xea;
186
    ut->ut16.utglue16  = (DWORD)UTGlue16_Segptr;
187 188 189 190 191 192 193 194

    ut->ut32.popl_eax  = 0x58;
    ut->ut32.pushl     = 0x68;
    ut->ut32.target    = (DWORD)target16;
    ut->ut32.pushl_eax = 0x50;
    ut->ut32.jmp       = 0xe9;
    ut->ut32.utglue32  = (DWORD)UTGlue32 - ((DWORD)&ut->ut32.utglue32 + sizeof(DWORD));

195 196
    ut->next = UT_head;
    UT_head = ut;
197 198 199 200 201 202 203 204 205 206 207

    return ut;
}

/****************************************************************************
 *		UTFree
 */
static void UTFree( UTINFO *ut )
{
    UTINFO **ptr;

208
    for ( ptr = &UT_head; *ptr; ptr = &(*ptr)->next )
209 210 211 212 213 214
        if ( *ptr == ut )
        {
            *ptr = ut->next;
            break;
        }

215
    HeapFree( GetProcessHeap(), 0, ut );
216 217 218 219 220 221 222 223 224
}

/****************************************************************************
 *		UTFind
 */
static UTINFO *UTFind( HMODULE hModule )
{
    UTINFO *ut;

225
    for ( ut = UT_head; ut; ut =ut->next )
226 227 228 229 230 231 232 233
        if ( ut->hModule == hModule )
            break;

    return ut;
}


/****************************************************************************
234
 *		UTRegister (KERNEL32.@)
235
 */
236
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
237
                        LPSTR lpszInitName, LPSTR lpszProcName,
238
                        FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
239 240 241
                        LPVOID lpBuff )
{
    UTINFO *ut;
242 243
    HMODULE16 hModule16;
    FARPROC16 target16, init16;
244 245 246 247

    /* Load 16-bit DLL and get UTProc16 entry point */

    if (   (hModule16 = LoadLibrary16( lpsz16BITDLL )) <= 32
248
        || (target16  = GetProcAddress16( hModule16, lpszProcName )) == 0 )
249 250 251 252
        return FALSE;

    /* Allocate UTINFO struct */

253
    RtlAcquirePebLock();
254 255 256 257
    if ( (ut = UTFind( hModule )) != NULL )
        ut = NULL;
    else
        ut = UTAlloc( hModule, hModule16, target16, pfnUT32CallBack );
258
    RtlReleasePebLock();
259 260 261 262 263 264 265 266 267 268

    if ( !ut )
    {
        FreeLibrary16( hModule16 );
        return FALSE;
    }

    /* Call UTInit16 if present */

    if (     lpszInitName
269
         && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
270
    {
271
        SEGPTR callback = MapLS( &ut->ut16 );
272
        SEGPTR segBuff  = MapLS( lpBuff );
273 274 275 276 277 278 279 280 281 282 283
        WORD args[4];
        DWORD ret;

        args[3] = SELECTOROF(callback);
        args[2] = OFFSETOF(callback);
        args[1] = SELECTOROF(segBuff);
        args[0] = OFFSETOF(segBuff);
        WOWCallback16Ex( (DWORD)init16, WCB16_PASCAL, sizeof(args), args, &ret );
        UnMapLS( segBuff );
        UnMapLS( callback );
        if (!ret)
284 285 286 287 288 289 290 291 292
        {
            UTUnRegister( hModule );
            return FALSE;
        }
    }

    /* Return 32-bit thunk */

    *ppfn32Thunk = (FARPROC) &ut->ut32;
293

294 295 296 297
    return TRUE;
}

/****************************************************************************
298
 *		UTUnRegister (KERNEL32.@)
299 300 301 302 303 304
 */
VOID WINAPI UTUnRegister( HMODULE hModule )
{
    UTINFO *ut;
    HMODULE16 hModule16 = 0;

305
    RtlAcquirePebLock();
306 307 308 309 310 311
    ut = UTFind( hModule );
    if ( !ut )
    {
        hModule16 = ut->hModule16;
        UTFree( ut );
    }
312
    RtlReleasePebLock();
313

314
    if ( hModule16 )
315 316 317 318
        FreeLibrary16( hModule16 );
}

/****************************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
319
 *		UTInit     (KERNEL.493)
320 321 322
 */
WORD WINAPI UTInit16( DWORD x1, DWORD x2, DWORD x3, DWORD x4 )
{
323
    FIXME("(%08lx, %08lx, %08lx, %08lx): stub\n", x1, x2, x3, x4 );
324 325
    return 0;
}