Fixing ChessBase 8 on Vista
As a chessplayer, I’m a long time owner or ChessBase 8. It’s a great program to organize my own games of chess. So far I found no need to do an update to ChessBase 9 or the new ChessBase light.
The situtation changed 2 weeks ago when I got my first PC with Windows Vista Home Premium installed. Vista by default enables ClearType and so far I like it. Unfortunately the older ChessBase programs like ChessBase 8, Fritz 8 or Fritz 9 or even my Shredder 10 do not correctly support ClearType.
You can see that the move notation in bold is perfectly readable, but the notation of variations is very thin and barely readable. Unfortunately that thin font is used in many places all over the program. The most important place is of course the display of variations.
The problem seems to be the font used. When switching over to “Arial” everything looks perfect. Unfortunately Arial is missing a few characters that are displayed, e. g. the nice chess pieces and a few special characters.
The only effective solution is to turn off ClearType for the whole operating system. That immediately fixes ChessBase 8 and makes it usable again. I don’t like this solution at all.
So I decided to dig into API hooking to ensure the fonts are created in a way that is good for Vista. My first google search on this scheme dug up a nice article on codeproject. I just modified the code to only hook up the windows API function CreateFontIndirect. The source you can download at codeproject is very simple and straight forward. No problems here.
#include "stdafx.h"
#include "ThreadSpy.h"
HFONT WINAPI MyCreateFontIndirectA( __in CONST LOGFONTA *lplf)
{
if (lplf)
{
LOGFONTA lfneu = *lplf;
if (lfneu.lfWeight <= FW_NORMAL)
{
lfneu.lfQuality = ANTIALIASED_QUALITY;
}
return ::CreateFontIndirectA(&lfneu);
}
else
return ::CreateFontIndirectA(lplf);
}
You can see that I’m explicitly hooking the A-Version of the function. I’m always compiling my own DLLs as unicode, so it’s important to specify the A-Version as the Chessbase programs I’m trying to fix here are not yet unicode compiled. The fix itself is simple and just ensures that all small-weight fonts are created using ANTIALIASED_QUALITY. This is not a ClearType quality and it’s not a default allowing Windows to choose. Specifying this flag makes sure the font gets rendered using the older antialiasing techniques.
Once the code is injected into the Chessbase program, the result is just perfect:
The only missing part now is a small loader that injects my DLL into the Chessbase program. Fortunately the author of the first article on codeproject did a few more articles and provided the basis for a loader, too. The final loader code is found in his third part of the article series. My loader is a clear strip-down of his menu driven full fledged solution.
#include "stdafx.h"
PROCESS_INFORMATION pi;
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tp;
if ( !::OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken )) return FALSE;
//
// Given a privilege’s name SeDebugPrivilege, we should locate its local LUID mapping.
//
if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
::CloseHandle( hToken );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = sedebugnameValue;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( !::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(tp), NULL, NULL ) )
{
::CloseHandle( hToken );
return FALSE;
}
::CloseHandle( hToken );
return TRUE;
}
BOOL InjectInto(LPCWSTR sName, LPCWSTR sParam)
{
// Check arguments
if (sName == NULL) return FALSE;
// Get the handle for the new specified process
STARTUPINFO startup;
GetStartupInfo(&startup);
HANDLE hThread;
WCHAR acParam[1024];
wcscpy_s(acParam, 1024, sName);
if (sParam != NULL && sParam[0])
{
wcscat_s(acParam, 1024, L" ");
wcscat_s(acParam, 1024, sParam);
if (!::CreateProcess(sName, acParam, NULL, NULL, TRUE, CREATE_SUSPENDED, 0, 0, &startup, &pi)) return FALSE;
}
else
{
if (!::CreateProcess(sName, NULL, NULL, NULL, TRUE, CREATE_SUSPENDED, 0, 0, &startup, &pi)) return FALSE;
}
// Get the library name
LPCWSTR LIBNAME = L"C8VistaFix.dll";
// Allocate space in the remote process for the pathname to our spying DLL
LPCWSTR LibName = (LPCWSTR)::VirtualAllocEx(pi.hProcess, NULL, (wcslen(LIBNAME) + 1) * sizeof(WCHAR), MEM_RESERVE, PAGE_EXECUTE_READWRITE);
LibName = (LPCWSTR)::VirtualAllocEx(pi.hProcess, (LPVOID)LibName, (wcslen(LIBNAME) + 1) * sizeof(WCHAR), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (LibName == NULL) return FALSE;
// Copy the DLL’s pathname to the remote process’s address space
if (!::WriteProcessMemory(pi.hProcess, (LPVOID)LibName, (LPVOID)LIBNAME, (wcslen(LIBNAME)+1)*sizeof(WCHAR), NULL)) return FALSE;
// Get the real address of LoadLibraryA in Kernel32.dll
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandleW(L"Kernel32"), "LoadLibraryW");
if (pfnThreadRtn == NULL) return FALSE;
// Create a remote thread that calls LoadLibraryA(DLLPathname)
hThread = ::CreateRemoteThread(pi.hProcess, NULL, 0, pfnThreadRtn, (LPVOID)LibName, 0, NULL);
if (hThread == NULL) return FALSE;
// Wait for the remote thread to terminate
::WaitForSingleObject(hThread, INFINITE);
// Get the thread exit code
DWORD exit;
GetExitCodeThread(hThread, &exit);
return TRUE;
}
BOOL LaunchThread()
{
// So resumre the thread
if (ResumeThread(pi.hThread) == -1)
return FALSE;
return TRUE;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPCWSTR lpstrCmdLine, int nCmdShow)
{
if (!EnableDebugPrivilege())
{
MessageBoxW(0, L"Fehler bei EnableDebugPrivilege", L"Fehler", MB_OK);
return 1;
}
if (!InjectInto(L"C8Broken.exe", lpstrCmdLine))
{
MessageBoxW(0, L"Fehler bei Launch", L"Fehler", MB_OK);
return 1;
}
if (!LaunchThread())
{
MessageBoxW(0, L"Fehler bei Start", L"Fehler", MB_OK);
return 1;
}
return 0;
}
Basically it runs like this:
- Load “C8Broken.exe” in a suspended, not yet running state
- Inject the DLL that hooks the CreateFontIndirectA function calls
- Start the “C8Broken.exe” thread.
You can imagine, that “C8Broken.exe” is just the original “C8.exe” renamed. My program takes the place of “C8.exe” so it gets called whenever Chessbase 8 is launched. The same goes if my code is used to replace “ChessProgram8.exe” or some newer version of it. Just rename the original file to “C8Broken.exe” and give the loaded the appropriate name.
You can download the compiled binaries as a ready-to-use solution to the Chessbase vista font problem. If you’re interested in my sourcecode, just drop me a note.

