/*
 * win_QrfeHardwareInfo.cpp
 *
 *  Created on: 02.12.2011
 *      Author: stefan.detter
 */

#define NOMINMAX 

#include <stdio.h>
#include <string.h>
#include <intrin.h>
#include <windows.h>

#include <QtGlobal>
#include <QrfeGlobal>
#include <QrfeTrace>

void qrfe_cpuid(int CPUInfo[4], int InfoType)
{
	__cpuid(CPUInfo, InfoType);
}

bool qrfe_getCpuId( QString & vendor, QString & brand )
{
	int cpuInfo[4];
	uint infoType = 0;
	QByteArray data;

	qrfe_cpuid(cpuInfo, infoType);

	data = QrfeGlobal::arrayToQByteArray(cpuInfo, 4);
    vendor = QString::fromLatin1(data.mid(4, 4) + data.mid(12, 4) + data.mid(8, 4));

	for(infoType = 0x80000002; infoType < 0x80000005; infoType++)
	{
		qrfe_cpuid(cpuInfo, infoType);
		data = QrfeGlobal::arrayToQByteArray(cpuInfo, 4);
        brand += QString::fromLatin1(data);
	}

//	QByteArray result;
//
//	int cpuInfo[4];
//	uint infoType = 0;
//	QByteArray data;
//
//	uint nIds 	= 0x00000000;
//	uint nxIds 	= 0x80000000;
//
//	QString vendorId;
//	QString brandString;
//
//
//	for(infoType = 0; infoType <= nIds; infoType++ )
//	{
//		bool use = false;
//
//		qrfe_cpuid(cpuInfo, infoType);
//
//		data = QrfeGlobal::arrayToQByteArray(cpuInfo, 4);
//
//		if(infoType == 0x00000000)			// Get vendor ID
//		{
//			nIds = cpuInfo[0];
//			vendorId = QString::fromAscii(data.mid(4, 4) + data.mid(12, 4) + data.mid(8, 4));
//
//			use = true;
//		}
//		else if(infoType == 0x00000001)		// Processor Info and Feature Bits
//		{
//			data[4] = data[5] = data[6] = data[7] = 0;	// remove EBX (changing)
//			use = true;
//		}
//		else if(infoType == 0x00000002)		// Cache and TLB Descriptor information
//		{
//			use = true;
//		}
//		else if(infoType == 0x00000003)		// Processor Serial Number // not implemented any more, but if it is, take it
//		{
//			use = true;
//		}
//
//		if(use)
//		{
//			//QrfeTrace::trc(0, QString("%1").arg((uint)infoType, 8, 16, QChar('0')) + ": 0x" + data.toHex());
//			result.append(data);
//		}
//	}
//
//	for(infoType = 0x80000000; infoType <= nxIds; infoType++ )
//	{
//		bool use = false;
//
//		qrfe_cpuid(cpuInfo, infoType);
//
//		data = QrfeGlobal::arrayToQByteArray(cpuInfo, 4);
//
//		if(infoType == 0x80000000)			// Get Highest Extended Function Supported
//		{
//			nxIds = cpuInfo[0];
//		}
//		else if(infoType == 0x80000001)		// Extended Processor Info and Feature Bits
//		{
//			use = true;
//		}
//		else if( infoType == 0x80000002 || infoType == 0x80000003 || infoType == 0x80000004 ) 	// Processor Brand String
//		{
//			brandString += QString::fromAscii(data);
//			use = true;
//		}
//		else if(infoType == 0x80000005)		// L1 Cache and TLB Identifiers
//		{
//			use = true;
//		}
//		else if(infoType == 0x80000006)		// Extended L2 Cache Features
//		{
//			use = true;
//		}
//		else if(infoType == 0x80000007)		// Advanced Power Management Information
//		{
//			use = true;
//		}
//		else if(infoType == 0x80000008)		// Virtual and Physical address Sizes
//		{
//			use = true;
//		}
//
//		if(use)
//		{
//			//QrfeTrace::trc(0, QString("%1").arg((uint)infoType, 8, 16, QChar('0')) + ": 0x" + data.toHex());
//			result.append(data);
//		}
//	}

	//QrfeTrace::trc(0, "--CpuVendor: " + vendor);
	//QrfeTrace::trc(0, "--CpuBrand: " + brand);

	return true;
}

bool qrfe_getVolumeSerialNumber( quint32 &serial )
{
	DWORD maximumComponentLength, fileSystemFlags;
	WCHAR infoBuf[128];
	WCHAR systemRoot[4];

	LPCTSTR root;

	if(GetSystemDirectory(infoBuf, 128) < 1)
	{
		root = NULL;
	}
	else
	{
		systemRoot[0] = infoBuf[0];
		systemRoot[1] = ':';
		systemRoot[2] = '\\';
		systemRoot[3] = 0;

		root = systemRoot;

		//QrfeTrace::trc(0, "--SystemDirectory: " + QString::fromWCharArray((const wchar_t*)infoBuf));
	}

	int i = 0;

	while(GetVolumeInformation( root, NULL, 0, (LPDWORD)&serial, (LPDWORD)&maximumComponentLength, (LPDWORD)&fileSystemFlags, NULL, 0) == FALSE)
	{
		i++;
		if(i > 5)
		{
			QrfeTrace::trcWarning(" Could not retrieve serial of " + QString::fromWCharArray((const wchar_t*)root, 3));
			return false;
		}
	}

	return true;
}
