Introduction
Generic Thunk is a technology from Microsoft allowing 16-bit Windows application to make in-process calls to exported functions of a 32-bit DLL. This article presents a simple application of the technology.
Using the code
#include <Windows.h>
DWORD (FAR PASCAL *LoadLibraryEx32W)(
LPCSTR lpszLibFile,
DWORD hFile,
DWORD dwFlags
);
DWORD (FAR PASCAL *FreeLibrary32W)(
DWORD hInst
);
DWORD (FAR PASCAL *GetProcAddress32W)(
DWORD hModule,
LPCSTR lpszProc
);
DWORD (FAR PASCAL *CallProc32W0)(
DWORD lpProcAddress,
DWORD fAddressConvert,
DWORD nParams
);
static HINSTANCE ghKernelDll;
void PASCAL LoadKernelDll(void)
{
ghKernelDll = LoadLibrary("Kernel.DLL");
LoadLibraryEx32W = (DWORD (FAR PASCAL *)(LPCSTR, DWORD, DWORD))
GetProcAddress(ghKernelDll, "LoadLibraryEx32W");
FreeLibrary32W = (DWORD (FAR PASCAL *)(DWORD))
GetProcAddress(ghKernelDll, "FreeLibrary32W");
GetProcAddress32W = (DWORD (FAR PASCAL *)(DWORD, LPCSTR))
GetProcAddress(ghKernelDll, "GetProcAddress32W");
CallProc32W0 = (DWORD (FAR PASCAL *)(DWORD, DWORD, DWORD))
GetProcAddress(ghKernelDll, "CallProc32W");
}
void PASCAL FreeKernelDll(void)
{
FreeLibrary(ghKernelDll);
}
static DWORD ghKernel32Dll;
static DWORD ghGetTickCount32;
void PASCAL LoadKernel32Dll(void)
{
LoadKernelDll();
ghKernel32Dll = LoadLibraryEx32W("Kernel32.DLL", 0, 0);
ghGetTickCount32 = GetProcAddress32W(ghKernel32Dll, "GetTickCount");
}
void PASCAL FreeKernel32Dll(void)
{
FreeLibrary32W(ghKernel32Dll);
FreeKernelDll();
}
DWORD PASCAL GetTickCount32(void)
{
DWORD ret;
LoadKernel32Dll();
ret = CallProc32W0(ghGetTickCount32, 0, 0);
FreeKernel32Dll();
return ret;
}
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR lpCmdLine, int nCmdShow)
{
DWORD tick16, tick32;
tick16 = GetTickCount();
tick32 = GetTickCount32();
MessageBox(NULL, tick16 <= tick32 ? "Success" :
"Failure", "GetTickCount32", MB_ICONASTERISK);
return 0;
}
This is the complete code in C language, for the Win16 platform. We shall focus on the function GetTickCount32
.
The GetTickCount32
function is called once by the entry point function, WinMain
. The GetTickCount32
function calls the LoadKernel32Dll
function, the CallProc32W0
function, and the FreeKernel32Dll
function.
The invocation of CallProc32W0
is the in-process cross-boundary call to the desired 32-bit DLL function. In order to use the CallProc32W0
function, we need to get its procedure address. It is the procedure address of the CallProc32W
function of the KERNEL.DLL library.
The invocation of LoadKernel32Dll
gets a 32-bit value representing the procedure GetTickCount
of the KERNEL32.DLL library. In addition, it gets the procedure address of the CallProc32W
function of the KERNEL.DLL library by calling the LoadKernelDll
function.
The invocation of FreeKernel32Dll
decrements the reference count of the loaded KERNEL32.DLL library. In addition, it decrements the reference count of the loaded KERNEL.DLL library by calling the FreeKernelDll
function.
Summary
This article demonstrates an invocation of the GetTickCount
function of the KERNEL32.DLL library from the Win16 platform.