#include "DeviceProduct.h"
DeviceProduct::DeviceProduct()
{
}

DeviceProduct::DeviceProduct(wstring ProductName)
{
	m_ProductName = ProductName;
	FindNETFramework();
	FindVsCPulsPulsRedistributable();
	OpenLocalMachineRootKey(RegeditCore::smPath_ProductsInfo.c_str());
}

DeviceProduct::~DeviceProduct()
{

}

wstring DeviceProduct::GetVersion()
{
	return m_Version;
}

wstring DeviceProduct::GetInstallLocation()
{
	return m_InstallLocation;
}


wstring DeviceProduct::GetNETVersion()
{
	return m_NETVersion;
}

wstring DeviceProduct::GetNETTargetVersion()
{
	return m_NETTargetVersion;
}

wstring DeviceProduct::GetVsCPulsPulsVersion() {
	return m_VsCPulsPulsVersion;
}

wstring DeviceProduct::GetVsCPulsPulsInstalled() {
	return m_VsCPulsPulsInstalled;
}

bool DeviceProduct::OpenLocalMachineRootKey(LPCTSTR productsInfoPath)
{
	long lRet;
	HKEY hKey;
	LPCTSTR lpSubKey;
	lpSubKey = productsInfoPath;
	lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
	bool state = false;

	if (lRet == ERROR_SUCCESS)
	{
		state = SearchAllProducts(hKey, lpSubKey);
	}

	return state;
}

bool DeviceProduct::SearchAllProducts(HKEY hKey, LPCTSTR productsInfoPath)
{
	bool state = false;
	DWORD index = 0;
	TCHAR szKeyName[255] = { 0 };
	DWORD dwKeyLen = 255;
	wstring strBuffer;

	while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, index, szKeyName, &dwKeyLen, 0, NULL, NULL, NULL))
	{
		index++;
		wstring temp(szKeyName);
		strBuffer = temp;

		if (!strBuffer.empty())
		{
			wstring productsInfo(productsInfoPath);
			strBuffer = productsInfo + L"\\" + strBuffer;
			state = OpenLocalMachineSubKey(strBuffer);
		
			if (state)
				break;

			//continue;
		}
		dwKeyLen = 255;
		memset(szKeyName, 0, 255);
	}
	dwKeyLen = 255;
	memset(szKeyName, 0, 255);
	return state;
}


bool DeviceProduct::OpenLocalMachineSubKey(std::wstring AppKey)
{
	bool state = false;
	long lRet;
	HKEY hKey;
	LPCTSTR lpSubKey;

	//AppKey = RegeditCore::smPath_ProductsInfo + L"\\" + AppKey;
	lpSubKey = AppKey.c_str();
	lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);

	if (lRet == ERROR_SUCCESS)
	{
		state = FindProductInfo(hKey, lpSubKey);
	}
	else
	{
		m_Version = L"";
	}

	return state;
}


