Click here to Skip to main content
15,892,927 members
Articles / Desktop Programming / MFC

The Ultimate TCP/IP Home Page

Rate me:
Please Sign up or sign in to vote.
4.98/5 (77 votes)
25 Aug 2007CPOL13 min read 2.6M   45.4K   267  
Ultimate TCP-IP is now Open Source
//=================================================================
//  class: CDNS
//  File:  DNS.cpp
//
//  Implementation of CDNS class
//
//=================================================================
// Ultimate TCP/IP v4.2
// This software along with its related components, documentation and files ("The Libraries")
// is � 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
// governed by a software license agreement ("Agreement").  Copies of the Agreement are
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
// to obtain this file, or directly from our office.  For a copy of the license governing
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
//=================================================================

#include "stdafx.h"
#include <process.h>
#include <time.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include "UTDns.h"
#include "DNS.h"
#include "AboutDlg.h"

// Suppress warnings for non-safe str fns. Transitional, for VC6 support.
#pragma warning (push)
#pragma warning (disable : 4996)

/////////////////////////////////////////////////////////////////////////////
// CDNS
/////////////////////////////////////////////////////////////////////////////

/***************************************************
CDNS
	Standart constructor. 
Params
    none
Return
	none
****************************************************/
CDNS::CDNS() :
		m_bBlockingMode(FALSE),			// Set non blocking mode as default
		m_lnLookupTimeOut(20),			// Set default lookup time-out 
		m_bDoAuthoritativeLookup(FALSE),// Clear Authoritative Lookup flag
		m_bDNSThreadRunning(FALSE),		// Clear DNS thread flag
		m_bGoingToClose(FALSE),			// Initialize closing flag with FALSE
		m_hDNSThread(NULL),				// Initialize DNS thread with NULL
		m_bDNSEntryValid(FALSE),		// Clear DNS entry valid flag
		m_bAbortFlag(FALSE)				// Clear abort flag
{
	// Load DNS Icon
	m_hDNSIcon = LoadIcon(_Module.m_hInst, MAKEINTRESOURCE(IDI_ICON_DNS));	

	// Initiate default control size 32 x 32 pixels
    SIZE	sz = { 32, 32 };
    AtlPixelToHiMetric (&sz, &m_sizeExtent);		// convert pixels to himetric
    m_sizeNatural	= m_sizeExtent;					// store natural extent

	// Disable resizing of the control
	m_bAutoSize		= TRUE;				
}


/***************************************************
~CDNS
	Destructor.
Params
    none
Return
	none
****************************************************/
CDNS::~CDNS()
{
	// Set flags to terminate all running threads
	m_bGoingToClose	= TRUE;
	m_bAbortFlag	= TRUE;

	// Hmmm  there is  a bug in ATL 3.0
	// lets try to hack it
	HRESULT		hr = CoInitialize(NULL);



	// If DNS thread is running - will wait till it exits
	// or will time-out. Time-out value is based upon m_lnLookupTimeOut
	// but it can't be less than 2 minutes
	if(m_bDNSThreadRunning) 
	{
		ResumeThread(m_hDNSThread);
		WaitForSingleObject(m_hDNSThread, max(m_lnLookupTimeOut+1 * 1000, 60000));
	}

	// Destroy DNS icon handle
	if(m_hDNSIcon) {
		DestroyIcon( m_hDNSIcon );							
		m_hDNSIcon = NULL;
		}

//	CoUninitialize();
}

/***************************************************
InterfaceSupportsErrorInfo
	Checks if specified interface supports error
	information.
Params
    riid	- inteface id
Return
	S_OK	- support error info
	S_FALSE - don't support error info
****************************************************/
STDMETHODIMP CDNS::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = {	&IID_IDNS, };

	for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++) {
		if (InlineIsEqualGUID(*arr[i], riid))
			return S_OK;
		}

	return S_FALSE;
}

