Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Generic Thunk of Windows

1.76/5 (6 votes)
27 Sep 2008CPOL1 min read 1  
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

C++
#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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)