utthunk.c 8.03 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 18
 *
 * 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
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 20
 */

21 22
#include <stdarg.h>

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

32
WINE_DEFAULT_DEBUG_CHANNEL(thunk);
33

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

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;

58
#include "poppack.h"
59

60
typedef struct _UTINFO
61
{
62
    struct _UTINFO    *next;
63 64
    HMODULE            hModule;
    HMODULE16          hModule16;
65

66 67 68 69 70
    UT16THUNK          ut16;
    UT32THUNK          ut32;

} UTINFO;

71 72
static UTINFO *UT_head; /* head of Universal Thunk list */

73
typedef DWORD (CALLBACK *UTGLUEPROC)( LPVOID lpBuff, DWORD dwUserDefined );
74

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

VOID WINAPI UTUnRegister( HMODULE hModule );


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

    /* Convert arguments to flat pointers */

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

    /* Call 32-bit routine */

    return target( lpBuff, dwUserDefined );
}

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

    /* Convert arguments to SEGPTRs */

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

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

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

    segBuff = MapLS( lpBuff );

    /* Call 16-bit routine */

140 141 142 143 144
    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 );
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

    /* 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 )
{
167 168 169 170 171
    static FARPROC16 UTGlue16_Segptr = NULL;
    UTINFO *ut;

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

177
    ut = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UTINFO) );
178 179 180 181 182 183 184 185 186 187
    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;
188
    ut->ut16.utglue16  = (DWORD)UTGlue16_Segptr;
189 190 191 192 193 194 195 196

    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));

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

    return ut;
}

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

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

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

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

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

    return ut;
}


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

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

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

    /* Allocate UTINFO struct */

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

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

    /* Call UTInit16 if present */

    if (     lpszInitName
271
         && (init16 = GetProcAddress16( hModule16, lpszInitName )) != 0 )
272
    {
273
        SEGPTR callback = MapLS( &ut->ut16 );
274
        SEGPTR segBuff  = MapLS( lpBuff );
275 276 277 278 279 280 281 282 283 284 285
        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)
286 287 288 289 290 291 292 293 294
        {
            UTUnRegister( hModule );
            return FALSE;
        }
    }

    /* Return 32-bit thunk */

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

296 297 298 299
    return TRUE;
}

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

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

316
    if ( hModule16 )
317 318 319 320
        FreeLibrary16( hModule16 );
}

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