/***************************************************
OnDraw
	Draw the icon
Params
    di	- A reference to the ATL_DRAWINFO structure
Return
	S_OK	- success
****************************************************/
HRESULT CDNS::OnDraw(ATL_DRAWINFO& di)
{
	// Fill background & draw a boreder
	RECT& rc = *(RECT*)di.prcBounds;
	Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);

	// Draw DNS Icon
	if(m_hDNSIcon)
		DrawIcon(di.hdcDraw, rc.left, rc.top, m_hDNSIcon);	
 		
	return S_OK;
}

/***************************************************
GetInterfaceSafetyOptions
	Gets inteface safety options
Params
	riid				- interface ID
	pdwSupportedOptions	- supported options
	pdwEnabledOptions	- enabled options
Return
	S_OK			- success
	E_NOINTERFACE	- no such interface
	E_FAIL			- failed
****************************************************/
STDMETHODIMP CDNS::GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
{

	ATLTRACE(_T("CObjectSafetyImpl::GetInterfaceSafetyOptions\n"));

	if (!pdwSupportedOptions || !pdwEnabledOptions)
		return E_FAIL;

	LPUNKNOWN pUnk;
	if (_InternalQueryInterface (riid, (void**)&pUnk) == E_NOINTERFACE) {
		// Our object doesn't even support this interface.
		return E_NOINTERFACE;
		}
	else {
		// Cleanup after ourselves.
		pUnk->Release();
		pUnk = NULL;
		}

	if (riid == IID_IDispatch) {
		// IDispatch is an interface used for scripting. If your
		// control supports other IDispatch or Dual interfaces, you
		// may decide to add them here as well. Client wants to know
		// if object is safe for scripting. Only indicate safe for
		// scripting when the interface is safe.
		*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
		*pdwEnabledOptions = m_dwCurrentSafety & INTERFACESAFE_FOR_UNTRUSTED_CALLER;
		return S_OK;
		}
	else if ((riid == IID_IPersistStreamInit) || (riid == IID_IPersistStorage) || (riid == IID_IPersistPropertyBag)) {
		// IID_IPersistStreamInit and IID_IPersistStorage are
		// interfaces used for Initialization. If your control
		// supports other Persistence interfaces, you may decide to
		// add them here as well. Client wants to know if object is
		// safe for initializing. Only indicate safe for initializing
		// when the interface is safe.
		*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
		*pdwEnabledOptions = m_dwCurrentSafety & INTERFACESAFE_FOR_UNTRUSTED_DATA;
		return S_OK;
		}
	else {
		// We are saying that no other interfaces in this control are
		// safe for initializing or scripting.
		*pdwSupportedOptions = 0;
		*pdwEnabledOptions = 0;
		return E_FAIL;
		}
   }


/***************************************************
SetInterfaceSafetyOptions
	Sets inteface safety options
Params
	riid				- interface ID
	dwOptionSetMask		- options mask
	pdwEnabledOptions	- enabled options
Return
	S_OK			- success
	E_NOINTERFACE	- no such interface
	E_FAIL			- failed
****************************************************/
STDMETHODIMP CDNS::SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{

	ATLTRACE(_T("CObjectSafetyImpl::SetInterfaceSafetyOptions\n"));

	if (!dwOptionSetMask && !dwEnabledOptions) return E_FAIL;
   
	LPUNKNOWN pUnk;
	if (_InternalQueryInterface (riid, (void**)&pUnk) == E_NOINTERFACE) {
		// Our object doesn't even support this interface.
		return E_NOINTERFACE;
		}
	else {
		// Cleanup after ourselves.
		pUnk->Release();
		pUnk = NULL;
		}

	// Store our current safety level to return in
	// GetInterfaceSafetyOptions
	m_dwCurrentSafety |= dwEnabledOptions & dwOptionSetMask;
	if ((riid == IID_IDispatch) && (m_dwCurrentSafety & INTERFACESAFE_FOR_UNTRUSTED_CALLER)) {
		// Client wants us to disable any functionality that would
		// make the control unsafe for scripting. The same applies to
		// any other IDispatch or Dual interfaces your control may
		// support. Because our control is safe for scripting by
		// default we just return S_OK.
		return S_OK;
		}
	else if (((riid == IID_IPersistStreamInit) || (riid == IID_IPersistStorage) || (riid == IID_IPersistPropertyBag)) &&
             (m_dwCurrentSafety & INTERFACESAFE_FOR_UNTRUSTED_DATA)) {
		// Client wants us to make the control safe for initializing
		// from persistent data. For these interfaces, this control
		// is safe so we return S_OK. For Any interfaces that are not
		// safe, we would return E_FAIL.
		return S_OK;
		}
	else {
		// This control doesn't allow Initialization or Scripting
		// from any other interfaces so return E_FAIL.
		return E_FAIL;
		}
}


