Click here to Skip to main content
15,884,099 members
Articles / Programming Languages / C++

ClearType over Remote Desktop in Windows XP

Rate me:
Please Sign up or sign in to vote.
4.93/5 (22 votes)
6 Nov 2007CPOL5 min read 209.8K   843   27  
A kernel patch that will enable ClearType over RDP in Windows XP SP2
#include "stdafx.h"
#include "resource.h"
#include <sstream>

using namespace std;

template <class T>
T& make_ref(T const& t)
{
    return const_cast<T&>(t);
}

#define MAKE_STRING(msg) (static_cast<wostringstream&>(make_ref(wostringstream()) << msg).str())

// This function will extract one of the embedded PE files in this
// executable image and save it to disk.
bool SaveResource(WORD resId, wstring destPath)
{
	HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(resId), L"BIN");
	HGLOBAL hLoadedRes = LoadResource(NULL, hRes);

	char *pRes = static_cast<char*>(LockResource(hLoadedRes));
	DWORD dwResSize = SizeofResource(NULL, hRes);

	ofstream outstream(destPath.c_str(), ios::binary);
	if (!outstream)
		return false;

	outstream.write(pRes, dwResSize);
	outstream.close();
	return true;
}

void ShowMessage(const wstring &msg)
{
	OutputDebugStringW(msg.c_str());
	wcout << msg;
}

int _tmain(int argc, _TCHAR* argv[])
{
	wchar_t buffer[MAX_PATH];
	ExpandEnvironmentStrings(L"%SystemDrive%", &buffer[0], sizeof(buffer) / sizeof(wchar_t));

	wstring driverPath = &buffer[0];
	driverPath.append(L"\\RdpClearType.sys");

	DeleteFile(driverPath.c_str());

	if (!SaveResource(IDR_BIN1, driverPath))
	{
		ShowMessage(MAKE_STRING(L"RdpClearType: ERROR extracting driver from exe" << endl));
		return 1;
	}

	SC_HANDLE hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (!hScm)
	{
		ShowMessage(MAKE_STRING(L"RdpClearType: ERROR calling OpenSCManager(): " << GetLastError() << endl));
		return 1;
	}

	int retval = 1;

	SC_HANDLE hSvc = CreateService(
		hScm,
		L"RdpClearType",
		L"RdpClearType",
		SERVICE_ALL_ACCESS,
		SERVICE_KERNEL_DRIVER,
		SERVICE_DEMAND_START,
		SERVICE_ERROR_NORMAL,
		driverPath.c_str(),
		NULL,
		NULL,
		NULL,
		NULL,
		NULL
		);

	if (hSvc)
	{
		SERVICE_STATUS svcStatus = { 0 };

		if (StartService(hSvc, 0, NULL))
		{
			do
			{
				Sleep(250);
				if (!QueryServiceStatus(hSvc, &svcStatus))
				{
					ShowMessage(MAKE_STRING(L"RdpClearType: ERROR calling QueryServiceStatus(): " << GetLastError() << endl));
					break;
				}
			}
			while (svcStatus.dwCurrentState != SERVICE_RUNNING);

			HANDLE hFile = CreateFileW(
				L"\\\\.\\RdpClearType",
				GENERIC_READ | GENERIC_WRITE,
				0,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL,
				NULL
			);

			if (hFile == INVALID_HANDLE_VALUE)
			{
				ShowMessage(MAKE_STRING(L"RdpClearType: ERROR opening handle to RdpClearType device: " << GetLastError() << endl));
			}
			else
			{
				DWORD bytes = 0;
				BOOL result = DeviceIoControl(
					hFile,
					0,
					NULL,
					0,
					NULL,
					0,
					&bytes,
					NULL
				);

				if (result)
				{
					ShowMessage(MAKE_STRING(L"RdpClearType: ClearType should now be working inside of Remote Desktop connections." << endl));
					ValidateRect(NULL, NULL);
					retval = 0;
				}
				else
				{
					ShowMessage(MAKE_STRING(L"RdpClearType: ERROR calling DeviceIoControl: " << GetLastError() << endl));
				}

				CloseHandle(hFile);
			}

			if (ControlService(hSvc, SERVICE_CONTROL_STOP, &svcStatus))
			{
				do
				{
					Sleep(250);
					if (!QueryServiceStatus(hSvc, &svcStatus))
					{
						ShowMessage(MAKE_STRING(L"RdpClearType: ERROR calling QueryServiceStatus(): " << GetLastError() << endl));
						break;
					}
				}
				while (svcStatus.dwCurrentState != SERVICE_STOPPED);
			}
			else
			{
				ShowMessage(MAKE_STRING(L"RdpClearType: ERROR stopping service: " << GetLastError() << endl));
			}
		}
		else
		{
			ShowMessage(MAKE_STRING(L"RdpClearType: ERROR starting service: " << GetLastError() << endl));
		}

		DeleteService(hSvc);
	}
	else
	{
		ShowMessage(MAKE_STRING(L"RdpClearType: ERROR creating service: " << GetLastError() << endl));
	}

	DeleteFile(driverPath.c_str());
	return retval;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions