Export to shared memory

The data is exported to shared memory. The name of the shared memory is "GPxCInfo". It is guarded by a mutex named "GPxCInfo_Mutex". The contents of the shared memory are defined by the following structure:
#ifdef _MSC_VER
  #pragma pack(push, 1)
#else
  #pragma pack(1)
#endif

#ifndef BYTE
#define BYTE unsigned char
#endif
#ifndef WORD
#define WORD unsigned short
#endif
#ifndef DWORD
#define DWORD unsigned int
#endif

#define GPXCINFO_NAME       "GPxCInfo"
#define GPXCINFO_MUTEX_NAME GPXCINFO_NAME"_Mutex"

#define GPX_CIF_PITLIGHT    0x01 // set if pit light is on
#define GPX_CIF_REDLED      0x02 // set if red led is on (failure/warning)
#define GPX_CIF_YELLOWLED   0x04 // set if yellow led is on (yellow flag)
#define GPX_CIF_BLUELED     0x08 // set if blue led is on (blue flag)

struct GPxCInfoData {
	BYTE flags;             // see GPX_CIF_* defines above
	BYTE lap;               // lap number
	BYTE position;          // race position
	WORD fuel;              // fuel laps (value = fuel laps * 10)
	BYTE temp;              // water temperature
	int  speed;             // rounded speed in either kph or mph
	DWORD splittime;        // last split or lap time
	char gear;              // gear
	WORD revs;              // rpm
	DWORD time;             // session time in millis
	DWORD timeFront;        // difference in millis to driver in front (or 0xc0000000 if n/a)
	DWORD timeBehind;       // difference in millis to driver behind (or 0xc0000000 if n/a)
	char driverFront[24];   // initial and last name of driver in front, if available
	char driverBehind[24];  // initial and last name of driver behind, if available
};

#ifdef _MSC_VER
  #pragma pack(pop)
#else
  #pragma pack()
#endif
	
The contents are updated each frame. Here is sample code of how to access it:
static const size_t DATA_SIZE = sizeof(GPxCInfoData);
static GPxCInfoData *pData = NULL;
static LPVOID pSharedData = NULL;
static HANDLE hFileMapping = NULL;
static HANDLE hMutex = NULL;

static BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType);
static bool Init();
static void End();
static bool Read();


static BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{
	switch (dwCtrlType) {
		case CTRL_C_EVENT:
		case CTRL_BREAK_EVENT:
		case CTRL_CLOSE_EVENT:
			End();
			break;
	}
	return FALSE;
}


static bool Init()
{
	SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);

	hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, DATA_SIZE, GPXCINFO_NAME);
	if (hFileMapping == NULL) {
		fprintf(stderr, "Error creating file mapping: last error = %d\n", GetLastError());
		return false;
	}
	
	pSharedData = MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
	if (pSharedData == NULL) {
		fprintf(stderr, "Error mapping view of file: last error = %d\n", GetLastError());
		return false;
	}

	hMutex = CreateMutex(NULL, FALSE, GPXCINFO_MUTEX_NAME);
	if (hMutex == NULL) {
		fprintf(stderr, "Error creating mutex: last error = %d\n", GetLastError());
		return false;
	}
	
	pData = new GPxCInfoData;

	return true;
}

static void End()
{
	fprintf(stderr, "Cleaning up...\n");

	delete pData;
	pData = NULL;

	if (hMutex != NULL) {
		CloseHandle(hMutex);
		hMutex = NULL;
	}
	
	if (pSharedData != NULL) {
		UnmapViewOfFile(pSharedData);
		pSharedData = NULL;
	}
	
	if (hFileMapping != NULL) {
		CloseHandle(hFileMapping);
		hFileMapping = NULL;
	}

	SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
}

static bool Read()
{
	bool ret = false;

	// obtain mutex ownership
	DWORD dwWaitResult = WaitForSingleObject(hMutex, 1000);
	switch (dwWaitResult) {
		case WAIT_OBJECT_0:
 			__try {
				__try {
					// copy data from shared memory
					memcpy(pData, pSharedData, DATA_SIZE);
					ret = true;
				}
				__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
						EXCEPTION_EXECUTE_HANDLER :
						EXCEPTION_CONTINUE_SEARCH) {
					fprintf(stderr, "Access violation while reading data from shared memory\n");
				}
			}
			__finally {
				// release ownership
				if (!ReleaseMutex(hMutex))
					fprintf(stderr, "Error releasing mutex: last error = %d\n", GetLastError());
			}
			break;
		case WAIT_FAILED:
			fprintf(stderr, "Error waiting for object: last error = %d\n", GetLastError());
			break;
		case WAIT_TIMEOUT:
			fprintf(stderr, "Timed out waiting for lock\n");
			break;
	}

	return ret;
}


int main(int argc, char* argv[])
{
	if (Init()) {
		for (;;) {
			Read();
			fprintf(stdout, "%d\n", pData->speed);
			Sleep(500);
		}
	}

	End();

	return 0;
}