////////////////////////////////////////////////////
//	Current entry Get functions
////////////////////////////////////////////////////

/***************************************************
get_EntryHostName
    Gets current entry host name
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::get_EntryHostName(BSTR *pVal)
{
	if(pVal == NULL)	return E_POINTER;

	_bstr_t	bstrString = m_CurDNSEntry.szHost;
	if(!SysReAllocString(pVal, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
get_EntryType
    Gets current entry type
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntryType(DNSEntryTypes *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.nType;
	return S_OK;
}

/***************************************************
get_EntryTimeToLive
    Gets current entry Time To Live
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntryTimeToLive(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lTTL;
	return S_OK;
}

/***************************************************
get_EntrySOA_Serial
    Gets current entry Start of Authority Zone Saerial
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntrySOA_Serial(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lSOA_Serial;
	return S_OK;
}

/***************************************************
get_EntrySOA_Refresh
    Gets current entry time interval before the zone 
	should be refreshed.
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntrySOA_Refresh(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lSOA_Refresh;
	return S_OK;
}

/***************************************************
get_EntrySOA_Retry
    Gets current entry time interval that should elapse 
	befaore a failed refresh should be tried.
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntrySOA_Retry(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lSOA_Retry;
	return S_OK;
}

/***************************************************
get_EntrySOA_Expire
	Gets current entry upper limit on the time interval 
	that can elapse before the zone is no longer authoritative.
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntrySOA_Expire(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lSOA_Expire;
	return S_OK;
}

/***************************************************
get_EntrySOA_Minimum
	Gets current entry minimum TTL field that should 
	be exported with any entry from this zone.
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntrySOA_Minimum(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.lSOA_Minimum;
	return S_OK;
}

/***************************************************
get_EntryData
	Gets current entry data
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntryData(BSTR *pVal)
{
	if(pVal == NULL)	return E_POINTER;

	_bstr_t	bstrString = m_CurDNSEntry.szData;
	if(!SysReAllocString(pVal, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
get_EntryData2
	Gets current entry data2
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntryData2(BSTR *pVal)
{
	if(pVal == NULL)	return E_POINTER;

	_bstr_t	bstrString = m_CurDNSEntry.szData2;
	if(!SysReAllocString(pVal, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
get_EntryMX_Preference
	Gets current entry 16 bit integer which specifies 
	the prefrence givin to this entry among others at 
	the same host. (Mail Exchange Type entries only)
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK			- success
	E_POINTER		- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_EntryMX_Preference(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (DNSEntryTypes)m_CurDNSEntry.nMX_Preference;
	return S_OK;
}

////////////////////////////////////////////////////
//	IFinger interface properties Set/Get functions
////////////////////////////////////////////////////

/***************************************************
get_LookupTimeOut
    Gets lookup time out
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK		- success
	E_POINTER	- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_LookupTimeOut(long *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = m_lnLookupTimeOut;
	return S_OK;
}

/***************************************************
put_LookupTimeOut
    Sets lookup time out
Params
    newVal	- new value of the property
Return
	S_OK		- success
	S_FALSE		- can't change property now
	E_FAIL		- invalid connect time-out value
****************************************************/
STDMETHODIMP CDNS::put_LookupTimeOut(long newVal)
{
	if(newVal == m_lnLookupTimeOut)	return S_OK;

	if(FireOnRequestEdit(DISPID_LOOKUP_TIME_OUT) == S_FALSE)
		return S_FALSE;

	if(newVal >= 0) {
		m_lnLookupTimeOut = newVal;
		m_bRequiresSave = TRUE;
		SetLookupTimeOut(m_lnLookupTimeOut);

		FireOnChanged(DISPID_LOOKUP_TIME_OUT);

		SendOnDataChange(NULL);
		}
	else 
		return AtlReportError(CLSID_DNS,"Invalid Lookup Time Out value", IID_IDNS, E_FAIL);

	return S_OK;
}

