|
|
/*****************************************************************************
* * DiThunk.c * * Copyright (c) 1996-1997 Microsoft Corporation. All Rights Reserved. * * Abstract: * * Template thunks for Windows 95 device manager. * * Contents: * * Thunk_Init * Thunk_Term * *****************************************************************************/
#include "dinputpr.h"
#include "dithunk.h"
/*****************************************************************************
* * The sqiffle for this file. * *****************************************************************************/
#define sqfl sqflThunk
KERNELPROCADDR g_kpa;
#pragma BEGIN_CONST_DATA
/*
* Careful! This must match KERNELPROCADDR ... */ static LPCSTR c_rgpszKernel32[] = { (LPVOID) 35, /* LoadLibrary16 */ (LPVOID) 36, /* FreeLibrary16 */ (LPVOID) 37, /* GetProcAddress16 */
"MapLS", "UnMapLS", "MapSL", "MapSLFix", "UnMapSLFixArray", "QT_Thunk", };
/***************************************************************************
* * @doc INTERNAL * * @func DWORD | TemplateThunk | * * Call down, passing all sorts of random parameters. * * Parameter signature is as follows: * * p = 0:32 pointer to convert to 16:16 pointer * * l = a 32-bit integer * * s = a 16-bit integer * * * P = returns a pointer * * L = returns a 32-bit integer * * S = returns a 16-bit signed integer * * U = returns a 16-bit unsigned integer * ***************************************************************************/
#pragma warning(disable:4035) /* no return value (duh) */
#ifdef WIN95
#ifdef SLOW_BUT_READABLE
__declspec(naked) int TemplateThunk(FARPROC fp, PCSTR pszSig, ...) { BYTE rgbThunk[60]; /* For private use of QT_Thunk */ LPVOID *ppvArg; int i; LPVOID pv; int iRc;
__asm {
/* Function prologue */ push ebp; mov ebp, esp; sub esp, __LOCAL_SIZE; push ebx; push edi; push esi;
}
/* Thunk all the parameters according to the signature */ ppvArg = (LPVOID)(&pszSig+1); for (i = 0; ; i++) { pv = ppvArg[i]; switch (pszSig[i]) { case 'p': pv = ppvArg[i] = MapLS(pv); __asm push pv; break;
case 'l': __asm push pv; break;
case 's': __asm mov eax, pv; __asm push ax; break;
default: goto doneThunk; } }
doneThunk:;
/* Call the 16:16 procedure */ __asm { mov edx, fp; mov ebx, ebp; lea ebp, rgbThunk+64; /* Required by QT_Thunk */ } g_kpa.QT_Thunk(); __asm { mov ebp, ebx; shl eax, 16; /* Convert DX:AX to EAX */ shrd eax, edx, 16; mov iRc, eax; }
/* Now unthunk the parameters */ ppvArg = (LPVOID)(&pszSig+1); for (i = 0; ; i++) { switch (pszSig[i]) { case 'p': UnMapLS(ppvArg[i]); break;
case 'l': case 's': break;
default: goto doneUnthunk; } }
doneUnthunk:;
/* Thunk the return value */ switch (pszSig[i]) { case 'L': break;
case 'U': iRc = LOWORD(iRc); break;
case 'S': iRc = (short)iRc; break;
case 'P': iRc = (int)MapSL((LPVOID)iRc); break; }
__asm { mov eax, iRc; pop esi; pop edi; pop ebx; mov esp, ebp; pop ebp; ret; } }
#else /* Fast but illegible */
__declspec(naked) int TemplateThunk(FARPROC fp, PCSTR pszSig, ...) { __asm {
/* Function prologue */ push ebp; mov ebp, esp; sub esp, 60; /* QT_Thunk needs 60 bytes */ push ebx; push edi; push esi;
/* Thunk all the parameters according to the signature */
lea esi, pszSig+4; /* esi -> next arg */ mov ebx, pszSig; /* ebx -> signature string */ thunkLoop:; mov al, [ebx]; inc ebx; /* al = pszSig++ */ cmp al, 'p'; /* Q: Pointer? */ jz thunkPtr; /* Y: Do the pointer */ cmp al, 'l'; /* Q: Long? */ jz thunkLong; /* Y: Do the long */ cmp al, 's'; /* Q: Short? */ jnz thunkDone; /* N: Done */
/* Y: Do the short */ lodsd; /* eax = *ppvArg++ */ push ax; /* Push the short */ jmp thunkLoop;
thunkPtr: lodsd; /* eax = *ppvArg++ */ push eax; call dword ptr g_kpa.MapLS; /* Map it */ mov [esi][-4], eax; /* Save it for unmapping */ push eax; jmp thunkLoop;
thunkLong: lodsd; /* eax = *ppvArg++ */ push eax; jmp thunkLoop; thunkDone:
/* Call the 16:16 procedure */
mov edx, fp; call dword ptr g_kpa.QT_Thunk; shl eax, 16; /* Convert DX:AX to EDX */ shld edx, eax, 16;
/* Translate the return code according to the signature */
mov al, [ebx][-1]; /* Get return code type */ cmp al, 'P'; /* Pointer? */ jz retvalPtr; /* Y: Do the pointer */ cmp al, 'S'; /* Signed? */ jz retvalSigned; /* Y: Do the signed short */ cmp al, 'U'; /* Unsigned? */ mov edi, edx; /* Assume long or void */ jnz retvalOk; /* N: Then long or void */
movzx edi, dx; /* Sign-extend short */ jmp retvalOk;
retvalPtr: push edx; /* Pointer */ call dword ptr g_kpa.MapSL; /* Map it up */ jmp retvalOk;
retvalSigned: /* Signed */ movsx edi, dx; /* Sign-extend short */ jmp retvalOk;
retvalOk: /* Return value in EDI */
/* Now unthunk the parameters */
lea esi, pszSig+4; /* esi -> next arg */ mov ebx, pszSig; /* ebx -> signature string */ unthunkLoop:; mov al, [ebx]; inc ebx; /* al = pszSig++ */ cmp al, 'p'; /* Pointer? */ jz unthunkPtr; /* Y: Do the pointer */ cmp al, 'l'; /* Long? */ jz unthunkSkip; /* Y: Skip it */ cmp al, 's'; /* Short? */ jnz unthunkDone; /* N: Done */ unthunkSkip: lodsd; /* eax = *ppvArg++ */ jmp unthunkLoop;
unthunkPtr: lodsd; /* eax = *ppvArg++ */ push eax; call dword ptr g_kpa.UnMapLS;/* Unmap it */ jmp unthunkLoop;
unthunkDone:
/* Done */
mov eax, edi; pop esi; pop edi; pop ebx; mov esp, ebp; pop ebp; ret; } }
#endif
#else // Not X86
int __cdecl TemplateThunk(FARPROC fp, PCSTR pszSig, ...) { return 0; } #endif
#pragma BEGIN_CONST_DATA
/***************************************************************************
* * @doc INTERNAL * * @func FARPROC | GetProcOrd | * * GetProcAddress on a DLL by ordinal. * * Win95 does not let you GetProcAddress on KERNEL32 by ordinal, * so we need to do it the evil way. * * @parm HINSTANCE | hinstDll | * * The instance handle of the DLL we want to get the ordinal * from. The only DLL you need to use this function for is * KERNEL32. * * @parm UINT | ord | * * The ordinal you want to retrieve. * ***************************************************************************/
#define poteExp(pinth) (&(pinth)->OptionalHeader. \
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT])
FARPROC NTAPI GetProcOrd(HINSTANCE hinstDll, UINT ord) { FARPROC fp;
/*
* Make sure the MZ header is good. */
PIMAGE_DOS_HEADER pidh = (LPVOID)hinstDll; if (!IsBadReadPtr(pidh, sizeof(*pidh)) && pidh->e_magic == IMAGE_DOS_SIGNATURE) {
/*
* Make sure the PE header is good. */ PIMAGE_NT_HEADERS pinth = pvAddPvCb(pidh, pidh->e_lfanew); if (!IsBadReadPtr(pinth, sizeof(*pinth)) && pinth->Signature == IMAGE_NT_SIGNATURE) {
/*
* Make sure the export table is good and the ordinal * is within range. */ PIMAGE_EXPORT_DIRECTORY pedt = pvAddPvCb(pidh, poteExp(pinth)->VirtualAddress); if (!IsBadReadPtr(pedt, sizeof(*pedt)) && (ord - pedt->Base) < pedt->NumberOfFunctions) {
PDWORD peat = pvAddPvCb(pidh, (DWORD)pedt->AddressOfFunctions); fp = (FARPROC)pvAddPvCb(pidh, peat[ord - pedt->Base]); if ((DWORD)cbSubPvPv(fp, peat) >= poteExp(pinth)->Size) { /* fp is valid */ } else { /* Note: We don't support forwarding */ fp = 0; } } else { fp = 0; } } else { fp = 0; } } else { fp = 0; }
return fp; }
/***************************************************************************
* * @doc INTERNAL * * @func BOOL | GetKernelProcAddresses | * * Get all the necessary proc addresses from Kernel. * ***************************************************************************/
BOOL EXTERNAL Thunk_GetKernelProcAddresses(void) { DllEnterCrit();
if (g_kpa.QT_Thunk == 0) { HINSTANCE hinstK32 = GetModuleHandle(TEXT("KERNEL32"));
if (hinstK32) { int i; FARPROC *rgfpKpa = (LPVOID)&g_kpa;
for (i = 0; i < cA(c_rgpszKernel32); i++) { if (HIWORD((UINT_PTR)c_rgpszKernel32[i])) { rgfpKpa[i] = GetProcAddress(hinstK32, c_rgpszKernel32[i]); } else { rgfpKpa[i] = GetProcOrd(hinstK32, (UINT)(UINT_PTR)c_rgpszKernel32[i]); } if (!rgfpKpa[i]) break; /* Aigh! */ } } }
DllLeaveCrit();
return (BOOL)(UINT_PTR)g_kpa.QT_Thunk;
}
/***************************************************************************
* * @doc INTERNAL * * @func HINSTANCE | ThunkGetProcAddresses | * * Get all the necessary proc addresses. * ***************************************************************************/
HINSTANCE EXTERNAL Thunk_GetProcAddresses(FARPROC *rgfp, LPCSTR *rgpsz, UINT cfp, LPCSTR pszLibrary) { HINSTANCE hinst;
hinst = g_kpa.LoadLibrary16(pszLibrary); if (hinst >= (HINSTANCE)32) { UINT ifp; for (ifp = 0; ifp < cfp; ifp++) { rgfp[ifp] = g_kpa.GetProcAddress16(hinst, rgpsz[ifp]); if (!rgfp[ifp]) { g_kpa.FreeLibrary16(hinst); hinst = 0; break; } } } else { hinst = 0; }
return hinst;
}
|