|
|
/********************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name: thunk.c
Abstract: Thunk procedures for calling 16-bit functions
Revision History:
Brijesh Krishnaswami (brijeshk) 05/24/99 - created (imported from msinfo codebase) ********************************************************************/
#include <windows.h>
#include "drvdefs.h"
/***************************************************************************
* * @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
__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
} 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; } }
#pragma warning(default:4035)
/***************************************************************************
* * Functions we call down in Win16. * ***************************************************************************/
FARPROC g_rgfpKernel[] = { (FARPROC)132, /* GetWinFlags */ (FARPROC)355, /* GetWinDebugInfo */ (FARPROC)169, /* GetFreeSpace */ (FARPROC) 47, /* GetModuleHandle */ (FARPROC) 93, /* GetCodeHandle */ (FARPROC)104, /* GetCodeInfo */ (FARPROC) 49, /* GetModuleFileName */ (FARPROC)175, /* AllocSelector */ (FARPROC)186, /* GetSelectorBase */ (FARPROC)187, /* SetSelectorBase */ (FARPROC)188, /* GetSelectorLimit */ (FARPROC)189, /* SetSelectorLimit */ (FARPROC)176, /* FreeSelector */ (FARPROC) 27, /* GetModuleName */ (FARPROC)167, /* GetExpWinVer */ (FARPROC)184, /* GlobalDosAlloc */ (FARPROC)185, /* GlobalDosFree */ (FARPROC) 16, /* GlobalReAlloc */ };
#define g_fpGetWinFlags g_rgfpKernel[0]
#define g_fpGetWinDebugInfo g_rgfpKernel[1]
#define g_fpGetFreeSpace g_rgfpKernel[2]
#define g_fpGetModuleHandle g_rgfpKernel[3]
#define g_fpGetCodeHandle g_rgfpKernel[4]
#define g_fpGetCodeInfo g_rgfpKernel[5]
#define g_fpGetModuleFileName g_rgfpKernel[6]
#define g_fpAllocSelector g_rgfpKernel[7]
#define g_fpGetSelectorBase g_rgfpKernel[8]
#define g_fpSetSelectorBase g_rgfpKernel[9]
#define g_fpGetSelectorLimit g_rgfpKernel[10]
#define g_fpSetSelectorLimit g_rgfpKernel[11]
#define g_fpFreeSelector g_rgfpKernel[12]
#define g_fpGetModuleName g_rgfpKernel[13]
#define g_fpGetExpWinVer g_rgfpKernel[14]
#define g_fpGlobalDosAlloc g_rgfpKernel[15]
#define g_fpGlobalDosFree g_rgfpKernel[16]
#define g_fpGlobalReAlloc g_rgfpKernel[17]
FARPROC g_rgfpUser[] = { (FARPROC)216, /* UserSeeUserDo */ (FARPROC)284, /* GetFreeSystemResources */ (FARPROC)256, /* GetDriverInfo */ (FARPROC)257, /* GetNextDriver */ };
#define g_fpUserSeeUserDo g_rgfpUser[0]
#define g_fpGetFreeSystemResources g_rgfpUser[1]
#define g_fpGetDriverInfo g_rgfpUser[2]
#define g_fpGetNextDriver g_rgfpUser[3]
/***************************************************************************
* * @doc INTERNAL * * @func void | ThunkGetProcAddresses | * * Get all the necessary proc addresses. * ***************************************************************************/
HINSTANCE ThunkGetProcAddresses(FARPROC *rgfp, UINT cfp, LPCTSTR ptszLibrary, BOOL fFree) { HINSTANCE hinst;
hinst = LoadLibrary16(ptszLibrary); if (hinst >= (HINSTANCE)32) { UINT ifp; for (ifp = 0; ifp < cfp; ifp++) { rgfp[ifp] = GetProcAddress16(hinst, (PVOID)rgfp[ifp]); }
if (fFree) { FreeLibrary16(hinst); }
} else { hinst = 0; }
return hinst;
}
/***************************************************************************
* * @doc INTERNAL * * @func void | ThunkInit | * * GetProcAddress16 our brains out. * ***************************************************************************/
LPVOID g_pvWin16Lock = NULL; HINSTANCE g_hinstUser;
void ThunkInit(void) { if (g_pvWin16Lock == NULL) { ThunkGetProcAddresses(g_rgfpKernel, cA(g_rgfpKernel), TEXT("KERNEL"), 1); g_hinstUser = ThunkGetProcAddresses(g_rgfpUser, cA(g_rgfpUser), TEXT("USER"), 1); GetpWin16Lock(&g_pvWin16Lock); } }
HMODULE16 GetModuleHandle16(LPCSTR pszModule) { return (HMODULE16)TemplateThunk(g_fpGetModuleHandle, "pU", pszModule); }
int GetModuleFileName16(HMODULE16 hmod, LPSTR sz, int cch) { return TemplateThunk(g_fpGetModuleFileName, "spsS", hmod, sz, cch); }
int GetModuleName16(HMODULE16 hmod, LPSTR sz, int cch) { return TemplateThunk(g_fpGetModuleName, "spsS", hmod, sz, cch); }
UINT AllocCodeSelector16(void) { return TemplateThunk(g_fpAllocSelector, "sU", HIWORD(g_fpAllocSelector)); }
DWORD GetSelectorBase16(UINT sel) { return TemplateThunk(g_fpGetSelectorBase, "sL", sel); }
UINT SetSelectorBase16(UINT sel, DWORD dwBase) { return TemplateThunk(g_fpSetSelectorBase, "slU", sel, dwBase); }
DWORD GetSelectorLimit16(UINT sel) { return TemplateThunk(g_fpGetSelectorLimit, "sL", sel); }
UINT SetSelectorLimit16(UINT sel, DWORD dwLimit) { return TemplateThunk(g_fpSetSelectorLimit, "slU", sel, dwLimit); }
UINT FreeSelector16(UINT sel) { return TemplateThunk(g_fpFreeSelector, "sU", sel); }
WORD GetExpWinVer16(HMODULE16 hmod) { return (WORD)TemplateThunk(g_fpGetExpWinVer, "sS", hmod); }
DWORD GlobalDosAlloc16(DWORD cb) { return (DWORD)TemplateThunk(g_fpGlobalDosAlloc, "lL", cb); }
UINT GlobalDosFree16(UINT uiSel) { return (UINT)TemplateThunk(g_fpGlobalDosFree, "sS", uiSel); }
/*
* Kernel has thunks for GlobalAlloc, GlobalFree, but not GlobalRealloc. */ WORD GlobalReAlloc16(WORD hglob, DWORD cb, UINT fl) { return (WORD)TemplateThunk(g_fpGlobalReAlloc, "slsS", hglob, cb, fl); }
#define SD_ATOMNAME 0x000E
UINT GetUserAtomName(UINT atom, LPSTR psz) { return (UINT)TemplateThunk(g_fpUserSeeUserDo, "sspS", SD_ATOMNAME, atom, psz); }
#define SD_GETRGPHKSYSHOOKS 0x0010
DWORD GetUserHookTable(void) { return (UINT)TemplateThunk(g_fpUserSeeUserDo, "sslL", SD_GETRGPHKSYSHOOKS, 0, 0); }
BOOL GetDriverInfo16(WORD hDriver, DRIVERINFOSTRUCT16* pdis) { return (BOOL)TemplateThunk(g_fpGetDriverInfo, "spS", hDriver, pdis); }
WORD GetNextDriver16(WORD hDriver, DWORD fdwFlag) { return (WORD)TemplateThunk(g_fpGetNextDriver, "slS", hDriver, fdwFlag);
}
/***************************************************************************
* * @doc INTERNAL * * @func BOOL | Int86x | * * Issue a real-mode software interrupt. * * We do this by allocating a temporary code selector and * thunking to it. * * ***************************************************************************/
BYTE rgbInt31[] = { 0x55, /* push bp */ 0x8B, 0xEC, /* mov bp, sp */ 0x57, /* push di */ 0xC4, 0x7E, 0x06, /* les di, [bp+6] */ 0x8B, 0x5E, 0x0A, /* mov bx, [bp+10] */ 0x33, 0xC9, /* xor cx, cx */ 0xB8, 0x00, 0x03, /* mov ax, 0300h */ 0xCD, 0x31, /* int 31h */ 0x72, 0x02, /* jc $+4 */ 0x33, 0xC0, /* xor ax, ax */ 0x5F, /* pop di */ 0x5D, /* pop bp */ 0xCA, 0x06, 0x00, /* retf 6 */ };
UINT Int86x(UINT intno, PRMIREGS preg) { UINT selCode = AllocCodeSelector16(); UINT uiRc; if (selCode) { SetSelectorBase16(selCode, (DWORD)rgbInt31); SetSelectorLimit16(selCode, sizeof(rgbInt31)); preg->ss = preg->sp = 0; uiRc = (UINT)TemplateThunk((FARPROC)MAKELONG(0, selCode), "spU", intno, preg); FreeSelector16(selCode); } else { uiRc = 0x8011; /* Descriptor unavailable */ } return uiRc; }
/***************************************************************************
* * @doc INTERNAL : ported from msinfo 4.10 code * * @func Token_Find | * * Returns the first token in the string. * * Tokens are space or comma separated strings. Quotation marks * have no effect. We also treat semicolons as separators. * (This lets us use this routine for walking the PATH too.) * * *pptsz is modified in place to contain a pointer that can * be passed subsequently to Token_Find to pull the next token. * ***************************************************************************/ LPTSTR Token_Find(LPTSTR *pptsz) { LPTSTR ptsz = *pptsz; while (*ptsz) {
/*
* Skip leading separators. */ while (*ptsz == TEXT(' ') || *ptsz == TEXT(',') || *ptsz == TEXT(';')) { ptsz++; }
if (*ptsz) { LPTSTR ptszStart = ptsz;
/*
* Skip until we see a separator. */ while (*ptsz != TEXT('\0') && *ptsz != TEXT(' ') && *ptsz != TEXT(',') && *ptsz != TEXT(';')) { ptsz++; }
/*
* Wipe out the separator, and advance ptsz past it * if there is something after it. (Don't advance * it beyond the end of the string!) */ if (*ptsz) { *ptsz++ = 0; } *pptsz = ptsz;
return ptszStart;
} else { break; } } return 0; }
#pragma warning(default:4035)
|