/***************************************************
get_BlockingMode
    Gets blocking mode
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK		- success
	E_POINTER	- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_BlockingMode(VARIANT_BOOL *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = m_bBlockingMode;
	return S_OK;
}

/***************************************************
put_BlockingMode
    Sets blocking mode
Params
    newVal	- new value of the property
Return
	S_OK		- success
	S_FALSE		- can't change property now
	E_FAIL		- invalid connect time-out value
****************************************************/
STDMETHODIMP CDNS::put_BlockingMode(VARIANT_BOOL newVal)
{
	if(newVal == m_bBlockingMode)	return S_OK;

	if(FireOnRequestEdit(DISPID_BLOCKING_MODE) == S_FALSE)
		return S_FALSE;

	m_bBlockingMode = newVal;
	m_bRequiresSave = TRUE;

	FireOnChanged(DISPID_BLOCKING_MODE);

	SendOnDataChange(NULL);

	return S_OK;
}

/***************************************************
get_IncludeDefaultMX
    Gets IncludeDefaultMX flag
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK		- success
	E_POINTER	- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_IncludeDefaultMX(VARIANT_BOOL *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = GetIncludeDefaultMX();
	return S_OK;
}

/***************************************************
put_IncludeDefaultMX
    Sets IncludeDefaultMX flag
Params
    newVal	- new value of the property
Return
	S_OK		- success
	S_FALSE		- can't change property now
****************************************************/
STDMETHODIMP CDNS::put_IncludeDefaultMX(VARIANT_BOOL newVal)
{
	if(newVal == (VARIANT_BOOL)GetIncludeDefaultMX())	return S_OK;

	if(FireOnRequestEdit(DISPID_INCLUDE_DEF_MX) == S_FALSE)
		return S_FALSE;

	IncludeDefaultMX(newVal != 0);
	m_bRequiresSave = TRUE;

	FireOnChanged(DISPID_BLOCKING_MODE);

	SendOnDataChange(NULL);
	
	return S_OK;
}

/***************************************************
get_IsAuthoritative
    Returns TRUE if the last lookup was autoritative.
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK		- success
	E_POINTER	- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_IsAuthoritative(VARIANT_BOOL *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = CUT_DNSClient::IsAuthoritative();
	return S_OK;
}

/***************************************************
get_Protocol
    Gets current protocol TCP or UDP
Params
    pVal	- pointer to the variable receiving the value
Return
	S_OK		- success
	E_POINTER	- wrong pointer
****************************************************/
STDMETHODIMP CDNS::get_Protocol(ProtocolTypes *pVal)
{
	if(pVal == NULL)	return E_POINTER;
	*pVal = (CUT_DNSClient::GetUseUDP()) ? ptUDP : ptTCP;
	return S_OK;
}

/***************************************************
put_Protocol
    Sets current protocol TCP or UDP
Params
    newVal	- new value of the property
Return
	S_OK		- success
	S_FALSE		- can't change property now
	E_FAIL		- invalid connect time-out value
****************************************************/
STDMETHODIMP CDNS::put_Protocol(ProtocolTypes newVal)
{
	if(newVal == ((CUT_DNSClient::GetUseUDP()) ? ptUDP : ptTCP))	return S_OK;

	if(FireOnRequestEdit(DISPID_PROTOCOL) == S_FALSE)
		return S_FALSE;

	if(newVal == ptUDP)
		CUT_DNSClient::SetUseUDP(TRUE);
	else
		CUT_DNSClient::SetUseUDP(FALSE);

	m_bRequiresSave = TRUE;

	FireOnChanged(DISPID_PROTOCOL);

	SendOnDataChange(NULL);

	return S_OK;
}

////////////////////////////////////////////////////
//	IFinger interface methods
////////////////////////////////////////////////////

