Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

510 lines
12 KiB

/********************************************************************
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)