Leaked source code of windows server 2003
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.
 
 
 
 
 
 

758 lines
27 KiB

/*****************************************************************************
*
* Thunk.c
*
* Copyright (c) 1996 - 1999 Microsoft Corporation. All Rights Reserved.
*
* Abstract:
*
* Thunking to 16-bit code without using the thunk compiler.
* This is important if you want your DLL to run on both Win95
* and Windows NT.
*
*****************************************************************************/
#pragma warning(disable:4054) /* cannot cast to function ptr */
#pragma warning(disable:4055) /* cannot cast from function ptr */
#pragma warning(disable:4115) /* rpcndr.h: parenthesized type */
#pragma warning(disable:4201) /* winnt.h: nameless union */
#pragma warning(disable:4214) /* winnt.h: unsigned bitfields */
#pragma warning(disable:4514) /* winnt.h: fiber goo */
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
#include <pshpack1.h> /* Byte packing, please */
#define BEGIN_CONST_DATA data_seg(".text", "CODE")
#define END_CONST_DATA data_seg(".data", "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 pvAdd(pv, cb) ((LPVOID)((LPSTR)(pv) + (DWORD)(cb)))
#define pvSub(pv1, pv2) (DWORD)((LPSTR)(pv1) - (LPSTR)(pv2))
#define poteExp(pinth) (&(pinth)->OptionalHeader. \
DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT])
FARPROC NTAPI
GetProcOrd(HINSTANCE hinstDll, UINT_PTR 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 = pvAdd(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 =
pvAdd(pidh, poteExp(pinth)->VirtualAddress);
if (!IsBadReadPtr(pedt, sizeof(*pedt)) &&
(ord - pedt->Base) < pedt->NumberOfFunctions) {
PDWORD peat = pvAdd(pidh, pedt->AddressOfFunctions);
fp = (FARPROC)pvAdd(pidh, peat[ord - pedt->Base]);
if (pvSub(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;
}
/***************************************************************************
*
* This structure starts out life as the things that we will GetProcAddress
* for. And then it turns into pointers to functions.
*
***************************************************************************/
#pragma BEGIN_CONST_DATA
static TCHAR c_tszKernel32[] = TEXT("KERNEL32");
static LPCSTR c_rgpszKernel32[] = {
(LPVOID) 35, /* LoadLibrary16 */
(LPVOID) 36, /* FreeLibrary16 */
(LPVOID) 37, /* GetProcAddress16 */
"QT_Thunk",
"MapLS",
"UnMapLS",
"MapSL",
"MapSLFix",
};
#pragma END_CONST_DATA
typedef struct MANUALIMPORTTABLE { /* mit */
/* By ordinal */
HINSTANCE (NTAPI *LoadLibrary16)(LPCSTR);
BOOL (NTAPI *FreeLibrary16)(HINSTANCE);
FARPROC (NTAPI *GetProcAddress16)(HINSTANCE, LPCSTR);
/* By name */
void (__cdecl *QT_Thunk)(void);
LPVOID (NTAPI *MapLS)(LPVOID);
void (NTAPI *UnMapLS)(LPVOID);
LPVOID (NTAPI *MapSL)(LPVOID);
LPVOID (NTAPI *MapSLFix)(LPVOID);
} MIT;
static MIT s_mit;
/***************************************************************************
*
* @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
*
* @parm FARPROC | fp |
*
* 16:16 function to call.
*
* @parm PCSTR | pszSig |
*
* Function signature.
*
***************************************************************************/
#pragma warning(disable:4035) /* no return value (duh) */
#ifndef NON_X86
__declspec(naked) DWORD
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 s_mit.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 s_mit.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 s_mit.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 s_mit.UnMapLS; /* Unmap it */
jmp unthunkLoop;
unthunkDone:
/* Done */
mov eax, edi;
pop esi;
pop edi;
pop ebx;
mov esp, ebp;
pop ebp;
ret;
}
}
#else
TemplateThunk(FARPROC fp, PCSTR pszSig, ...)
{
return 0;
}
#endif
#pragma warning(default:4035)
/***************************************************************************
*
* @doc INTERNAL
*
* @func void | ThunkInit |
*
* Initialize the various goo we need in KERNEL32.
*
* Returns FALSE if we cannot initialize the thunks.
* (For example, if the platform doesn't support flat thunks.)
*
* Note that you must never ever call this function more
* than once.
*
***************************************************************************/
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
#endif
#pragma BEGIN_CONST_DATA
static char c_szVidx16[] = "VIDX16.DLL";
static LPCSTR c_rgpszVidx16[] = {
(LPCSTR)6, /* vidxAllocHeaders */
(LPCSTR)7, /* vidxFreeHeaders */
(LPCSTR)8, /* vidxAllocBuffer */
(LPCSTR)9, /* vidxAllocPreviewBuffer */
(LPCSTR)10, /* vidxFreeBuffer */
(LPCSTR)11, /* vidxSetRect */
(LPCSTR)12, /* vidxFrame */
(LPCSTR)13, /* vidxAddBuffer */
(LPCSTR)14, /* vidxGetErrorText */
(LPCSTR)15, /* vidxUpdate */
(LPCSTR)16, /* vidxDialog */
(LPCSTR)17, /* vidxStreamInit */
(LPCSTR)18, /* vidxStreamFini */
(LPCSTR)19, /* vidxConfigure */
(LPCSTR)20, /* vidxOpen */
(LPCSTR)21, /* vidxClose */
(LPCSTR)22, /* vidxGetChannelCaps */
(LPCSTR)23, /* vidxStreamReset */
(LPCSTR)24, /* vidxStreamStart */
(LPCSTR)25, /* vidxStreamStop */
(LPCSTR)26, /* vidxStreamUnprepareHeader */
(LPCSTR)27, /* vidxCapDriverDescAndVer */
(LPCSTR)28, /* vidxMessage */
(LPCSTR)29, /* vidxFreePreviewBuffer */
};
#pragma END_CONST_DATA
static HINSTANCE s_hinstVidx16;
static FARPROC s_rgfpVidx16[ARRAYSIZE(c_rgpszVidx16)];
#define s_fpvidxAllocHeaders s_rgfpVidx16[0]
#define s_fpvidxFreeHeaders s_rgfpVidx16[1]
#define s_fpvidxAllocBuffer s_rgfpVidx16[2]
#define s_fpvidxAllocPreviewBuffer s_rgfpVidx16[3]
#define s_fpvidxFreeBuffer s_rgfpVidx16[4]
#define s_fpvidxSetRect s_rgfpVidx16[5]
#define s_fpvidxFrame s_rgfpVidx16[6]
#define s_fpvidxAddBuffer s_rgfpVidx16[7]
#define s_fpvideoGetErrorText s_rgfpVidx16[8]
#define s_fpvideoUpdate s_rgfpVidx16[9]
#define s_fpvideoDialog s_rgfpVidx16[10]
#define s_fpvideoStreamInit s_rgfpVidx16[11]
#define s_fpvideoStreamFini s_rgfpVidx16[12]
#define s_fpvideoConfigure s_rgfpVidx16[13]
#define s_fpvideoOpen s_rgfpVidx16[14]
#define s_fpvideoClose s_rgfpVidx16[15]
#define s_fpvideoGetChannelCaps s_rgfpVidx16[16]
#define s_fpvideoStreamReset s_rgfpVidx16[17]
#define s_fpvideoStreamStart s_rgfpVidx16[18]
#define s_fpvideoStreamStop s_rgfpVidx16[19]
#define s_fpvideoStreamUnprepareHeader s_rgfpVidx16[20]
#define s_fpvideoCapDriverDescAndVer s_rgfpVidx16[21]
#define s_fpvideoMessage s_rgfpVidx16[22]
#define s_fpvidxFreePreviewBuffer s_rgfpVidx16[23]
/***************************************************************************
*
* @doc INTERNAL
*
* @func void | ThunkTerm |
*
* Free it.
*
***************************************************************************/
void NTAPI
ThunkTerm(void)
{
if (s_hinstVidx16) {
s_mit.FreeLibrary16(s_hinstVidx16);
s_hinstVidx16 = 0;
}
}
/***************************************************************************
*
* @doc INTERNAL
*
* @func void | ThunkGetProcAddresses |
*
* Get all the necessary proc addresses.
*
***************************************************************************/
HINSTANCE NTAPI
ThunkGetProcAddresses(FARPROC rgfp[], LPCSTR rgpsz[], UINT cfp,
LPCSTR pszLibrary)
{
HINSTANCE hinst;
hinst = s_mit.LoadLibrary16(pszLibrary);
if (hinst >= (HINSTANCE)32) {
UINT ifp;
for (ifp = 0; ifp < cfp; ifp++) {
rgfp[ifp] = s_mit.GetProcAddress16(hinst, rgpsz[ifp]);
if (!rgfp[ifp]) {
s_mit.FreeLibrary16(hinst);
hinst = 0;
break;
}
}
} else {
hinst = 0;
}
return hinst;
}
/***************************************************************************
*
* @doc INTERNAL
*
* @func void | ThunkInit |
*
* GetProcAddress16 our brains out.
*
***************************************************************************/
BOOL NTAPI
ThunkInit(void)
{
HINSTANCE hinstK32 = GetModuleHandle(c_tszKernel32);
BOOL fRc;
if (hinstK32) {
int i;
FARPROC *rgfpMit = (LPVOID)&s_mit;
for (i = 0; i < ARRAYSIZE(c_rgpszKernel32); i++) {
if ((LONG_PTR)(c_rgpszKernel32[i]) & ~(LONG_PTR)65535) {
rgfpMit[i] = GetProcAddress(hinstK32, c_rgpszKernel32[i]);
} else {
rgfpMit[i] = GetProcOrd(hinstK32, (UINT_PTR)c_rgpszKernel32[i]);
}
if (!rgfpMit[i]) return FALSE; /* Aigh! */
}
s_hinstVidx16 =
ThunkGetProcAddresses(s_rgfpVidx16, c_rgpszVidx16,
ARRAYSIZE(s_rgfpVidx16),
c_szVidx16);
if (!s_hinstVidx16) {
goto failed;
}
fRc = 1;
} else {
failed:;
ThunkTerm();
fRc = 0;
}
return fRc;
}
/***************************************************************************
*
* Now come the actual thunklets.
*
***************************************************************************/
// typedef DWORD HDR32;
// typedef DWORD HVIDEO;
// typedef DWORD *LPHVIDEO;
typedef struct channel_caps_tag CHANNEL_CAPS, *LPCHANNEL_CAPS;
#include "ivideo32.h"
typedef PTR32 FAR * PPTR32;
extern int g_IsNT;
#define tHVIDEO "l"
#define tUINT "s"
#define tHWND "s"
#define tHDC "s"
#define tint "s"
#define tDWORD "l"
#define tLPARAM "l"
#define tDWORD_PTR "l" // exactly like DWORD, or we'll blow up
#define tHDR32 "l"
#define tPTR32 "l"
#define tLPVIDEOHDR "p" // was l
#define tLPVOID "p"
#define tLPDWORD "p"
#define tPPTR32 "p"
#define tLPSTR "p"
#define tLPTSTR "p"
#define tLPHVIDEO "p"
#define tLPCHANNEL_CAPS "p"
#define rDWORD "L"
#define rLRESULT "L"
#pragma BEGIN_CONST_DATA
#define MAKETHUNK1(rT, fn, t1, a1) \
rT NTAPI \
fn(t1 a1) \
{ \
if (g_IsNT) \
return NT##fn(a1); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 \
r##rT, a1); \
} \
#define MAKETHUNK2(rT, fn, t1, a1, t2, a2) \
rT NTAPI \
fn(t1 a1, t2 a2) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 \
r##rT, a1, a2); \
} \
#define MAKETHUNK3(rT, fn, t1, a1, t2, a2, t3, a3) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 \
r##rT, a1, a2, a3); \
} \
#define MAKETHUNK4(rT, fn, t1, a1, t2, a2, t3, a3, t4, a4) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3, t4 a4) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3,a4); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 t##t4 \
r##rT, a1, a2, a3, a4); \
} \
#define MAKETHUNK5(rT, fn, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3,a4,a5); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 t##t4 t##t5 \
r##rT, a1, a2, a3, a4, a5); \
} \
#define MAKETHUNK6(rT, fn, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3,a4,a5,a6); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 t##t4 t##t5 t##t6 \
r##rT, a1, a2, a3, a4, a5, a6); \
} \
#define MAKETHUNK7(rT, fn, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, \
t7, a7) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3,a4,a5,a6,a7); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 t##t4 t##t5 t##t6 t##t7 \
r##rT, a1, a2, a3, a4, a5, a6, a7); \
} \
#define MAKETHUNK8(rT, fn, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, \
t7, a7, t8, a8) \
rT NTAPI \
fn(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6, t7 a7, t8 a8) \
{ \
if (g_IsNT) \
return NT##fn(a1,a2,a3,a4,a5,a6,a7,a8); \
else \
return (rT)TemplateThunk(s_fp##fn, \
t##t1 t##t2 t##t3 t##t4 t##t5 t##t6 t##t7 t##t8 \
r##rT, a1, a2, a3, a4, a5, a6, a7, a8); \
} \
MAKETHUNK4(DWORD, vidxAllocHeaders,
HVIDEO, hv,
UINT, nHeaders,
UINT, cbHeader,
PPTR32, lp32Hdrs)
MAKETHUNK1(DWORD, vidxFreeHeaders,
HVIDEO, hv)
MAKETHUNK4(DWORD, vidxAllocBuffer,
HVIDEO, hv,
UINT, iHdr,
PPTR32, pp32Hdr,
DWORD, dwSize)
MAKETHUNK4(DWORD, vidxAllocPreviewBuffer,
HVIDEO, hv,
PPTR32, pp32Hdr,
UINT, cbHdr,
DWORD, cbData)
MAKETHUNK2(DWORD, vidxFreePreviewBuffer,
HVIDEO, hv,
PPTR32, pp32Hdr)
MAKETHUNK2(DWORD, vidxFreeBuffer,
HVIDEO, hv,
DWORD, p32Hdr)
MAKETHUNK4(DWORD, videoGetErrorText,
HVIDEO, hv,
UINT, wError,
LPTSTR, lpText,
UINT, wSize)
MAKETHUNK6(DWORD, vidxSetRect,
HVIDEO, hv,
UINT, wMsg,
int, left,
int, top,
int, right,
int, bottom)
MAKETHUNK3(DWORD, videoUpdate,
HVIDEO, hv,
HWND, hWnd,
HDC, hDC)
MAKETHUNK3(DWORD, videoDialog,
HVIDEO, hv,
HWND, hWndParent,
DWORD, dwFlags)
MAKETHUNK5(DWORD, videoStreamInit,
HVIDEO, hvideo,
DWORD, dwMicroSecPerFrame,
DWORD_PTR, dwCallback,
DWORD_PTR, dwCallbackInst,
DWORD, dwFlags)
MAKETHUNK1(DWORD, videoStreamFini,
HVIDEO, hvideo)
MAKETHUNK2(DWORD, vidxFrame,
HVIDEO, hvideo,
LPVIDEOHDR, p32hdr)
MAKETHUNK8(DWORD, videoConfigure,
HVIDEO, hvideo,
UINT, msg,
DWORD, dwFlags,
LPDWORD, lpdwReturn,
LPVOID, lpData1,
DWORD, dwSize1,
LPVOID, lpData2,
DWORD, dwSize2)
MAKETHUNK3(DWORD, videoOpen,
LPHVIDEO,phv,
DWORD, dwDevice,
DWORD, dwFlags)
MAKETHUNK1(DWORD, videoClose,
HVIDEO, hv)
MAKETHUNK3(DWORD, videoGetChannelCaps,
HVIDEO, hv,
LPCHANNEL_CAPS, lpcc,
DWORD, dwSize)
MAKETHUNK3(DWORD, vidxAddBuffer,
HVIDEO, hvideo,
PTR32, p32Hdr,
DWORD, dwSize)
MAKETHUNK1(DWORD, videoStreamReset,
HVIDEO, hvideo)
MAKETHUNK1(DWORD, videoStreamStart,
HVIDEO, hvideo)
MAKETHUNK1(DWORD, videoStreamStop,
HVIDEO, hvideo)
MAKETHUNK3(DWORD, videoStreamUnprepareHeader,
HVIDEO, hvideo,
LPVIDEOHDR, lpVHdr,
DWORD, dwSize)
MAKETHUNK5(DWORD, videoCapDriverDescAndVer,
DWORD, dwDeviceID,
LPTSTR, lpszDesc,
UINT, cbDesc,
LPTSTR, lpszVer,
UINT, cbVer)
MAKETHUNK4(LRESULT, videoMessage,
HVIDEO, hVideo,
UINT, uMsg,
LPARAM, dw1,
LPARAM, dw2)