/***************************************************
Lookup
    Performs a basic DNS lookup of the given
    name. The results are held internally and
    can be retrieved with the Enum... functions
Params
    Server	- the name of the server to send the request to
    Domain	- domain name to look up
    Result  - return code
Return
	S_OK	- success
****************************************************/
STDMETHODIMP CDNS::Lookup(BSTR Server, BSTR Domain, DNSRequestTypes Type, int *Result)
{
	HRESULT		hResult		= S_OK;

	// If thread is already running return fecInUse
	if( ! m_bDNSThreadRunning ) {

		m_bAbortFlag		= FALSE;		// Clear abort flag

		m_bstrServer	= Server;	// Save server name to send the request to
		m_bstrDomain	= Domain;	// Save domain name to lookup
		m_nType			= Type;		// Save request type

		// If we use blocking mode
		if(m_bBlockingMode) {
			LONG	lRetCode;

			// Lookup name
			if(m_bDoAuthoritativeLookup)
				lRetCode = CUT_DNSClient::AuthoritativeLookup(m_bstrServer, m_bstrDomain, m_nType);
			else
				lRetCode = CUT_DNSClient::LookupName(m_bstrServer, m_bstrDomain, m_nType);

			// Fire DNS Result event
			Fire_OnLookup(lRetCode);

			*Result = lRetCode;
			}

		// If we use non blocking mode - create separate thread
		else {
			// Marshal all event sinks intefaces into streams
			MarshalInterfacesToStream(this);

			// Begin DNS thread
			m_hDNSThread = (HANDLE)_beginthread(( void (__cdecl *)(void *)) DNSThread,NULL, (void *) this);
			if(m_hDNSThread == (HANDLE) -1) {
				*Result = ecInternalError;
				hResult = E_OUTOFMEMORY;
				}
			else  {
				m_bDNSThreadRunning = TRUE;
				*Result = ecSuccess;
				}
			}

		}
	else 
		*Result = ecInUse;

	if(!m_bDNSThreadRunning)
		m_bDoAuthoritativeLookup = FALSE;

	return hResult;
}

/***************************************************
AuthoritativeLookup
    Performs an authorized DNS lookup of the given
    name. If the given name server is not
    authorized for the given domain, then this 
    routine will try and search for an authorized
    name server. The results are held internally and
    can be retrieved with the Enum... functions
Params
    Server	- the name of the server to send the request to
    Domain	- domain name to look up
    Result  - return code
Return
	S_OK	- success
****************************************************/
STDMETHODIMP CDNS::AuthoritativeLookup(BSTR Server, BSTR Domain, DNSRequestTypes Type, int *Result)
{
	m_bDoAuthoritativeLookup = TRUE;
	
	return Lookup(Server, Domain, Type, Result);
}

