65.9K
CodeProject is changing. Read more.
Home

Generic Thunk of Windows

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.76/5 (6 votes)

Sep 27, 2008

CPOL

1 min read

viewsIcon

17135

Minimal application of Generic Thunk.

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>

// KERNEL.DLL

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);
}

// KERNEL32.DLL

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;
}

// WinMain

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.