#include "PCIDCalculator.h"
#include "BiosInfo.h"
#include <intrin.h>
#include "md_5.h"
#include "MacAddress.h"

#include <Iphlpapi.h>
#pragma comment( lib, "Iphlpapi.lib" )

#pragma warning(disable : 4996)

CPCIDCalculator::CPCIDCalculator(void)
{
}

CPCIDCalculator::~CPCIDCalculator(void)
{
}

bool CPCIDCalculator::IsWin7OS()
{
    OSVERSIONINFO osvi;
    bool bIsWindows7 = false;

    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    GetVersionEx(&osvi);
    if (osvi.dwMajorVersion > 5) //win7 或 windowsXP之后
        bIsWindows7 = true;
    return bIsWindows7;
}

int CPCIDCalculator::CalculatePCID( char buf[16] )
{
    unsigned int flag = (PCID_DISK|PCID_CPU|PCID_BIOS|PCID_MAC);

    char tembuf[1024] = {'\0'};
    int  total = 1024;
    int  used  = 0;

    if( flag&PCID_MAC )
    {
        MyMacAddress myAdress;
        if( myAdress.WMI_GetMacAddress(1, 1) > 0 )
        {
            memcpy( &tembuf[used], MyMacAddress::PermanentAddress, MACADDRESS_BYTELEN );
            used += MACADDRESS_BYTELEN;
#if defined(_DEBUG)
            printf("mac: %02x-%02x-%02x-%02x-%02x-%02x\n",
                MyMacAddress::PermanentAddress[0],MyMacAddress::PermanentAddress[1],
                MyMacAddress::PermanentAddress[2],MyMacAddress::PermanentAddress[3],
                MyMacAddress::PermanentAddress[4],MyMacAddress::PermanentAddress[5]);
#endif

        }
        else
        {
            int len = GetMac( &tembuf[used], total-used );
            used += len;
        }
    }
    
    if( flag&PCID_CPU )
    {
        int arr[4];
        ZeroMemory( arr, sizeof(arr) );
        __cpuid( arr, 0 );
        memcpy_s( &tembuf[used], total-used, arr, sizeof(arr));
        used += sizeof(arr);
        
        ZeroMemory( arr, sizeof( arr ) );
        __cpuid( arr, 1 );
        memcpy_s( &tembuf[used], total-used, arr, 4);
        memcpy_s( &tembuf[used + 4], total-used, arr + 2, sizeof(arr) - 8);
        //memcpy_s( &tembuf[used], total-used, arr, sizeof(arr));
        used += (sizeof(arr) - 4);
        
        ZeroMemory( arr, sizeof( arr ));
        __cpuid( arr, 3 );
        memcpy_s( &tembuf[used], total-used, arr, sizeof(arr) );
        used += sizeof(arr);   
    }
    if( flag&PCID_BIOS )
    {
        CBiosInfo bios;
        if( bios.InitBiosInfo() )
        {
            string str = bios.GetSystemECAssetTagNmuber();
            str += bios.GetSystemECManufacturer();
            str += bios.GetSystemECSerialNumber();
            str += bios.GetSystemECType();
            str += bios.GetSystemECVersion();
            str += bios.GetSystemFamily();
            str += bios.GetSystemManufacturer();
            str += bios.GetSystemProductName();
            str += bios.GetSystemSerialNumber();
            str += bios.GetSystemSKUNumber();
            str += bios.GetSystemVersion();
			if( total-used >= str.length() )
			{
				memcpy_s( &tembuf[used], total-used, str.c_str(), str.length() );
				used += str.length();
			}
			else
			{
				memcpy_s( &tembuf[used], total-used, str.c_str(), total-used );
				used += total-used;
			}
        }
    }


    MD5 md5( tembuf, used );
	memcpy_s( buf, 16, md5.digest(), 16 );
    return 16;
}

int CPCIDCalculator::GetMac( char * buf, int len )
{
    UINT uErrorCode = 0;
    IP_ADAPTER_INFO iai;
    ULONG uSize = 0;
    DWORD dwResult = GetAdaptersInfo( &iai, &uSize );
    if( dwResult == ERROR_BUFFER_OVERFLOW )
    {
        IP_ADAPTER_INFO* piai = (IP_ADAPTER_INFO*)new char[uSize];
        if( piai != NULL )
        {
            dwResult = GetAdaptersInfo( piai, &uSize );
            if( dwResult == ERROR_SUCCESS )
            {
                IP_ADAPTER_INFO* piai2 = piai;
                DWORD uSystemInfoLen = 0;
                while( piai2 != NULL && ( uSystemInfoLen + piai2->AddressLength ) < len )
                {
                    if( piai2->AddressLength > 0 )
                    {
                        CopyMemory( buf + uSystemInfoLen, piai2->Address, piai2->AddressLength );
                        uSystemInfoLen += piai2->AddressLength;
                        break;
                    }
                    piai2 = piai2->Next;
                }
                delete piai;
                return uSystemInfoLen;
            }
        }
        delete piai;
    }
    return 0;
}