bool DeviceProduct::FindProductInfo(HKEY hKey, LPCTSTR lpSubKey)
{
	bool state = false;
	DWORD dwType = REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ | REG_DWORD_LITTLE_ENDIAN | REG_DWORD_BIG_ENDIAN | REG_LINK | REG_RESOURCE_LIST | REG_FULL_RESOURCE_DESCRIPTOR | REG_RESOURCE_REQUIREMENTS_LIST | REG_QWORD_LITTLE_ENDIAN;
	HKEY hkRKey;

	DWORD index = 0;
	TCHAR szKeyName[255] = { 0 };
	DWORD dwKeyLen = 255;
	wstring strBuffer;
	wstring strMidReg;
	TCHAR szBufferAppInfo[255] = { 0 };
	DWORD dwNameLen = 255;

	//遍历已安装程序
	while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, index, szKeyName, &dwKeyLen, 0, NULL, NULL, NULL))
	{
		//获取已安装程序的节点
		index++;
		wstring nodeTemp(szKeyName);
		strBuffer = nodeTemp;

		if (!strBuffer.empty())
		{
			wstring nodePathTemp(L"\\" + strBuffer);
			strMidReg = lpSubKey + nodePathTemp;

			if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strMidReg.c_str(), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hkRKey) == ERROR_SUCCESS)
			{
				RegQueryValueEx(hkRKey, L"DisplayName", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
				wstring displayNameTemp(szBufferAppInfo);
				dwNameLen = 255;
				memset(szBufferAppInfo, 0, 255);

				if (displayNameTemp == m_ProductName)
				{
					RegQueryValueEx(hkRKey, L"DisplayVersion", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
					wstring displayVersionTemp(szBufferAppInfo);
					m_Version = displayVersionTemp;
					dwNameLen = 255;
					memset(szBufferAppInfo, 0, 255);

					RegQueryValueEx(hkRKey, L"InstallLocation", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
					wstring installLocationTemp(szBufferAppInfo);
					m_InstallLocation = installLocationTemp;

					dwNameLen = 255;
					memset(szBufferAppInfo, 0, 255);
					return state;
				}

				dwNameLen = 255;
				memset(szBufferAppInfo, 0, 255);

			}
			
			dwKeyLen = 255;
			memset(szKeyName, 0, 255);
		}

		
	}
	return state;
}



bool DeviceProduct::FindNETFramework()
{
	HKEY hkRKey;
	TCHAR szBufferAppInfo[255] = { 0 };
	DWORD dwNameLen = 255;
	DWORD dwType = REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ | REG_DWORD_LITTLE_ENDIAN | REG_DWORD_BIG_ENDIAN | REG_LINK | REG_RESOURCE_LIST | REG_FULL_RESOURCE_DESCRIPTOR | REG_RESOURCE_REQUIREMENTS_LIST | REG_QWORD_LITTLE_ENDIAN;

	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegeditCore::smPath_NETFrameworkInfo.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hkRKey) == ERROR_SUCCESS)
	{

		RegQueryValueEx(hkRKey, L"TargetVersion", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
		wstring displayVersionTemp(szBufferAppInfo);
		m_NETTargetVersion = displayVersionTemp;
		dwNameLen = 255;
		memset(szBufferAppInfo, 0, 255);

		RegQueryValueEx(hkRKey, L"Version", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
		wstring installLocationTemp(szBufferAppInfo);
		m_NETVersion  = installLocationTemp;

		dwNameLen = 255;
		memset(szBufferAppInfo, 0, 255);
		return true;
	}	
	return false;

}

bool DeviceProduct::FindVsCPulsPulsRedistributable() {
	HKEY hkRKey;
	TCHAR szBufferAppInfo[255] = { 0 };
	DWORD dwNameLen = 255;
	DWORD dwType = REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ | REG_DWORD_LITTLE_ENDIAN | REG_DWORD_BIG_ENDIAN | REG_LINK | REG_RESOURCE_LIST | REG_FULL_RESOURCE_DESCRIPTOR | REG_RESOURCE_REQUIREMENTS_LIST | REG_QWORD_LITTLE_ENDIAN;

	if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegeditCore::smPath_VsCPulsPulsInfoX64.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hkRKey) == ERROR_SUCCESS)
	{

		RegQueryValueEx(hkRKey, L"Installed", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
		wstring displayVersionTemp(szBufferAppInfo);
		m_VsCPulsPulsInstalled = displayVersionTemp;
		dwNameLen = 255;
		memset(szBufferAppInfo, 0, 255);

		RegQueryValueEx(hkRKey, L"Version", 0, &dwType, (LPBYTE)szBufferAppInfo, &dwNameLen);
		wstring installLocationTemp(szBufferAppInfo);
		m_VsCPulsPulsVersion = installLocationTemp;

		dwNameLen = 255;
		memset(szBufferAppInfo, 0, 255);
		return true;
	}
	return false;
}

