#include <tchar.h>
#include "winring0/OlsApiInit.h"

#define INST_RETIRED_ANY_ADDR           (0x309)
#define CPU_CLK_UNHALTED_THREAD_ADDR    (0x30A)
#define CPU_CLK_UNHALTED_REF_ADDR       (0x30B)
#define IA32_CR_PERF_GLOBAL_CTRL        (0x38F)
#define IA32_CR_FIXED_CTR_CTRL          (0x38D)
#define IA32_PERFEVTSEL0_ADDR           (0x186)

typedef unsigned long long uint64;
typedef signed long long int64;
typedef unsigned int uint32;
typedef signed int int32;


bool InitDrv();
int readMSR(uint64 msr, uint64* value);
int writeMSR(uint64 msr, uint64 value);

#pragma warning(disable : 4996) // for sprintf
// data structure for converting two uint32s <->uin64
union cvt_ds
{
	UINT64 ui64;
	struct
	{
		DWORD low;
		DWORD high;
	} ui32;
};


HMODULE hOpenLibSys = NULL;

bool InitDrv() {
	const BOOL result = InitOpenLibSys(&hOpenLibSys);
	if (result == FALSE) hOpenLibSys = NULL;
	return result == TRUE;
}

void EnableFixCtrl() {
	writeMSR(IA32_CR_PERF_GLOBAL_CTRL, 0x700000000);

}


int readMSR(uint64 msr, uint64* value) {
	cvt_ds cvt;
	cvt.ui64 = 0;
	BOOL status = Rdmsr((DWORD)msr, &(cvt.ui32.low), &(cvt.ui32.high));
	if (status) *value = cvt.ui64;
	return status ? sizeof(uint64) : 0;
}

int writeMSR(uint64 msr, uint64 value) {
	cvt_ds cvt;
	cvt.ui64 = value;
	BOOL status = Wrmsr((DWORD)msr, (cvt.ui32.low), (cvt.ui32.high));
	return status ? sizeof(uint64) : 0;
}