/***************************************************
GetEntryShortName
	Gets the name of the entry type in short format
Params
    EntryType	- entry type
    Name		- pointer to the result name
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::GetEntryShortName(DNSEntryTypes EntryType, BSTR *Name)
{
	_bstr_t	bstrString = CUT_DNSClient::GetShortName(EntryType);

	if(!SysReAllocString(Name, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
GetEntryLongName
	Gets the name of the entry type in long format
Params
    EntryType	- entry type
    Name		- pointer to the result name
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::GetEntryLongName(DNSEntryTypes EntryType, BSTR *Name)
{
	_bstr_t	bstrString = CUT_DNSClient::GetLongName(EntryType);

	if(!SysReAllocString(Name, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}
/***************************************************
GetNameFromAddress
	Returns the name associated with the given address
Params
    Address - address string to lookup
    Name    - pointer to the result name
    Result  - return code
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::GetNameFromAddress(BSTR Address, BSTR *Name, int *Result)
{
	char	buffer[DNS_BUFFER_SIZE + 1];
	_bstr_t	bstrString = Address;

	if((*Result = CUT_WSClient::GetNameFromAddress(bstrString, buffer, DNS_BUFFER_SIZE)) == UTE_SUCCESS)
		bstrString = buffer;
	else
		bstrString = L"";

 	if(!SysReAllocString(Name, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
GetAddressFromName
	Returns the address associated with the given name
Params
    Name	- name to lookup
    Address - pointer to the result address
    Result  - return code
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::GetAddressFromName(BSTR Name, BSTR *Address, int *Result)
{
	char	buffer[DNS_BUFFER_SIZE + 1];
	_bstr_t	bstrString = Name;

	if((*Result = CUT_WSClient::GetAddressFromName(bstrString, buffer, DNS_BUFFER_SIZE)) == UTE_SUCCESS)
		bstrString = buffer;
	else
		bstrString = L"";

 	if(!SysReAllocString(Address, bstrString))
 		return E_OUTOFMEMORY;

	return S_OK;
}

/***************************************************
EnumDNSServers
    Enumerates the available name servers
    that were returned during the last lookup.
    If an address is available as well as the
    name then it is also returned
Params
    Name	- pointer to the result name
    Address	- pointer to the result address
    Result  - return code
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::EnumDNSServers(BSTR *Name, BSTR *Address, int *Result)
{
	char	bufName[DNS_BUFFER_SIZE + 1], bufAddress[DNS_BUFFER_SIZE + 1];

	if((*Result = CUT_DNSClient::EnumDNSServers(bufName, DNS_BUFFER_SIZE, bufAddress, DNS_BUFFER_SIZE)) == UTE_SUCCESS) {
		m_bDNSEntryValid = TRUE;
		
		_bstr_t		bstrString = bufName;
		if(!SysReAllocString(Name, bstrString))
 			return E_OUTOFMEMORY;
		
		bstrString = bufAddress;
		if(!SysReAllocString(Address, bstrString))
 			return E_OUTOFMEMORY;
		}
	else
		m_bDNSEntryValid = FALSE;

	return S_OK;
}

/***************************************************
EnumMXRecords
    Enumerates the available mail servers
    that were returned during the last lookup.
    If an address is available as well as the
    name then it is also returned
Params
    Name	- pointer to the result name
    Address	- pointer to the result address
    Result  - return code
Return
	S_OK			- success
	E_OUTOFMEMORY	- not enough memory
****************************************************/
STDMETHODIMP CDNS::EnumMXRecords(BSTR *Name, BSTR *Address, int *Result)
{
	char	bufName[DNS_BUFFER_SIZE + 1], bufAddress[DNS_BUFFER_SIZE + 1];

	if((*Result = CUT_DNSClient::EnumMXRecords(bufName, DNS_BUFFER_SIZE, bufAddress, DNS_BUFFER_SIZE)) == UTE_SUCCESS) {
		m_bDNSEntryValid = TRUE;
		
		_bstr_t		bstrString = bufName;
		if(!SysReAllocString(Name, bstrString))
 			return E_OUTOFMEMORY;
		
		bstrString = bufAddress;
		if(!SysReAllocString(Address, bstrString))
 			return E_OUTOFMEMORY;
		}
	else
		m_bDNSEntryValid = FALSE;

	return S_OK;
}

/***************************************************
EnumDNSEntry
    Enumerates the available DNS entries
    that were returned during the last lookup.
Params
    Result  - return code
Return
	S_OK		- success
****************************************************/
STDMETHODIMP CDNS::EnumDNSEntry(int *Result)
{
	if((*Result = CUT_DNSClient::EnumDNSEntry(&m_CurDNSEntry)) == UTE_SUCCESS)
		m_bDNSEntryValid = TRUE;
	else
		m_bDNSEntryValid = FALSE;
	return S_OK;
}

/***************************************************
ResetEnumeration
	Resets the enumeration routines so that
    the next time one is called it will start
    from the beginning.
Params
    none
Return
	S_OK		- success
****************************************************/
STDMETHODIMP CDNS::ResetEnumeration()
{
	ResetEnumerations();
	return S_OK;
}

/***************************************************
CancelLookup
	Cancel current name lookup operation
Params
    none
Return
	S_OK		- success
****************************************************/
STDMETHODIMP CDNS::CancelLookup()
{
	m_bAbortFlag = TRUE;
	return S_OK;
}
/***************************************************
AboutBox
	Display about box
Params
    none
Return
	S_OK		- success
****************************************************/
STDMETHODIMP CDNS::AboutBox()
{
	CAboutDlg	dlg;

	dlg.DoModal();
	return S_OK;
}

