Note: This is not the complete source code--just the main source file.
You can download the full source (with include files) from our sample code archive by clicking on the diskette icons.

MXbyHexDns.cpp

// MXbyHexDns sample
// version 2002-08-21
// 
// Demonstrates how to obtain MX records with HexDns.
//
// History:
// 2002-08-21  Created
//
// Copyright 2002 Hexillion Technologies. All rights reserved.
// 
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND/OR
// FITNESS FOR A PARTICULAR PURPOSE.


#include "stdafx.h"
#include <iostream>
#include "HexComPtr.h"
#include "HexDns.h"

#import "HexDns.dll" no_namespace

using namespace std;

int main(int argc, char* argv[])
	{
	int iReturn = 0;

	try
		{
		// If we don't have one argument (aside from utility name)...
		if( 2 != argc )
			{
			// Display usage and exit
			cout << "Usage: MXbyHexDns domain" << endl;
			throw 0;
			}

		CoInitialize( NULL );

		// Declare instance of a licensing-aware _com_ptr_t derivative
		HexComPtr< HEX_IIID( IConnectionSync ) > pDns;

		// Use this code to get your runtime license key while your license
		// file is in place. Then comment the code out and put the runtime
		// key in the CreateInstanceLic calls below. Your binary will then
		// work without the license file.
//		_bstr_t bstrKey;
//		pDns.RequestLicKey( __uuidof( Connection ), bstrKey );
//		cout << "Runtime license key: " << (TCHAR*)bstrKey << endl;

		// Create an instance of HexDns.Connection
		HRESULT hr = pDns.CreateInstanceLic( __uuidof( Connection ), L"*** Put your runtime license key here ***" );

		// If CreateInstance failed...
		if( FAILED( hr ) )
			{
			cout << "Creation of HexDns.Connection instance failed. HRESULT=0x" << hex << hr << endl;
			throw -1;
			}

		// You know you're using the runtime license when the Error property and
		// LicensedProcessors property are both zero
		bool bUsingRuntimeKey = (0 == pDns->Error) && (0 == pDns->LicensedProcessors);

		// Get an instance of HexDns.Lookup for converting IP addresses to strings
		HexComPtr< HEX_IIID( ILookupSync ) > pLkup;
		hr = pLkup.CreateInstanceLic( __uuidof( LookUp ), L"*** Put your runtime license key here ***" );

		// If CreateInstance failed...
		if( FAILED( hr ) )
			{
			cout << "Creation of HexDns.Lookup instance failed. HRESULT=0x" << hex << hr << endl;
			throw -1;
			}

		// If HexDns couldn't find local nameservers for some reason...
		if( 0 == pDns->ServerAddrs->Count )
			{
			cout << "HexDns could not find local nameservers." << endl;
			throw -1;
			}

		// Set the timeout
		pDns->Timeout = 4000;  // 4 seconds

		// Do the query
		IMessagePtr pMsg = pDns->Query( argv[1], hexDnsTypeMX, hexDnsClassIN );

		// If the query failed...
		if( hexDnsErrSuccess != pDns->Error )
			{
			cout << "MX query for " << argv[1] << " failed with error: " << (TCHAR*)GetDnsErrorString( pDns->Error ) << endl;
			throw -1;
			}

		// If the server returned an error...
		if( hexDnsMsgRcodeSuccess != pMsg->ResponseCode )
			{
			cout << "The nameserver returned an error: " << (TCHAR*)GetMsgRcodeString( pMsg->ResponseCode ) << endl;
			throw -1;
			}

		// Write an intro
		cout << "MX records returned for " << argv[1] << ':' << endl;

		// Cache pointers to returned record collections
		// These are 1-based collections
		IRecordsPtr pAnswers = pMsg->AnswerRecords;
		IRecordsPtr pAdditionals = pMsg->AddtlRecords;

		long lMaxAns = pAnswers->Count;  
		long lMaxAdd = pAdditionals->Count;
		long lAddr;
		int iCount = 0;
		IRecordPtr pRec;
		IRecordInMxPtr pMX;

		// For each record in the Answers section...
		for( long l = 1; l <= lMaxAns; l++ )
			{
			pRec = pAnswers->Item( l );

			// If it's an MX record (and not, say, a CNAME record)...
			if( hexDnsTypeMX == pRec->Type )
				{
				iCount++;
				pMX = (IRecordInMxPtr)pRec;

				// Loop through the Additionals section looking for a corresponding A record
				lAddr = 0;
				for( long m = 1; m <= lMaxAdd; m++ )
					{
					IRecordPtr pRecAdd = pAdditionals->Item( m );

					// If it's an A record with the name of the exchanger...
					if( hexDnsTypeA == pRecAdd->Type &&
						pRecAdd->Name == pMX->Exchange )
						{
						// Grab the address
						lAddr = ((IRecordInAPtr)pRecAdd)->Addr;
						break;
						}
					}

				// Print the record
				cout << '\t' << pMX->Preference << '\t' << (TCHAR*)(pMX->Exchange);

				if( 0 != lAddr )
					cout << " [" << (TCHAR*)(pLkup->AddrToString( lAddr )) << ']';

				cout << endl;
				}
			}

		// If we didn't get any MX records...
		if( 0 == iCount )
			// Say so
			cout << "\t(none)" << endl;
		}
	catch( int i )
		{
		iReturn = i;
		}

	CoUninitialize();

	return iReturn;
	}