Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2050 lines
56 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 1999--2001 Microsoft Corporation
//
// Module Name:
// CAlertEmailConsumer.cpp
//
// Description:
// Implementation of CAlertEmailConsumer class methods
//
// [Header File:]
// CAlertEmailConsumer.h
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <cdosys_i.c>
#include <wbemcli.h>
#include <wbemprov.h>
#include <wbemidl.h>
#include <appsrvcs.h>
#include <appmgrobjs.h>
#include <iads.h>
#include <Adshlp.h>
#include "alertemailmsg.h"
#include "CAlertEmailConsumer.h"
//
// Name of WBEM class
//
const WCHAR PROPERTY_CLASS_NAME [] = L"__CLASS";
//
// Key name of alert email's settings.
//
const WCHAR SA_ALERTEMAIL_KEYPATH [] =
L"SOFTWARE\\Microsoft\\ServerAppliance\\AlertEmail";
//
// Delimiter
//
const WCHAR DELIMITER[] = L"\\";
const WCHAR ENTER[] = L"\n";
const WCHAR COLON = L':';
const WCHAR ENDCODE = L'\0';
//
// HTTP header
//
const WCHAR HTTPHEADER[] = L"http://";
//
// SMTP Meta path
//
const WCHAR SMTP_META_PATH[] = L"IIS://LOCALHOST/SMTPSVC/1";
//
// Value name of alert email's settings.
//
const WCHAR ENABLEALERTEAMIL[] = L"EnableAlertEmail";
const WCHAR SENDEMAILTYPE[] = L"SendEmailType";
const WCHAR RECEIVEREMAILADDRESS[] = L"ReceiverEmailAddress";
//
// The setting value of alert->email disabled.
//
const DWORD ALERTEMAILDISABLED = 0;
//
// Name of caption ID in alertdefinitions.
//
const WCHAR ALERTDEFINITIONCAPTIONID [] = L"CaptionRID";
//
// Name of description ID in alertdefinitions.
//
const WCHAR ALERTDEFINITIONDESCRIPTIONRID [] = L"DescriptionRID";
//
// Name of resource file in alertdefintions.
//
const WCHAR ALERTDEFINITIONSOURCE [] = L"Source";
//
// Name of alert email resource
//
const WCHAR ALERTEMAILRESOURCE[] = L"AlertEmailMsg.dll";
//
// Max value of Appliance Name
//
const DWORD MAXAPPLIANCEDNSNAME = 1024;
//
// WBEM namespace to connection to
//
const WCHAR DEFAULT_NAMESPACE[] = L"root\\MicrosoftIISv1";
//
// Query Language to use for WBEM
//
const WCHAR QUERY_LANGUAGE [] = L"WQL";
//
// WBEM query which specifies the IIS server settings we're interest in.
//
const WCHAR QUERY_STRING [] =
L"select * from IIS_WebServerSetting where servercomment=\"Administration\"";
const WCHAR SERVERBINDINGSPROP[] = L"ServerBindings";
//
// PROGID of the Element Manager
//
const WCHAR ELEMENT_RETRIEVER [] = L"Elementmgr.ElementRetriever";
//
// PROGID of the Localization Manager
//
const WCHAR LOCALIZATION_MANAGER [] = L"ServerAppliance.LocalizationManager";
//
// Type name of alert resource information.
//
const WCHAR ALERTDEFINITIONS [] = L"AlertDefinitions";
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::CAlertEmailConsumer
//
// Description:
// Class constructor.
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
CAlertEmailConsumer::CAlertEmailConsumer()
{
m_cRef = 0L;
m_lCurAlertType = 0;
m_lAlertEmailDisabled = ALERTEMAILDISABLED;
m_pLocInfo = NULL;
m_pcdoIMessage = NULL;
m_pElementEnum = NULL;
m_hAlertKey = NULL;
m_hThread = NULL;
m_hCloseThreadEvent = NULL;
m_pstrFullyQualifiedDomainName = NULL;
m_pstrNetBIOSName = NULL;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::~CAlertEmailConsumer
//
// Description:
// Class deconstructor.
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
CAlertEmailConsumer::~CAlertEmailConsumer()
{
if( m_hAlertKey != NULL )
{
::RegCloseKey( m_hAlertKey );
}
if( m_pLocInfo != NULL )
{
m_pLocInfo->Release();
}
if( m_pElementEnum != NULL )
{
m_pElementEnum->Release();
}
if( m_pcdoIMessage != NULL )
{
m_pcdoIMessage->Release();
}
if( m_pstrFullyQualifiedDomainName != NULL )
{
::free( m_pstrFullyQualifiedDomainName );
}
if( m_pstrNetBIOSName != NULL )
{
::free( m_pstrNetBIOSName );
}
if( m_hThread != NULL )
{
::CloseHandle( m_hThread );
}
if( m_hCloseThreadEvent != NULL )
{
::CloseHandle( m_hCloseThreadEvent );
}
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::QueryInterface
//
// Description:
// An method implement of IUnkown interface.
//
// Arguments:
// [in] riid Identifier of the requested interface
// [out] ppv Address of output variable that receives the
// interface pointer requested in iid
//
// Returns:
// NOERROR if the interface is supported
// E_NOINTERFACE if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CAlertEmailConsumer::QueryInterface(
IN REFIID riid,
OUT LPVOID FAR *ppv
)
{
*ppv=NULL;
if (riid == IID_IUnknown || riid == IID_IWbemUnboundObjectSink)
{
*ppv = (IWbemUnboundObjectSink *) this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::AddRef
//
// Description:
// increments the reference count for an interface on an object
//
// Returns:
// The new reference count.
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
CAlertEmailConsumer::AddRef(void)
{
InterlockedIncrement( &m_cRef );
return m_cRef;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::Release
//
// Description:
// decrements the reference count for an interface on an object.
//
// Returns:
// The new reference count.
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG)
CAlertEmailConsumer::Release(void)
{
InterlockedDecrement( &m_cRef );
if (0 != m_cRef)
{
return m_cRef;
}
// delete this;
BOOL bReturn;
bReturn = ::SetEvent( m_hCloseThreadEvent );
if( !bReturn )
{
SATraceString(
"AlertEmail:Release setevent error!!!"
);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::IndicateToConsumer
//
// Description:
// An method implement of IWbemUnboundObjectSink interface.
//
// Arguments:
// [in] pLogicalConsumer Pointer to the logical consumer object for
// which this set of objects is delivered.
// [in] lObjectCount Number of objects delivered in the array that
// follows.
// [in] ppObjArray Pointer to an array of IWbemClassObject
// instances which represent the events delivered.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CAlertEmailConsumer::IndicateToConsumer(
IN IWbemClassObject *pLogicalConsumer,
IN long lObjectCount,
IN IWbemClassObject **ppObjArray
)
{
HRESULT hr = WBEM_S_NO_ERROR;
if( m_lAlertEmailDisabled == ALERTEMAILDISABLED )
{
return WBEM_S_NO_ERROR;
}
try
{
for (LONG lCount = 0; lCount < lObjectCount; lCount++)
{
//
// get the event type
//
CComVariant vtName;
hr = ppObjArray[lCount]->Get (
PROPERTY_CLASS_NAME,
0, //reserved
&vtName,
NULL, // type
NULL // flavor
);
if (FAILED (hr))
{
SATraceString(
"AlertEmail: IndicateToConsumer Get Class name failed"
);
break;
}
//
// check if we support the event received
//
if (0 == _wcsicmp (CLASS_WBEM_RAISE_ALERT, V_BSTR (&vtName)))
{
//
// handle a raise alert event
//
hr = RaiseAlert ( ppObjArray[lCount] );
if ( FAILED (hr) )
{
SATraceString(
"AlertEmail: IndicateToConsumer RaiseAlert failed"
);
break;
}
}
else if (0 == _wcsicmp (CLASS_WBEM_CLEAR_ALERT, V_BSTR (&vtName)))
{
//
// handle a clear alert
//
hr = ClearAlert ( ppObjArray[lCount] );
if ( FAILED (hr) )
{
SATraceString(
"AlertEmail: IndicateToConsumer ClearAlert failed"
);
break;
}
}
} // for loop
}
catch (...)
{
hr = WBEM_E_FAILED;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::ClearAlert
//
// Description:
// This is the CAlertEmailConsumer class private method
// which is NOT used now.
//
// Arguments:
// [in] pObject Pointer to an IWbemClassObject instances which
// represent ClearAlert events delivered.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::ClearAlert(
IN IWbemClassObject *pObject
)
{
HRESULT hr = WBEM_S_NO_ERROR;
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::RaiseAlert
//
// Description:
// This is the CAlertEmailConsumer class private method
// which is used to send email with the alert information
// by local SMTP server.
//
// Arguments:
// [in] pObject Pointer to an IWbemClassObject instances which
// represent RaiseAlert events delivered.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::RaiseAlert(
IN IWbemClassObject *pObject
)
{
LONG lAlertType;
CComVariant vtProperty;
HRESULT hr = WBEM_S_NO_ERROR;
//
// Get alert type.
//
hr = pObject->Get (
PROPERTY_ALERT_TYPE,
0, //reserved
&vtProperty,
NULL, // type
NULL // flavor
);
if( FAILED (hr) )
{
SATraceString(
"AlertEmail:RaiseAlert get alert type failed"
);
return hr;
}
//
// Map to bitmap type definition
//
lAlertType = 1 << V_I4( &vtProperty );
if( lAlertType & m_lCurAlertType )
{
//
// It's the type user set to send mail.
//
do
{
//
// Get name of alert resource dll.
//
CComVariant vtAlertLog;
hr = pObject->Get (
PROPERTY_ALERT_LOG,
0, //reserved
&vtAlertLog,
NULL, // type
NULL // flavor
);
if( FAILED (hr) )
{
SATraceString(
"AlertEmail:RaiseAlert get alert source failed"
);
break;
}
//
// Get alert ID.
//
CComVariant vtAlertID;
hr = pObject->Get (
PROPERTY_ALERT_ID,
0, //reserved
&vtAlertID,
NULL, // type
NULL // flavor
);
if( FAILED (hr) )
{
SATraceString(
"AlertEmail:RaiseAlert get alert ID failed"
);
break;
}
//
// Get replace strings.
//
CComVariant vtReplaceStr;
hr = pObject->Get (
PROPERTY_ALERT_STRINGS,
0, //reserved
&vtReplaceStr,
NULL, // type
NULL // flavor
);
if( FAILED (hr) )
{
SATraceString(
"AlertEmail:RaiseAlert get alert replace string failed"
);
break;
}
//
// We got all neccessary info,it's time to send email.
//
hr = SendMailFromResource(
V_BSTR( &vtAlertLog ),
V_I4( &vtAlertID ),
&vtReplaceStr
);
if( FAILED (hr) )
{
SATraceString(
"AlertEmail:RaiseAlert call SendMailFromResource failed"
);
break;
}
} //do
while ( FALSE );
} // if( lAlertType & m_lCurAlertType )
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::SendMailFromResource
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get useful message about the alert from Local Manager and send
// mail with the messages.
//
// Arguments:
// [in] lpszSource Point to the name of alert resource.
// [in] lSourceID Alert ID.
// [in] pvtReplaceStr Point to array of replace strings.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::SendMailFromResource(
LPWSTR lpszSource,
LONG lSourceID,
VARIANT* pvtReplaceStr
)
{
HRESULT hr = WBEM_S_NO_ERROR;
WCHAR wstrAlertItem[MAX_PATH];
IWebElement* pWebElement;
IDispatch* pDispatch;
//
// Format the alert item name:
// Name = AlertDefinitions<AlertLog><AlertID>
//
::wsprintf( wstrAlertItem, L"AlertDefinitions%s%lX", lpszSource,lSourceID );
//int cchWritten = _snwprintf( wstrAlertItem, MAX_PATH, L"AlertDefinitions%s%lX",
// lpszSource, lSourceID );
//if ( cchWritten >= MAX_PATH || cchWritten < 0 )
//{
// return E_INVALIDARG;
//}
do
{
//
// Get the element of alert definition from element manager.
//
hr = m_pElementEnum->Item(
&CComVariant( wstrAlertItem ),
&pDispatch
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource find alert item failed"
);
break;
}
hr = pDispatch->QueryInterface(
__uuidof (IWebElement),
reinterpret_cast <PVOID*> (&pWebElement)
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource queryinterface failed"
);
break;
}
//
// allocate BSTR for alertdefintion source
//
CComBSTR bstrAlertDefinitionSourceName (ALERTDEFINITIONSOURCE);
if (NULL == bstrAlertDefinitionSourceName.m_str)
{
SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINTIONSOURCE)");
hr = E_OUTOFMEMORY;
break;
}
//
//Get name of alert's resource dll.
// AlertLog != AlertSource now! -- 2001/02/07 i-xingj
//
CComVariant vtAlertSource;
hr = pWebElement->GetProperty (
bstrAlertDefinitionSourceName,
&vtAlertSource
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource get Alert source failed"
);
break;
}
//
// allocate BSTR for DesinitionCaptionID string
//
CComBSTR bstrAlertDefinitionCaptionIDName (ALERTDEFINITIONCAPTIONID);
if (NULL == bstrAlertDefinitionCaptionIDName.m_str)
{
SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINTIONCAPTIONID)");
hr = E_OUTOFMEMORY;
break;
}
//
// Get caption ID string
//
CComVariant vtCaptionID;
hr = pWebElement->GetProperty (
bstrAlertDefinitionCaptionIDName,
&vtCaptionID
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource find alert captionID failed"
);
break;
}
//
// allocate BSTR for AlertDescription RID
//
CComBSTR bstrAlertDefinitionDescriptionRIDName (ALERTDEFINITIONDESCRIPTIONRID);
if (NULL == bstrAlertDefinitionDescriptionRIDName.m_str)
{
SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINITIONDESCRIPTIONRID)");
hr = E_OUTOFMEMORY;
break;
}
//
// Get description ID string
//
CComVariant vtDescriptionID;
hr = pWebElement->GetProperty (
bstrAlertDefinitionDescriptionRIDName,
&vtDescriptionID
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource get alert descriptionID failed"
);
break;
}
LONG lAlertCaptionID;
LONG lAlertDescriptionID;
//
// Change type from string to long.
//
if ( EOF == ::swscanf( V_BSTR( &vtCaptionID ), L"%X", &lAlertCaptionID ))
{
SATraceString( "AlertEmail:SendMailFromResource get caption invalid" );
break;
}
if ( EOF == ::swscanf( V_BSTR( &vtDescriptionID ), L"%X", &lAlertDescriptionID ))
{
SATraceString( "AlertEmail:SendMailFromResource get description invalid" );
break;
}
//
// Get caption string from resource as email's subject.
//
CComBSTR pszSubject;
hr = m_pLocInfo->GetString(
V_BSTR( &vtAlertSource ),
lAlertCaptionID,
pvtReplaceStr,
&pszSubject
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource get subjuct failed"
);
break;
}
//
// Get description string from resource as email's message.
//
CComBSTR pszMessage;
hr = m_pLocInfo->GetString(
V_BSTR( &vtAlertSource ),
lAlertDescriptionID,
pvtReplaceStr,
&pszMessage
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource get message failed"
);
break;
}
//
// allocate BSTR for email source
//
CComBSTR bstrAlertEmailResourceName (ALERTEMAILRESOURCE);
if (NULL == bstrAlertEmailResourceName.m_str)
{
SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTEMAILRESOURCE)");
hr = E_OUTOFMEMORY;
break;
}
//
// Get alert email defined message.
//
CComBSTR pszConstantMessage;
hr = m_pLocInfo->GetString(
bstrAlertEmailResourceName,
SA_ALERTEMAIL_SETTINGS_EMAIL_CONTENT,
NULL,
&pszConstantMessage
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMailFromResource get constantMsg failed"
);
break;
}
pszMessage += CComBSTR( ENTER );
pszMessage += CComBSTR( ENTER );
pszMessage += pszConstantMessage;
//
// Send mail use local SMTP server.
//
hr = SendMail( pszSubject, pszMessage );
} //do
while( FALSE );
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::Initialize
//
// Description:
// This is the CAlertEmailConsumer class public method call by
// CAlertEmailConsumerProvider to initialize useful parameters.
//
// Returns:
// S_OK if successful
// E_FAIL if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::Initialize()
{
ULONG ulReturn;
HRESULT hr = S_OK;
DWORD dwThreadID;
//
// Initialize Element Manager.
//
hr = InitializeElementManager();
if (FAILED (hr))
{
SATraceString(
"AlertEmailProvider:Initialize InitializeElementManager failed"
);
return WBEM_E_FAILED;
}
//
// Initialize Local Manager
//
hr = InitializeLocalManager();
if (FAILED (hr))
{
SATraceString(
"AlertEmailProvider:Initialize InitializeLocalManager failed"
);
return WBEM_E_FAILED;
}
//
// Initialize a CDO IMessage interface.
//
hr = InitializeCDOMessage();
if (FAILED (hr))
{
SATraceString(
"AlertEmailProvider:Initialize InitializeCDOMessage failed"
);
return WBEM_E_FAILED;
}
//
// Open registry key of alertemail settings.
//
ulReturn = ::RegOpenKey(
HKEY_LOCAL_MACHINE,
SA_ALERTEMAIL_KEYPATH,
&m_hAlertKey
);
if( ulReturn != ERROR_SUCCESS )
{
SATraceString(
"AlertEmail:Initialize OpenKey failed"
);
return E_FAIL;
}
//
// Get alert email settings from registry.
//
if( FALSE == RetrieveRegInfo() )
{
SATraceString(
"AlertEmail:Initialize RetrieveRegInfo failed"
);
return E_FAIL;
}
//
// Get server name fully qualified domain anem.
//
if( FALSE == GetComputerName( &m_pstrFullyQualifiedDomainName, ComputerNameDnsFullyQualified ) )
{
SATraceString(
"AlertEmail:Initialize GetComputerName ComputerNameDnsFullyQualified failed"
);
return E_FAIL;
}
//
// Get server name.
//
if( FALSE == GetComputerName( &m_pstrNetBIOSName, ComputerNameNetBIOS ) )
{
SATraceString(
"AlertEmail:Initialize GetComputerName ComputerNameNetBIOS failed"
);
return E_FAIL;
}
//
// Event for notify thread exit.
//
m_hCloseThreadEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
if( m_hCloseThreadEvent == NULL )
{
SATraceString(
"AlertEmail:Initialize CreateEvent failed"
);
return E_FAIL;
}
//
// Thread used to monitor registy change.
//
m_hThread = ::CreateThread( 0,
0,
CAlertEmailConsumer::RegThreadProc,
this,
0,
&dwThreadID );
if( m_hThread == NULL )
{
SATraceString(
"AlertEmail:Initialize CreateThread failed"
);
return E_FAIL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::GetSMTPFromDomainName
//
// Description:
// Get the value of "Full Qualified Domain Name" entry in SMTP Delivery tab in MMC.
//
// Arguments:
// [out] bstrDomainName returns domain name that is found in Metabase.
//
// Returns:
// hr
//
//
//////////////////////////////////////////////////////////////////////////////
HRESULT CAlertEmailConsumer::GetSMTPFromDomainName( BSTR* bstrDomainName )
{
HRESULT hr = S_OK;
CComPtr<IADs> pADs;
//
// Initialize for return
//
*bstrDomainName = NULL;
CComBSTR bstrADSPath( SMTP_META_PATH );
if (NULL == bstrADSPath.m_str)
{
SATraceString ("CAlertEmailConsumer::GetSMTPFromDomainName failed to allocate memory for bstrADsPath");
return (E_OUTOFMEMORY);
}
hr = ADsGetObject( bstrADSPath, IID_IADs, (void**) &pADs );
if ( SUCCEEDED(hr) )
{
CComVariant varValue;
CComBSTR bstrFullyQualifiedDomainName (L"FullyQualifiedDomainName" );
if (NULL == bstrFullyQualifiedDomainName.m_str)
{
SATraceString ("CAlertEmailConsumer::GetSMTPFromDomainName failed to allocate memory for bstrFullyQualifiedDomainName");
hr = E_OUTOFMEMORY;
}
else
{
// Getting the FullyQualifiedDomainName property
hr = pADs->Get(bstrFullyQualifiedDomainName, &varValue );
if ( SUCCEEDED(hr) )
{
*bstrDomainName = SysAllocString( V_BSTR( &varValue ) );
}
}
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::SendMail
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to send mail through local SMTP server.
//
// Arguments:
// [in] bstrSubject Subject string.
// [in] bstrMessage Message string.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::SendMail(
BSTR bstrSubject,
BSTR bstrMessage
)
{
HRESULT hr = WBEM_S_NO_ERROR;
WCHAR* pstrPort = NULL;
do
{
//
// The algorithm is
// Look at the value of "Full Qualified Domain Name" entry in SMTP Delivery tab in MMC.
// 1) If the value is empty then the e-mail From Address is same as fully qualified domain name
// 2) IF there is value and that value is different from Full Qualified Computer Name then use
// 3) the following as From address.
// 4) Use the From Address as appliance_name@"Full Qualified Domain Name"
//
//
//
// allocate memory for BSTR
//
CComBSTR bstrFullyQualifiedDomainName( m_pstrFullyQualifiedDomainName );
if (NULL == bstrFullyQualifiedDomainName.m_str)
{
SATraceString("AlertEmail:SendMail failed to allocate memory for bstrFullyQualifiedDomainName" );
hr = E_OUTOFMEMORY;
break;
}
CComBSTR bstrFromAddress( m_pstrNetBIOSName );
if (NULL == bstrFromAddress.m_str)
{
SATraceString("AlertEmail:SendMail failed to allocate memory for bstrFromAddress" );
hr = E_OUTOFMEMORY;
break;
}
BSTR bstrDomainName = NULL;
//
// Read SMTP "Full Qualified Domain Name" from Metabase
hr = GetSMTPFromDomainName( &bstrDomainName );
if ( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail GetSMTPFromDomainName failed"
);
return E_FAIL;
}
if ( bstrDomainName )
{
if ( _wcsicmp( bstrFullyQualifiedDomainName, bstrDomainName ) != 0 )
{
bstrFromAddress += CComBSTR( L"@" );
bstrFromAddress += bstrDomainName ;
}
}
//
// Set bstrFromAddress that is formed using the above algorithm
// as mail sender.
//
hr = m_pcdoIMessage->put_From( bstrFromAddress );
//
// Free BSTR
//
if ( bstrDomainName )
{
SysFreeString( bstrDomainName );
}
CComBSTR bstrMailAddress (m_pstrMailAddress );
if (NULL == bstrMailAddress.m_str)
{
SATraceString("AlertEmail:SendMail failed to allocate memory for bstrMailAddress" );
hr = E_OUTOFMEMORY;
break;
}
//
// Set mail address.
//
hr = m_pcdoIMessage->put_To( bstrMailAddress);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail put_To failed"
);
break;
}
//
// Set mail subject.
//
hr = m_pcdoIMessage->put_Subject( bstrSubject );
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail put_Subject failed"
);
break;
}
//
// Get text bodypart from the message object.
//
CComPtr<IBodyPart> pMsgBodyPart;
hr = m_pcdoIMessage->get_BodyPart( &pMsgBodyPart );
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail get_TextBodyPart failed"
);
break;
}
//
// Get current char set from localize manager.
//
CComBSTR bstrCharSet;
hr = m_pLocInfo->get_CurrentCharSet( &bstrCharSet );
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail get_CurrentCharSet failed"
);
break;
}
//
// Set char set to text bodypart with current char set.
//
// TMARSH: Hardcode charset to UTF-8.
hr = pMsgBodyPart->put_Charset( CComBSTR(L"utf-8") );
// hr = pMsgBodyPart->put_Charset( bstrCharSet );
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail put_CharSet failed"
);
break;
}
CComBSTR bstrExtendMessage;
bstrExtendMessage.AppendBSTR( bstrMessage );
/* bstrExtendMessage += CComBSTR( ENTER );
bstrExtendMessage += CComBSTR( HTTPHEADER );
bstrExtendMessage += CComBSTR( m_pstrApplianceName );
hr = GetAppliancePort( &pstrPort );
if( SUCCEEDED( hr ) )
{
bstrExtendMessage += CComBSTR( pstrPort );
}
else
{
SATraceString(
"AlertEmail:SendMail GetAppliancePort failed"
);
}
*/
//
// Set mail message.
//
hr = m_pcdoIMessage->put_TextBody( bstrExtendMessage );
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:SendMail put_TextBody failed"
);
break;
}
//
// Send it.
//
hr = m_pcdoIMessage->Send();
}while( FALSE );
if( pstrPort!= NULL )
{
::free( pstrPort );
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::GetFullyQualifiedDomainName
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get local appliance name in DNS format.
//
// Arguments:
// [in,out] pstrComputerName Pointer of computer name string.
//
// Returns:
// TRUE if successful
// FALSE if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
BOOL
CAlertEmailConsumer::GetComputerName(
LPWSTR* pstrComputerName,
COMPUTER_NAME_FORMAT nametype
)
{
BOOL bReturn = FALSE;
DWORD dwSize = 0;
DWORD dwCount = 1;
do
{
if( *pstrComputerName != NULL )
{
::free( *pstrComputerName );
}
dwSize = MAXAPPLIANCEDNSNAME * dwCount;
*pstrComputerName = ( LPWSTR ) ::malloc( sizeof(WCHAR) * dwSize );
if( *pstrComputerName == NULL )
{
SATraceString(
"AlertEmail:GetApplianceName malloc failed"
);
break;
}
//
// Get local computer name.
//
bReturn = ::GetComputerNameEx(
nametype,
*pstrComputerName,
&dwSize
);
dwCount <<= 1;
}
while( !bReturn &&
ERROR_MORE_DATA == ::GetLastError() &&
dwCount < 32
);
return bReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::GetAppliancePort
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get local appliance port.
//
// Arguments:
// [in,out] pstrPort Pointer of server port string.
//
// Returns:
// TRUE if successful
// FALSE if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::GetAppliancePort(
LPWSTR* pstrPort
)
{
HRESULT hr = S_OK;
try
{
do
{
CComPtr <IWbemLocator> pWbemLocator;
CComPtr <IWbemServices> pWbemServices;
CComPtr <IEnumWbemClassObject> pEnumServices;
//
// create the WBEM locator object
//
hr = ::CoCreateInstance (
CLSID_WbemLocator,
0, //aggregation pointer
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(PVOID*) &pWbemLocator
);
if( FAILED(hr) )
{
SATraceString(
"AlertEmail:GetAppliancePort CoCreateInstance failed"
);
break;
}
//
// allocate memory for BSTR
//
CComBSTR bstrDefaultNameSpace (DEFAULT_NAMESPACE);
if (NULL == bstrDefaultNameSpace.m_str)
{
SATraceString("AlertEmail:GetAppliancePort failed to allocate memory for DEFAULT_NAMESPACE" );
hr = E_OUTOFMEMORY;
break;
}
//
// connect to WMI
//
hr = pWbemLocator->ConnectServer (
bstrDefaultNameSpace,
NULL, //user-name
NULL, //password
0, //current-locale
0, //reserved
NULL, //authority
NULL, //context
&pWbemServices
);
if( hr != WBEM_S_NO_ERROR )
{
SATraceString(
"AlertEmail:GetAppliancePort ConnectServer failed"
);
break;
}
//
// Query Web server instance.
//
hr = pWbemServices->ExecQuery(
CComBSTR( QUERY_LANGUAGE ),
CComBSTR( QUERY_STRING ),
0,
NULL,
&pEnumServices
);
if( hr != WBEM_S_NO_ERROR )
{
SATraceString(
"AlertEmail:GetAppliancePort ExecQuery failed"
);
break;
}
CComPtr <IWbemClassObject> pService;
ULONG uReturned;
//
// Now,we only care for the first match.
//
hr = pEnumServices->Next(
WBEM_NO_WAIT,
1,
&pService,
&uReturned
);
if( hr != WBEM_S_NO_ERROR )
{
SATraceString(
"AlertEmail:GetAppliancePort nothing found"
);
break;
}
CComVariant vtServerBindings;
//
// Get the "ServerBindings" property.
//
hr = pService->Get(
CComBSTR( SERVERBINDINGSPROP ),
0,
&vtServerBindings,
0,
0
);
if ( FAILED(hr) || !V_ISARRAY( &vtServerBindings ) )
{
hr = E_FAIL;
SATraceString(
"AlertEmail:GetAppliancePort get serverbindings failed"
);
break;
}
SAFEARRAY* psa;
BSTR HUGEP *pbstr;
//
// The property type is VT_ARRAY | VT_BSTR.
//
psa = V_ARRAY( &vtServerBindings );
if( psa->cDims <= 0 )
{
hr = E_FAIL;
SATraceString(
"AlertEmail:GetAppliancePort array dim error"
);
break;
}
//
// Access array data directly,it's a faster way.
//
hr = ::SafeArrayAccessData( psa, ( void HUGEP** )&pbstr );
if (FAILED(hr))
{
SATraceString(
"AlertEmail:GetAppliancePort SafeArrayAccessData failed"
);
break;
}
//
// Now we can alloc the port string.
//
*pstrPort = ( LPWSTR )malloc( sizeof(WCHAR) * MAX_COMPUTERNAME_LENGTH );
if( *pstrPort == NULL )
{
hr = E_FAIL;
SATraceString(
"AlertEmail:GetAppliancePort malloc failed"
);
break;
}
WCHAR* pszTemp1;
WCHAR* pszTemp2;
pszTemp1 = ::wcschr( pbstr[0], COLON );
pszTemp2 = ::wcsrchr( pbstr[0], COLON );
if( pszTemp2 != NULL && pszTemp1 != NULL )
{
pszTemp2[0] = ENDCODE;
::wcscpy( *pstrPort, pszTemp1 );
}
else
{
SATraceString(
"AlertEmail:GetAppliancePort string formate error"
);
hr = E_FAIL;
}
::SafeArrayUnaccessData( psa );
}
while( false );
}
catch (...)
{
SATraceString(
"AlertEmail:GetAppliancePort unkown exception"
);
hr = E_FAIL;
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::RetrieveRegInfo
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to retrieve alert email settings from registry.
//
// Returns:
// TRUE if successful
// FALSE if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
BOOL
CAlertEmailConsumer::RetrieveRegInfo()
{
BOOL bReturn = TRUE;
LONG lReturn;
DWORD dwDataSize;
//
// Get the email address will be send to.
//
dwDataSize = sizeof(m_pstrMailAddress);
lReturn = ::RegQueryValueEx(
m_hAlertKey,
RECEIVEREMAILADDRESS,
NULL,
NULL,
reinterpret_cast<PBYTE>(m_pstrMailAddress),
&dwDataSize );
if( lReturn != ERROR_SUCCESS)
{
m_pstrMailAddress[0] = L'\0'; // RegQueryValueEx doesn't guarantee
// a desirable value, so clear the string.
SATraceString(
"AlertEmail:RetrieveRegInfo query address failed"
);
bReturn = FALSE;
}
else
{
_ASSERT(dwDataSize <= sizeof(m_pstrMailAddress));
//
// Validate the e-mail address length.
//
LONG lLastCharacter;
if( sizeof( m_pstrMailAddress[0] ) > dwDataSize )
{
lLastCharacter = 0;
}
else
{
lLastCharacter = dwDataSize / sizeof( m_pstrMailAddress[0] ) - 1;
}
if( sizeof(m_pstrMailAddress) == dwDataSize &&
L'\0' != m_pstrMailAddress[lLastCharacter] )
{
SATraceString( "AlertEmail:RetrieveRegInfo address too long" );
bReturn = FALSE;
}
m_pstrMailAddress[lLastCharacter] = L'\0';
}
//
// Get alert enable setting.
//
dwDataSize = sizeof( LONG );
lReturn = ::RegQueryValueEx(
m_hAlertKey,
ENABLEALERTEAMIL,
NULL,
NULL,
reinterpret_cast<PBYTE>(&m_lAlertEmailDisabled),
&dwDataSize
);
if( lReturn != ERROR_SUCCESS)
{
SATraceString(
"AlertEmail:RetrieveRegInfo query enablealertemail failed"
);
bReturn = FALSE;
}
//
// Get alert type setting.
//
dwDataSize = sizeof( LONG );
lReturn = ::RegQueryValueEx(
m_hAlertKey,
SENDEMAILTYPE,
NULL,
NULL,
reinterpret_cast<PBYTE>(&m_lCurAlertType),
&dwDataSize
);
if( lReturn != ERROR_SUCCESS)
{
SATraceString(
"AlertEmail:RetrieveRegInfo query enablealertemail failed"
);
bReturn = FALSE;
}
return bReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::RegThreadProc
//
// Description:
// This is the CAlertEmailConsumer class static method which is used
// as worker thread entry.
//
// Arguments:
// [in] pIn Point to an instance of CAlertEmailConsumer class.
//
// Returns:
// 0 if successful
// -1 if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
DWORD WINAPI
CAlertEmailConsumer::RegThreadProc(
PVOID pIn
)
{
//
// Make transition to the per-instance method.
//
( (CAlertEmailConsumer *) pIn )->RegThread();
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::RegThread
//
// Description:
// This is the CAlertEmailConsumer class public method which is real
// worker thread process.
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
void
CAlertEmailConsumer::RegThread()
{
HANDLE hHandleArray[2];
DWORD dwEventCount;
DWORD dwReturn;
SATraceString(
"AlertEmail:RegThread enter"
);
//
// Handle list used by WaitForMultipleObjects
//
hHandleArray[0] = m_hCloseThreadEvent;
//
// Event for RegNotifyChangeKeyValue.
//
hHandleArray[1] = ::CreateEvent( NULL, FALSE, FALSE, NULL );
if( hHandleArray[1] != NULL )
{
dwEventCount = 2;
//
// Monitor key change action.
//
::RegNotifyChangeKeyValue( m_hAlertKey, //AlertEmail key
FALSE, //No subkey
REG_NOTIFY_CHANGE_LAST_SET, //Value change
hHandleArray[1], //Event handle
TRUE ); //APC
}
else
{
SATraceString(
"AlertEmail:RegThread CreateEvent failed"
);
dwEventCount = 1;
}
while( TRUE )
{
//
// Wait for both close and regchange event.
//
dwReturn = ::WaitForMultipleObjects( dwEventCount,
hHandleArray,
FALSE,
INFINITE );
switch( dwReturn )
{
case WAIT_OBJECT_0:
{
//
// Close thread event set in release method.
//
SATraceString(
"AlertEmail:RegThread get close event"
);
if( hHandleArray[1] != NULL )
{
::CloseHandle( hHandleArray[1] );
}
//
// Clean up.
//
delete this;
return;
} //case WAIT_OBJECT_0:
case WAIT_OBJECT_0 + 1:
{
//
// Registry changed event.
//
SATraceString(
"AlertEmail:RegThread get reg event"
);
BOOL bReturn;
//
// Refresh alert email settings.
//
bReturn = RetrieveRegInfo();
if( bReturn == FALSE )
{
SATraceString(
"AlertEmail:RegThread RetrieveRegInfo failed"
);
}
break;
} //case WAIT_OBJECT_0 + 1:
default:
{
//
// Wait error ocupied.
//
SATraceString(
"AlertEmail:RegThread waitevent error"
);
break;
} //default:
} //switch(dwReturn)
} // While( TRUE )
return;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::InitializeLocalManager
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get object of Local Manager.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT CAlertEmailConsumer::InitializeLocalManager()
{
CLSID clsidLocMgr;
HRESULT hr;
hr = ::CLSIDFromProgID (
LOCALIZATION_MANAGER,
&clsidLocMgr
);
if (SUCCEEDED (hr))
{
//
// create the Localization Manager COM object
//
hr = ::CoCreateInstance (
clsidLocMgr,
NULL,
CLSCTX_INPROC_SERVER,
__uuidof (ISALocInfo),
(PVOID*) &m_pLocInfo
);
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::InitializeElementManager
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get object of elements enum interface from Element manager.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CAlertEmailConsumer::InitializeElementManager()
{
HRESULT hr = WBEM_S_NO_ERROR;
IDispatch *pDispatch = NULL;
IWebElementRetriever *pWebElementRetriever = NULL;
do
{
//
// Get Element Manager's CLSID.
//
CLSID clsid;
hr = ::CLSIDFromProgID (
ELEMENT_RETRIEVER,
&clsid
);
if (FAILED (hr))
{
break;
}
//
// create the WebElementRetriever now
//
hr = ::CoCreateInstance (
clsid,
NULL,
CLSCTX_LOCAL_SERVER,
IID_IWebElementRetriever,
(PVOID*) &pWebElementRetriever
);
if (FAILED (hr))
{
break;
}
//
// allocate memory for BSTR(alert definitions)
//
CComBSTR bstrAlertDefinitions (ALERTDEFINITIONS);
if (NULL == bstrAlertDefinitions.m_str)
{
hr = E_OUTOFMEMORY;
break;
}
//
// Initial now
//
hr = pWebElementRetriever->GetElements (
WEB_ELEMENT_TYPE_DEFINITION,
bstrAlertDefinitions,
&pDispatch
);
if (FAILED (hr))
{
break;
}
//
// get the enum variant
//
hr = pDispatch->QueryInterface (
IID_IWebElementEnum,
reinterpret_cast <PVOID*> (&m_pElementEnum)
);
}while( FALSE );
if( pDispatch != NULL )
{
pDispatch->Release();
}
if( pWebElementRetriever != NULL )
{
pWebElementRetriever->Release();
}
return hr;
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlertEmailConsumer::InitializeCDOMessage
//
// Description:
// This is the CAlertEmailConsumer class private method which is used
// to get object of CDO::IMessage and set the configuration as using
// local SMTP server.
//
// Returns:
// WBEM_S_NO_ERROR if successful
// WBEM_E_FAILED if not
//
// History:
// Xing Jin (i-xingj) 23-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT CAlertEmailConsumer::InitializeCDOMessage()
{
HRESULT hr = S_OK;
CComPtr <IConfiguration> pConfig;
do
{
//
// Get an object of IMessage
//
hr = CoCreateInstance(
CLSID_Message,
NULL,
CLSCTX_INPROC_SERVER,
IID_IMessage,
(PVOID*) &m_pcdoIMessage
);
if (FAILED (hr))
{
SATraceString(
"AlertEmail: InitializeCDOMessage CoCreateInstance failed"
);
break;
}
//
// Get the configuration in this message object.
//
hr = m_pcdoIMessage->get_Configuration(&pConfig);
if (FAILED (hr))
{
SATraceString(
"AlertEmail: InitializeCDOMessage get_Configuration failed"
);
break;
}
//
// Set the configuration as default setting of local
// SMTP server.
//
hr = pConfig->Load( cdoIIS, NULL );
}
while( FALSE );
return hr;
}