/***************************************************
GetErrorText
	Returns a string representation of numeric error code.
Params
	ErrorCode	- number of error code
	ErrorText	- pointer to the error text varaible
Return
	S_OK			- success
	E_OUTOFMEMORY	- out of memory
****************************************************/
STDMETHODIMP CDNS::GetErrorText(long ErrorCode, BSTR *ErrorText)
{
 	HRESULT		hResult			= S_OK;
 	CComBSTR	bstrErrorMsg	= CUT_ERR::GetErrorString(ErrorCode);
 
 	if(!SysReAllocString(ErrorText, bstrErrorMsg))
 		hResult = E_OUTOFMEMORY;
 
 	return hResult;
}

/***************************************************
IsAborted
    This virtual function is called during time consuming
	operations to check if we want to abort operatin
Params
    none
Return
    TRUE	- abort operation
	FALSE	- continue
****************************************************/
BOOL CDNS::IsAborted() {
	return m_bAbortFlag;
}

/***************************************************
WaitWithMsgLoop
    Waits for the object to be signaled, meanwhile 
	dispatching window messages as needed. Analog of
	AtlWaitWithMessageLoop() but supports timeouts.
Params
    hEvent	- event to wait
	lTimeot	- timeout
Return
	TRUE	- signaled
	FALSE	- timeout
****************************************************/
BOOL CDNS::WaitWithMsgLoop(HANDLE hEvent, long lTimeout)
{
	struct _timeb	tstruct;
	DWORD			dwStartTime, dwCurTime;
	DWORD			dwRet;
	MSG				msg;
    

	// Get current time
	_ftime( &tstruct );
	dwStartTime  =	tstruct.millitm + (DWORD)(tstruct.time * 1000);

	while(1)
	{
		// Wait for our event or any message 
		dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, lTimeout, QS_ALLINPUT);

		if (dwRet == WAIT_OBJECT_0)
			return TRUE;    // The event was signaled

		if (dwRet != WAIT_OBJECT_0 + 1)
			break;          // Something else happened (timeout)

		// There is one or more window message available. Dispatch them
		while(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE))
		{
			// Each time subtract from timeout value
			_ftime( &tstruct );
			dwCurTime  =	tstruct.millitm + (DWORD)(tstruct.time * 1000);
			lTimeout -= (dwStartTime-dwCurTime);

			// Timed out
			if(lTimeout < 0)
				return FALSE;

			// Translate messages
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
				return TRUE; // Event is now signaled.
		}
	}
	return FALSE;
}
/***************************************************
DNSThread
    DNS thread function.
Params
    pThis	- pointer to the CDNS class
Return
	none
****************************************************/
void __stdcall CDNS::DNSThread( LPVOID pThis )
{

	CDNS		*ptrDNS	= (CDNS*)  pThis;
	HRESULT		hr = CoInitialize(NULL);
	LONG		lRetCode;

	if( hr == S_OK ) {
		if(ptrDNS != NULL) {
			if (ptrDNS->m_bGoingToClose )
			{
				// well the program is exiting so lets abort evrything
				ptrDNS->Fire_OnLookup(UTE_ABORTED);
				CoUninitialize();
				ptrDNS->m_bDoAuthoritativeLookup = FALSE;
				ptrDNS->m_bDNSThreadRunning = FALSE;
				_endthread();
				return ;

			}
			// Lookup name
			if(ptrDNS->m_bDoAuthoritativeLookup)
				lRetCode = ptrDNS->CUT_DNSClient::AuthoritativeLookup(ptrDNS->m_bstrServer, ptrDNS->m_bstrDomain, ptrDNS->m_nType);
			else
				lRetCode = ptrDNS->CUT_DNSClient::LookupName(ptrDNS->m_bstrServer, ptrDNS->m_bstrDomain, ptrDNS->m_nType);

			// Fire FingerResult event
			ptrDNS->Fire_OnLookup(lRetCode);
			}

		CoUninitialize();

		ptrDNS->m_bDoAuthoritativeLookup = FALSE;
		ptrDNS->m_bDNSThreadRunning = FALSE;
		}

	_endthread();
	return;
	}

#pragma warning (pop)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions