#include "stdafx.h"
#include "FarCryInstallJobs.h"



static inline unsigned int
HashDirectXVersion( unsigned int uiDirectXVersionMajor, unsigned int uiDirectXVersionMinor, TCHAR cDirectXVersionLetter )
{
	return( ( ( uiDirectXVersionMajor & 0x00FF ) << 24 ) |
		    ( ( uiDirectXVersionMinor & 0x00FF ) << 16 ) | 
			( ( cDirectXVersionLetter & 0xFFFF )       ) );
}



FARCRYINSTALLJOBS_API BOOL 
CheckForDirectX90bOrHigher()
{
	DWORD dwDirectXVersionMajor( 0 ); 
	DWORD dwDirectXVersionMinor( 0 );
	TCHAR cDirectXVersionLetter( 0 );

	bool bSuccessGettingMajor( false );
	bool bSuccessGettingMinor( false );
	bool bSuccessGettingLetter( false );

	// initialize COM
	HRESULT hr( CoInitialize( 0 ) );
	bool bCleanupCOM( SUCCEEDED( hr ) );

	// get an IDxDiagProvider
	bool bGotDirectXVersion( false );
	IDxDiagProvider* pDxDiagProvider( 0 );
	hr = CoCreateInstance( CLSID_DxDiagProvider, 0, CLSCTX_INPROC_SERVER, IID_IDxDiagProvider, (LPVOID*) &pDxDiagProvider );
	if( SUCCEEDED( hr ) )
	{
		// fill out a DXDIAG_INIT_PARAMS struct
		DXDIAG_INIT_PARAMS dxDiagInitParam;
		ZeroMemory( &dxDiagInitParam, sizeof( DXDIAG_INIT_PARAMS ) );
		dxDiagInitParam.dwSize                  = sizeof( DXDIAG_INIT_PARAMS );
		dxDiagInitParam.dwDxDiagHeaderVersion   = DXDIAG_DX9_SDK_VERSION;
		dxDiagInitParam.bAllowWHQLChecks        = false;
		dxDiagInitParam.pReserved               = 0;

		// init the m_pDxDiagProvider
		hr = pDxDiagProvider->Initialize( &dxDiagInitParam ); 
		if( SUCCEEDED( hr ) )
		{
			IDxDiagContainer* pDxDiagRoot( 0 );
			IDxDiagContainer* pDxDiagSystemInfo( 0 );

			// get the DxDiag root container
			hr = pDxDiagProvider->GetRootContainer( &pDxDiagRoot );
			if( SUCCEEDED( hr ) ) 
			{
				// get the object called DxDiag_SystemInfo
				hr = pDxDiagRoot->GetChildContainer( L"DxDiag_SystemInfo", &pDxDiagSystemInfo );
				if( SUCCEEDED( hr ) )
				{
					VARIANT var;
					VariantInit( &var );

					// get the "dwDirectXVersionMajor" property
					hr = pDxDiagSystemInfo->GetProp( L"dwDirectXVersionMajor", &var );
					if( SUCCEEDED( hr ) && var.vt == VT_UI4 )
					{
						dwDirectXVersionMajor = var.ulVal; 
						bSuccessGettingMajor = true;
					}
					VariantClear( &var );

					// get the "dwDirectXVersionMinor" property
					hr = pDxDiagSystemInfo->GetProp( L"dwDirectXVersionMinor", &var );
					if( SUCCEEDED( hr ) && var.vt == VT_UI4 )
					{
						dwDirectXVersionMinor = var.ulVal; 
						bSuccessGettingMinor = true;
					}
					VariantClear( &var );

					// get the "szDirectXVersionLetter" property
					hr = pDxDiagSystemInfo->GetProp( L"szDirectXVersionLetter", &var );
					if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != 0 )
					{
#ifdef UNICODE
						cDirectXVersionLetter = var.bstrVal[ 0 ]; 
#else
						char strDestination[ 10 ];
						WideCharToMultiByte( CP_ACP, 0, var.bstrVal, -1, strDestination, sizeof( strDestination ), 0, 0 );
						cDirectXVersionLetter = strDestination[ 0 ]; 
#endif
						bSuccessGettingLetter = true;
					}
					VariantClear( &var );

					// if it all worked right, then mark it down
					if( bSuccessGettingMajor && bSuccessGettingMinor && bSuccessGettingLetter )
					{
						bGotDirectXVersion = true;
					}

					pDxDiagSystemInfo->Release();
				}

				pDxDiagRoot->Release();
			}
		}
		
		pDxDiagProvider->Release();
	}

	// uninitialize COM
	if( false != bCleanupCOM )
	{
		CoUninitialize();
	}

#ifdef _DEBUG
	// spit out DirectX version in a message box (for testing only!)
	TCHAR pcDbgOutput[ 32 ];
	_stprintf( pcDbgOutput, _T( "DirectX %d.%d%c" ), dwDirectXVersionMajor, dwDirectXVersionMinor, cDirectXVersionLetter );
	::MessageBox( 0, pcDbgOutput, _T( "In debug build only!" ), MB_OK );
#endif

	// check version requirements
	if( false != bGotDirectXVersion )
	{
		return( HashDirectXVersion( dwDirectXVersionMajor, dwDirectXVersionMinor, cDirectXVersionLetter ) >= 
				HashDirectXVersion( 9, 0, TCHAR( 'b' ) ) );
	}

	// DirectX version couldn't be determined so assume DirectX 9.0b isn't installed
	return( FALSE );
}
