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

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 1999--2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CAlertEmailConsumer.cpp
  7. //
  8. // Description:
  9. // Implementation of CAlertEmailConsumer class methods
  10. //
  11. // [Header File:]
  12. // CAlertEmailConsumer.h
  13. //
  14. // History:
  15. // Xing Jin (i-xingj) 23-Dec-2000
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "stdafx.h"
  19. #include <cdosys_i.c>
  20. #include <wbemcli.h>
  21. #include <wbemprov.h>
  22. #include <wbemidl.h>
  23. #include <appsrvcs.h>
  24. #include <appmgrobjs.h>
  25. #include <iads.h>
  26. #include <Adshlp.h>
  27. #include "alertemailmsg.h"
  28. #include "CAlertEmailConsumer.h"
  29. //
  30. // Name of WBEM class
  31. //
  32. const WCHAR PROPERTY_CLASS_NAME [] = L"__CLASS";
  33. //
  34. // Key name of alert email's settings.
  35. //
  36. const WCHAR SA_ALERTEMAIL_KEYPATH [] =
  37. L"SOFTWARE\\Microsoft\\ServerAppliance\\AlertEmail";
  38. //
  39. // Delimiter
  40. //
  41. const WCHAR DELIMITER[] = L"\\";
  42. const WCHAR ENTER[] = L"\n";
  43. const WCHAR COLON = L':';
  44. const WCHAR ENDCODE = L'\0';
  45. //
  46. // HTTP header
  47. //
  48. const WCHAR HTTPHEADER[] = L"http://";
  49. //
  50. // SMTP Meta path
  51. //
  52. const WCHAR SMTP_META_PATH[] = L"IIS://LOCALHOST/SMTPSVC/1";
  53. //
  54. // Value name of alert email's settings.
  55. //
  56. const WCHAR ENABLEALERTEAMIL[] = L"EnableAlertEmail";
  57. const WCHAR SENDEMAILTYPE[] = L"SendEmailType";
  58. const WCHAR RECEIVEREMAILADDRESS[] = L"ReceiverEmailAddress";
  59. //
  60. // The setting value of alert->email disabled.
  61. //
  62. const DWORD ALERTEMAILDISABLED = 0;
  63. //
  64. // Name of caption ID in alertdefinitions.
  65. //
  66. const WCHAR ALERTDEFINITIONCAPTIONID [] = L"CaptionRID";
  67. //
  68. // Name of description ID in alertdefinitions.
  69. //
  70. const WCHAR ALERTDEFINITIONDESCRIPTIONRID [] = L"DescriptionRID";
  71. //
  72. // Name of resource file in alertdefintions.
  73. //
  74. const WCHAR ALERTDEFINITIONSOURCE [] = L"Source";
  75. //
  76. // Name of alert email resource
  77. //
  78. const WCHAR ALERTEMAILRESOURCE[] = L"AlertEmailMsg.dll";
  79. //
  80. // Max value of Appliance Name
  81. //
  82. const DWORD MAXAPPLIANCEDNSNAME = 1024;
  83. //
  84. // WBEM namespace to connection to
  85. //
  86. const WCHAR DEFAULT_NAMESPACE[] = L"root\\MicrosoftIISv1";
  87. //
  88. // Query Language to use for WBEM
  89. //
  90. const WCHAR QUERY_LANGUAGE [] = L"WQL";
  91. //
  92. // WBEM query which specifies the IIS server settings we're interest in.
  93. //
  94. const WCHAR QUERY_STRING [] =
  95. L"select * from IIS_WebServerSetting where servercomment=\"Administration\"";
  96. const WCHAR SERVERBINDINGSPROP[] = L"ServerBindings";
  97. //
  98. // PROGID of the Element Manager
  99. //
  100. const WCHAR ELEMENT_RETRIEVER [] = L"Elementmgr.ElementRetriever";
  101. //
  102. // PROGID of the Localization Manager
  103. //
  104. const WCHAR LOCALIZATION_MANAGER [] = L"ServerAppliance.LocalizationManager";
  105. //
  106. // Type name of alert resource information.
  107. //
  108. const WCHAR ALERTDEFINITIONS [] = L"AlertDefinitions";
  109. //////////////////////////////////////////////////////////////////////////////
  110. //
  111. // CAlertEmailConsumer::CAlertEmailConsumer
  112. //
  113. // Description:
  114. // Class constructor.
  115. //
  116. // History:
  117. // Xing Jin (i-xingj) 23-Dec-2000
  118. //
  119. //////////////////////////////////////////////////////////////////////////////
  120. CAlertEmailConsumer::CAlertEmailConsumer()
  121. {
  122. m_cRef = 0L;
  123. m_lCurAlertType = 0;
  124. m_lAlertEmailDisabled = ALERTEMAILDISABLED;
  125. m_pLocInfo = NULL;
  126. m_pcdoIMessage = NULL;
  127. m_pElementEnum = NULL;
  128. m_hAlertKey = NULL;
  129. m_hThread = NULL;
  130. m_hCloseThreadEvent = NULL;
  131. m_pstrFullyQualifiedDomainName = NULL;
  132. m_pstrNetBIOSName = NULL;
  133. }
  134. //////////////////////////////////////////////////////////////////////////////
  135. //
  136. // CAlertEmailConsumer::~CAlertEmailConsumer
  137. //
  138. // Description:
  139. // Class deconstructor.
  140. //
  141. // History:
  142. // Xing Jin (i-xingj) 23-Dec-2000
  143. //
  144. //////////////////////////////////////////////////////////////////////////////
  145. CAlertEmailConsumer::~CAlertEmailConsumer()
  146. {
  147. if( m_hAlertKey != NULL )
  148. {
  149. ::RegCloseKey( m_hAlertKey );
  150. }
  151. if( m_pLocInfo != NULL )
  152. {
  153. m_pLocInfo->Release();
  154. }
  155. if( m_pElementEnum != NULL )
  156. {
  157. m_pElementEnum->Release();
  158. }
  159. if( m_pcdoIMessage != NULL )
  160. {
  161. m_pcdoIMessage->Release();
  162. }
  163. if( m_pstrFullyQualifiedDomainName != NULL )
  164. {
  165. ::free( m_pstrFullyQualifiedDomainName );
  166. }
  167. if( m_pstrNetBIOSName != NULL )
  168. {
  169. ::free( m_pstrNetBIOSName );
  170. }
  171. if( m_hThread != NULL )
  172. {
  173. ::CloseHandle( m_hThread );
  174. }
  175. if( m_hCloseThreadEvent != NULL )
  176. {
  177. ::CloseHandle( m_hCloseThreadEvent );
  178. }
  179. }
  180. //////////////////////////////////////////////////////////////////////////////
  181. //
  182. // CAlertEmailConsumer::QueryInterface
  183. //
  184. // Description:
  185. // An method implement of IUnkown interface.
  186. //
  187. // Arguments:
  188. // [in] riid Identifier of the requested interface
  189. // [out] ppv Address of output variable that receives the
  190. // interface pointer requested in iid
  191. //
  192. // Returns:
  193. // NOERROR if the interface is supported
  194. // E_NOINTERFACE if not
  195. //
  196. // History:
  197. // Xing Jin (i-xingj) 23-Dec-2000
  198. //
  199. //////////////////////////////////////////////////////////////////////////////
  200. STDMETHODIMP
  201. CAlertEmailConsumer::QueryInterface(
  202. IN REFIID riid,
  203. OUT LPVOID FAR *ppv
  204. )
  205. {
  206. *ppv=NULL;
  207. if (riid == IID_IUnknown || riid == IID_IWbemUnboundObjectSink)
  208. {
  209. *ppv = (IWbemUnboundObjectSink *) this;
  210. AddRef();
  211. return NOERROR;
  212. }
  213. return E_NOINTERFACE;
  214. }
  215. //////////////////////////////////////////////////////////////////////////////
  216. //
  217. // CAlertEmailConsumer::AddRef
  218. //
  219. // Description:
  220. // increments the reference count for an interface on an object
  221. //
  222. // Returns:
  223. // The new reference count.
  224. //
  225. // History:
  226. // Xing Jin (i-xingj) 23-Dec-2000
  227. //
  228. //////////////////////////////////////////////////////////////////////////////
  229. STDMETHODIMP_(ULONG)
  230. CAlertEmailConsumer::AddRef(void)
  231. {
  232. InterlockedIncrement( &m_cRef );
  233. return m_cRef;
  234. }
  235. //////////////////////////////////////////////////////////////////////////////
  236. //
  237. // CAlertEmailConsumer::Release
  238. //
  239. // Description:
  240. // decrements the reference count for an interface on an object.
  241. //
  242. // Returns:
  243. // The new reference count.
  244. //
  245. // History:
  246. // Xing Jin (i-xingj) 23-Dec-2000
  247. //
  248. //////////////////////////////////////////////////////////////////////////////
  249. STDMETHODIMP_(ULONG)
  250. CAlertEmailConsumer::Release(void)
  251. {
  252. InterlockedDecrement( &m_cRef );
  253. if (0 != m_cRef)
  254. {
  255. return m_cRef;
  256. }
  257. // delete this;
  258. BOOL bReturn;
  259. bReturn = ::SetEvent( m_hCloseThreadEvent );
  260. if( !bReturn )
  261. {
  262. SATraceString(
  263. "AlertEmail:Release setevent error!!!"
  264. );
  265. }
  266. return 0;
  267. }
  268. //////////////////////////////////////////////////////////////////////////////
  269. //
  270. // CAlertEmailConsumer::IndicateToConsumer
  271. //
  272. // Description:
  273. // An method implement of IWbemUnboundObjectSink interface.
  274. //
  275. // Arguments:
  276. // [in] pLogicalConsumer Pointer to the logical consumer object for
  277. // which this set of objects is delivered.
  278. // [in] lObjectCount Number of objects delivered in the array that
  279. // follows.
  280. // [in] ppObjArray Pointer to an array of IWbemClassObject
  281. // instances which represent the events delivered.
  282. //
  283. // Returns:
  284. // WBEM_S_NO_ERROR if successful
  285. // WBEM_E_FAILED if not
  286. //
  287. // History:
  288. // Xing Jin (i-xingj) 23-Dec-2000
  289. //
  290. //////////////////////////////////////////////////////////////////////////////
  291. STDMETHODIMP
  292. CAlertEmailConsumer::IndicateToConsumer(
  293. IN IWbemClassObject *pLogicalConsumer,
  294. IN long lObjectCount,
  295. IN IWbemClassObject **ppObjArray
  296. )
  297. {
  298. HRESULT hr = WBEM_S_NO_ERROR;
  299. if( m_lAlertEmailDisabled == ALERTEMAILDISABLED )
  300. {
  301. return WBEM_S_NO_ERROR;
  302. }
  303. try
  304. {
  305. for (LONG lCount = 0; lCount < lObjectCount; lCount++)
  306. {
  307. //
  308. // get the event type
  309. //
  310. CComVariant vtName;
  311. hr = ppObjArray[lCount]->Get (
  312. PROPERTY_CLASS_NAME,
  313. 0, //reserved
  314. &vtName,
  315. NULL, // type
  316. NULL // flavor
  317. );
  318. if (FAILED (hr))
  319. {
  320. SATraceString(
  321. "AlertEmail: IndicateToConsumer Get Class name failed"
  322. );
  323. break;
  324. }
  325. //
  326. // check if we support the event received
  327. //
  328. if (0 == _wcsicmp (CLASS_WBEM_RAISE_ALERT, V_BSTR (&vtName)))
  329. {
  330. //
  331. // handle a raise alert event
  332. //
  333. hr = RaiseAlert ( ppObjArray[lCount] );
  334. if ( FAILED (hr) )
  335. {
  336. SATraceString(
  337. "AlertEmail: IndicateToConsumer RaiseAlert failed"
  338. );
  339. break;
  340. }
  341. }
  342. else if (0 == _wcsicmp (CLASS_WBEM_CLEAR_ALERT, V_BSTR (&vtName)))
  343. {
  344. //
  345. // handle a clear alert
  346. //
  347. hr = ClearAlert ( ppObjArray[lCount] );
  348. if ( FAILED (hr) )
  349. {
  350. SATraceString(
  351. "AlertEmail: IndicateToConsumer ClearAlert failed"
  352. );
  353. break;
  354. }
  355. }
  356. } // for loop
  357. }
  358. catch (...)
  359. {
  360. hr = WBEM_E_FAILED;
  361. }
  362. return hr;
  363. }
  364. //////////////////////////////////////////////////////////////////////////////
  365. //
  366. // CAlertEmailConsumer::ClearAlert
  367. //
  368. // Description:
  369. // This is the CAlertEmailConsumer class private method
  370. // which is NOT used now.
  371. //
  372. // Arguments:
  373. // [in] pObject Pointer to an IWbemClassObject instances which
  374. // represent ClearAlert events delivered.
  375. //
  376. // Returns:
  377. // WBEM_S_NO_ERROR if successful
  378. // WBEM_E_FAILED if not
  379. //
  380. // History:
  381. // Xing Jin (i-xingj) 23-Dec-2000
  382. //
  383. //////////////////////////////////////////////////////////////////////////////
  384. HRESULT
  385. CAlertEmailConsumer::ClearAlert(
  386. IN IWbemClassObject *pObject
  387. )
  388. {
  389. HRESULT hr = WBEM_S_NO_ERROR;
  390. return hr;
  391. }
  392. //////////////////////////////////////////////////////////////////////////////
  393. //
  394. // CAlertEmailConsumer::RaiseAlert
  395. //
  396. // Description:
  397. // This is the CAlertEmailConsumer class private method
  398. // which is used to send email with the alert information
  399. // by local SMTP server.
  400. //
  401. // Arguments:
  402. // [in] pObject Pointer to an IWbemClassObject instances which
  403. // represent RaiseAlert events delivered.
  404. //
  405. // Returns:
  406. // WBEM_S_NO_ERROR if successful
  407. // WBEM_E_FAILED if not
  408. //
  409. // History:
  410. // Xing Jin (i-xingj) 23-Dec-2000
  411. //
  412. //////////////////////////////////////////////////////////////////////////////
  413. HRESULT
  414. CAlertEmailConsumer::RaiseAlert(
  415. IN IWbemClassObject *pObject
  416. )
  417. {
  418. LONG lAlertType;
  419. CComVariant vtProperty;
  420. HRESULT hr = WBEM_S_NO_ERROR;
  421. //
  422. // Get alert type.
  423. //
  424. hr = pObject->Get (
  425. PROPERTY_ALERT_TYPE,
  426. 0, //reserved
  427. &vtProperty,
  428. NULL, // type
  429. NULL // flavor
  430. );
  431. if( FAILED (hr) )
  432. {
  433. SATraceString(
  434. "AlertEmail:RaiseAlert get alert type failed"
  435. );
  436. return hr;
  437. }
  438. //
  439. // Map to bitmap type definition
  440. //
  441. lAlertType = 1 << V_I4( &vtProperty );
  442. if( lAlertType & m_lCurAlertType )
  443. {
  444. //
  445. // It's the type user set to send mail.
  446. //
  447. do
  448. {
  449. //
  450. // Get name of alert resource dll.
  451. //
  452. CComVariant vtAlertLog;
  453. hr = pObject->Get (
  454. PROPERTY_ALERT_LOG,
  455. 0, //reserved
  456. &vtAlertLog,
  457. NULL, // type
  458. NULL // flavor
  459. );
  460. if( FAILED (hr) )
  461. {
  462. SATraceString(
  463. "AlertEmail:RaiseAlert get alert source failed"
  464. );
  465. break;
  466. }
  467. //
  468. // Get alert ID.
  469. //
  470. CComVariant vtAlertID;
  471. hr = pObject->Get (
  472. PROPERTY_ALERT_ID,
  473. 0, //reserved
  474. &vtAlertID,
  475. NULL, // type
  476. NULL // flavor
  477. );
  478. if( FAILED (hr) )
  479. {
  480. SATraceString(
  481. "AlertEmail:RaiseAlert get alert ID failed"
  482. );
  483. break;
  484. }
  485. //
  486. // Get replace strings.
  487. //
  488. CComVariant vtReplaceStr;
  489. hr = pObject->Get (
  490. PROPERTY_ALERT_STRINGS,
  491. 0, //reserved
  492. &vtReplaceStr,
  493. NULL, // type
  494. NULL // flavor
  495. );
  496. if( FAILED (hr) )
  497. {
  498. SATraceString(
  499. "AlertEmail:RaiseAlert get alert replace string failed"
  500. );
  501. break;
  502. }
  503. //
  504. // We got all neccessary info,it's time to send email.
  505. //
  506. hr = SendMailFromResource(
  507. V_BSTR( &vtAlertLog ),
  508. V_I4( &vtAlertID ),
  509. &vtReplaceStr
  510. );
  511. if( FAILED (hr) )
  512. {
  513. SATraceString(
  514. "AlertEmail:RaiseAlert call SendMailFromResource failed"
  515. );
  516. break;
  517. }
  518. } //do
  519. while ( FALSE );
  520. } // if( lAlertType & m_lCurAlertType )
  521. return hr;
  522. }
  523. //////////////////////////////////////////////////////////////////////////////
  524. //
  525. // CAlertEmailConsumer::SendMailFromResource
  526. //
  527. // Description:
  528. // This is the CAlertEmailConsumer class private method which is used
  529. // to get useful message about the alert from Local Manager and send
  530. // mail with the messages.
  531. //
  532. // Arguments:
  533. // [in] lpszSource Point to the name of alert resource.
  534. // [in] lSourceID Alert ID.
  535. // [in] pvtReplaceStr Point to array of replace strings.
  536. //
  537. // Returns:
  538. // WBEM_S_NO_ERROR if successful
  539. // WBEM_E_FAILED if not
  540. //
  541. // History:
  542. // Xing Jin (i-xingj) 23-Dec-2000
  543. //
  544. //////////////////////////////////////////////////////////////////////////////
  545. HRESULT
  546. CAlertEmailConsumer::SendMailFromResource(
  547. LPWSTR lpszSource,
  548. LONG lSourceID,
  549. VARIANT* pvtReplaceStr
  550. )
  551. {
  552. HRESULT hr = WBEM_S_NO_ERROR;
  553. WCHAR wstrAlertItem[MAX_PATH];
  554. IWebElement* pWebElement;
  555. IDispatch* pDispatch;
  556. //
  557. // Format the alert item name:
  558. // Name = AlertDefinitions<AlertLog><AlertID>
  559. //
  560. ::wsprintf( wstrAlertItem, L"AlertDefinitions%s%lX", lpszSource,lSourceID );
  561. //int cchWritten = _snwprintf( wstrAlertItem, MAX_PATH, L"AlertDefinitions%s%lX",
  562. // lpszSource, lSourceID );
  563. //if ( cchWritten >= MAX_PATH || cchWritten < 0 )
  564. //{
  565. // return E_INVALIDARG;
  566. //}
  567. do
  568. {
  569. //
  570. // Get the element of alert definition from element manager.
  571. //
  572. hr = m_pElementEnum->Item(
  573. &CComVariant( wstrAlertItem ),
  574. &pDispatch
  575. );
  576. if( FAILED(hr) )
  577. {
  578. SATraceString(
  579. "AlertEmail:SendMailFromResource find alert item failed"
  580. );
  581. break;
  582. }
  583. hr = pDispatch->QueryInterface(
  584. __uuidof (IWebElement),
  585. reinterpret_cast <PVOID*> (&pWebElement)
  586. );
  587. if( FAILED(hr) )
  588. {
  589. SATraceString(
  590. "AlertEmail:SendMailFromResource queryinterface failed"
  591. );
  592. break;
  593. }
  594. //
  595. // allocate BSTR for alertdefintion source
  596. //
  597. CComBSTR bstrAlertDefinitionSourceName (ALERTDEFINITIONSOURCE);
  598. if (NULL == bstrAlertDefinitionSourceName.m_str)
  599. {
  600. SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINTIONSOURCE)");
  601. hr = E_OUTOFMEMORY;
  602. break;
  603. }
  604. //
  605. //Get name of alert's resource dll.
  606. // AlertLog != AlertSource now! -- 2001/02/07 i-xingj
  607. //
  608. CComVariant vtAlertSource;
  609. hr = pWebElement->GetProperty (
  610. bstrAlertDefinitionSourceName,
  611. &vtAlertSource
  612. );
  613. if( FAILED(hr) )
  614. {
  615. SATraceString(
  616. "AlertEmail:SendMailFromResource get Alert source failed"
  617. );
  618. break;
  619. }
  620. //
  621. // allocate BSTR for DesinitionCaptionID string
  622. //
  623. CComBSTR bstrAlertDefinitionCaptionIDName (ALERTDEFINITIONCAPTIONID);
  624. if (NULL == bstrAlertDefinitionCaptionIDName.m_str)
  625. {
  626. SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINTIONCAPTIONID)");
  627. hr = E_OUTOFMEMORY;
  628. break;
  629. }
  630. //
  631. // Get caption ID string
  632. //
  633. CComVariant vtCaptionID;
  634. hr = pWebElement->GetProperty (
  635. bstrAlertDefinitionCaptionIDName,
  636. &vtCaptionID
  637. );
  638. if( FAILED(hr) )
  639. {
  640. SATraceString(
  641. "AlertEmail:SendMailFromResource find alert captionID failed"
  642. );
  643. break;
  644. }
  645. //
  646. // allocate BSTR for AlertDescription RID
  647. //
  648. CComBSTR bstrAlertDefinitionDescriptionRIDName (ALERTDEFINITIONDESCRIPTIONRID);
  649. if (NULL == bstrAlertDefinitionDescriptionRIDName.m_str)
  650. {
  651. SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTDEFINITIONDESCRIPTIONRID)");
  652. hr = E_OUTOFMEMORY;
  653. break;
  654. }
  655. //
  656. // Get description ID string
  657. //
  658. CComVariant vtDescriptionID;
  659. hr = pWebElement->GetProperty (
  660. bstrAlertDefinitionDescriptionRIDName,
  661. &vtDescriptionID
  662. );
  663. if( FAILED(hr) )
  664. {
  665. SATraceString(
  666. "AlertEmail:SendMailFromResource get alert descriptionID failed"
  667. );
  668. break;
  669. }
  670. LONG lAlertCaptionID;
  671. LONG lAlertDescriptionID;
  672. //
  673. // Change type from string to long.
  674. //
  675. if ( EOF == ::swscanf( V_BSTR( &vtCaptionID ), L"%X", &lAlertCaptionID ))
  676. {
  677. SATraceString( "AlertEmail:SendMailFromResource get caption invalid" );
  678. break;
  679. }
  680. if ( EOF == ::swscanf( V_BSTR( &vtDescriptionID ), L"%X", &lAlertDescriptionID ))
  681. {
  682. SATraceString( "AlertEmail:SendMailFromResource get description invalid" );
  683. break;
  684. }
  685. //
  686. // Get caption string from resource as email's subject.
  687. //
  688. CComBSTR pszSubject;
  689. hr = m_pLocInfo->GetString(
  690. V_BSTR( &vtAlertSource ),
  691. lAlertCaptionID,
  692. pvtReplaceStr,
  693. &pszSubject
  694. );
  695. if( FAILED(hr) )
  696. {
  697. SATraceString(
  698. "AlertEmail:SendMailFromResource get subjuct failed"
  699. );
  700. break;
  701. }
  702. //
  703. // Get description string from resource as email's message.
  704. //
  705. CComBSTR pszMessage;
  706. hr = m_pLocInfo->GetString(
  707. V_BSTR( &vtAlertSource ),
  708. lAlertDescriptionID,
  709. pvtReplaceStr,
  710. &pszMessage
  711. );
  712. if( FAILED(hr) )
  713. {
  714. SATraceString(
  715. "AlertEmail:SendMailFromResource get message failed"
  716. );
  717. break;
  718. }
  719. //
  720. // allocate BSTR for email source
  721. //
  722. CComBSTR bstrAlertEmailResourceName (ALERTEMAILRESOURCE);
  723. if (NULL == bstrAlertEmailResourceName.m_str)
  724. {
  725. SATraceString ("AlertEmail::SendMailFromResouce failed on SysAllocString (ALERTEMAILRESOURCE)");
  726. hr = E_OUTOFMEMORY;
  727. break;
  728. }
  729. //
  730. // Get alert email defined message.
  731. //
  732. CComBSTR pszConstantMessage;
  733. hr = m_pLocInfo->GetString(
  734. bstrAlertEmailResourceName,
  735. SA_ALERTEMAIL_SETTINGS_EMAIL_CONTENT,
  736. NULL,
  737. &pszConstantMessage
  738. );
  739. if( FAILED(hr) )
  740. {
  741. SATraceString(
  742. "AlertEmail:SendMailFromResource get constantMsg failed"
  743. );
  744. break;
  745. }
  746. pszMessage += CComBSTR( ENTER );
  747. pszMessage += CComBSTR( ENTER );
  748. pszMessage += pszConstantMessage;
  749. //
  750. // Send mail use local SMTP server.
  751. //
  752. hr = SendMail( pszSubject, pszMessage );
  753. } //do
  754. while( FALSE );
  755. return hr;
  756. }
  757. //////////////////////////////////////////////////////////////////////////////
  758. //
  759. // CAlertEmailConsumer::Initialize
  760. //
  761. // Description:
  762. // This is the CAlertEmailConsumer class public method call by
  763. // CAlertEmailConsumerProvider to initialize useful parameters.
  764. //
  765. // Returns:
  766. // S_OK if successful
  767. // E_FAIL if not
  768. //
  769. // History:
  770. // Xing Jin (i-xingj) 23-Dec-2000
  771. //
  772. //////////////////////////////////////////////////////////////////////////////
  773. HRESULT
  774. CAlertEmailConsumer::Initialize()
  775. {
  776. ULONG ulReturn;
  777. HRESULT hr = S_OK;
  778. DWORD dwThreadID;
  779. //
  780. // Initialize Element Manager.
  781. //
  782. hr = InitializeElementManager();
  783. if (FAILED (hr))
  784. {
  785. SATraceString(
  786. "AlertEmailProvider:Initialize InitializeElementManager failed"
  787. );
  788. return WBEM_E_FAILED;
  789. }
  790. //
  791. // Initialize Local Manager
  792. //
  793. hr = InitializeLocalManager();
  794. if (FAILED (hr))
  795. {
  796. SATraceString(
  797. "AlertEmailProvider:Initialize InitializeLocalManager failed"
  798. );
  799. return WBEM_E_FAILED;
  800. }
  801. //
  802. // Initialize a CDO IMessage interface.
  803. //
  804. hr = InitializeCDOMessage();
  805. if (FAILED (hr))
  806. {
  807. SATraceString(
  808. "AlertEmailProvider:Initialize InitializeCDOMessage failed"
  809. );
  810. return WBEM_E_FAILED;
  811. }
  812. //
  813. // Open registry key of alertemail settings.
  814. //
  815. ulReturn = ::RegOpenKey(
  816. HKEY_LOCAL_MACHINE,
  817. SA_ALERTEMAIL_KEYPATH,
  818. &m_hAlertKey
  819. );
  820. if( ulReturn != ERROR_SUCCESS )
  821. {
  822. SATraceString(
  823. "AlertEmail:Initialize OpenKey failed"
  824. );
  825. return E_FAIL;
  826. }
  827. //
  828. // Get alert email settings from registry.
  829. //
  830. if( FALSE == RetrieveRegInfo() )
  831. {
  832. SATraceString(
  833. "AlertEmail:Initialize RetrieveRegInfo failed"
  834. );
  835. return E_FAIL;
  836. }
  837. //
  838. // Get server name fully qualified domain anem.
  839. //
  840. if( FALSE == GetComputerName( &m_pstrFullyQualifiedDomainName, ComputerNameDnsFullyQualified ) )
  841. {
  842. SATraceString(
  843. "AlertEmail:Initialize GetComputerName ComputerNameDnsFullyQualified failed"
  844. );
  845. return E_FAIL;
  846. }
  847. //
  848. // Get server name.
  849. //
  850. if( FALSE == GetComputerName( &m_pstrNetBIOSName, ComputerNameNetBIOS ) )
  851. {
  852. SATraceString(
  853. "AlertEmail:Initialize GetComputerName ComputerNameNetBIOS failed"
  854. );
  855. return E_FAIL;
  856. }
  857. //
  858. // Event for notify thread exit.
  859. //
  860. m_hCloseThreadEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  861. if( m_hCloseThreadEvent == NULL )
  862. {
  863. SATraceString(
  864. "AlertEmail:Initialize CreateEvent failed"
  865. );
  866. return E_FAIL;
  867. }
  868. //
  869. // Thread used to monitor registy change.
  870. //
  871. m_hThread = ::CreateThread( 0,
  872. 0,
  873. CAlertEmailConsumer::RegThreadProc,
  874. this,
  875. 0,
  876. &dwThreadID );
  877. if( m_hThread == NULL )
  878. {
  879. SATraceString(
  880. "AlertEmail:Initialize CreateThread failed"
  881. );
  882. return E_FAIL;
  883. }
  884. return hr;
  885. }
  886. //////////////////////////////////////////////////////////////////////////////
  887. //
  888. // CAlertEmailConsumer::GetSMTPFromDomainName
  889. //
  890. // Description:
  891. // Get the value of "Full Qualified Domain Name" entry in SMTP Delivery tab in MMC.
  892. //
  893. // Arguments:
  894. // [out] bstrDomainName returns domain name that is found in Metabase.
  895. //
  896. // Returns:
  897. // hr
  898. //
  899. //
  900. //////////////////////////////////////////////////////////////////////////////
  901. HRESULT CAlertEmailConsumer::GetSMTPFromDomainName( BSTR* bstrDomainName )
  902. {
  903. HRESULT hr = S_OK;
  904. CComPtr<IADs> pADs;
  905. //
  906. // Initialize for return
  907. //
  908. *bstrDomainName = NULL;
  909. CComBSTR bstrADSPath( SMTP_META_PATH );
  910. if (NULL == bstrADSPath.m_str)
  911. {
  912. SATraceString ("CAlertEmailConsumer::GetSMTPFromDomainName failed to allocate memory for bstrADsPath");
  913. return (E_OUTOFMEMORY);
  914. }
  915. hr = ADsGetObject( bstrADSPath, IID_IADs, (void**) &pADs );
  916. if ( SUCCEEDED(hr) )
  917. {
  918. CComVariant varValue;
  919. CComBSTR bstrFullyQualifiedDomainName (L"FullyQualifiedDomainName" );
  920. if (NULL == bstrFullyQualifiedDomainName.m_str)
  921. {
  922. SATraceString ("CAlertEmailConsumer::GetSMTPFromDomainName failed to allocate memory for bstrFullyQualifiedDomainName");
  923. hr = E_OUTOFMEMORY;
  924. }
  925. else
  926. {
  927. // Getting the FullyQualifiedDomainName property
  928. hr = pADs->Get(bstrFullyQualifiedDomainName, &varValue );
  929. if ( SUCCEEDED(hr) )
  930. {
  931. *bstrDomainName = SysAllocString( V_BSTR( &varValue ) );
  932. }
  933. }
  934. }
  935. return hr;
  936. }
  937. //////////////////////////////////////////////////////////////////////////////
  938. //
  939. // CAlertEmailConsumer::SendMail
  940. //
  941. // Description:
  942. // This is the CAlertEmailConsumer class private method which is used
  943. // to send mail through local SMTP server.
  944. //
  945. // Arguments:
  946. // [in] bstrSubject Subject string.
  947. // [in] bstrMessage Message string.
  948. //
  949. // Returns:
  950. // WBEM_S_NO_ERROR if successful
  951. // WBEM_E_FAILED if not
  952. //
  953. // History:
  954. // Xing Jin (i-xingj) 23-Dec-2000
  955. //
  956. //////////////////////////////////////////////////////////////////////////////
  957. HRESULT
  958. CAlertEmailConsumer::SendMail(
  959. BSTR bstrSubject,
  960. BSTR bstrMessage
  961. )
  962. {
  963. HRESULT hr = WBEM_S_NO_ERROR;
  964. WCHAR* pstrPort = NULL;
  965. do
  966. {
  967. //
  968. // The algorithm is
  969. // Look at the value of "Full Qualified Domain Name" entry in SMTP Delivery tab in MMC.
  970. // 1) If the value is empty then the e-mail From Address is same as fully qualified domain name
  971. // 2) IF there is value and that value is different from Full Qualified Computer Name then use
  972. // 3) the following as From address.
  973. // 4) Use the From Address as appliance_name@"Full Qualified Domain Name"
  974. //
  975. //
  976. //
  977. // allocate memory for BSTR
  978. //
  979. CComBSTR bstrFullyQualifiedDomainName( m_pstrFullyQualifiedDomainName );
  980. if (NULL == bstrFullyQualifiedDomainName.m_str)
  981. {
  982. SATraceString("AlertEmail:SendMail failed to allocate memory for bstrFullyQualifiedDomainName" );
  983. hr = E_OUTOFMEMORY;
  984. break;
  985. }
  986. CComBSTR bstrFromAddress( m_pstrNetBIOSName );
  987. if (NULL == bstrFromAddress.m_str)
  988. {
  989. SATraceString("AlertEmail:SendMail failed to allocate memory for bstrFromAddress" );
  990. hr = E_OUTOFMEMORY;
  991. break;
  992. }
  993. BSTR bstrDomainName = NULL;
  994. //
  995. // Read SMTP "Full Qualified Domain Name" from Metabase
  996. hr = GetSMTPFromDomainName( &bstrDomainName );
  997. if ( FAILED(hr) )
  998. {
  999. SATraceString(
  1000. "AlertEmail:SendMail GetSMTPFromDomainName failed"
  1001. );
  1002. return E_FAIL;
  1003. }
  1004. if ( bstrDomainName )
  1005. {
  1006. if ( _wcsicmp( bstrFullyQualifiedDomainName, bstrDomainName ) != 0 )
  1007. {
  1008. bstrFromAddress += CComBSTR( L"@" );
  1009. bstrFromAddress += bstrDomainName ;
  1010. }
  1011. }
  1012. //
  1013. // Set bstrFromAddress that is formed using the above algorithm
  1014. // as mail sender.
  1015. //
  1016. hr = m_pcdoIMessage->put_From( bstrFromAddress );
  1017. //
  1018. // Free BSTR
  1019. //
  1020. if ( bstrDomainName )
  1021. {
  1022. SysFreeString( bstrDomainName );
  1023. }
  1024. CComBSTR bstrMailAddress (m_pstrMailAddress );
  1025. if (NULL == bstrMailAddress.m_str)
  1026. {
  1027. SATraceString("AlertEmail:SendMail failed to allocate memory for bstrMailAddress" );
  1028. hr = E_OUTOFMEMORY;
  1029. break;
  1030. }
  1031. //
  1032. // Set mail address.
  1033. //
  1034. hr = m_pcdoIMessage->put_To( bstrMailAddress);
  1035. if( FAILED(hr) )
  1036. {
  1037. SATraceString(
  1038. "AlertEmail:SendMail put_To failed"
  1039. );
  1040. break;
  1041. }
  1042. //
  1043. // Set mail subject.
  1044. //
  1045. hr = m_pcdoIMessage->put_Subject( bstrSubject );
  1046. if( FAILED(hr) )
  1047. {
  1048. SATraceString(
  1049. "AlertEmail:SendMail put_Subject failed"
  1050. );
  1051. break;
  1052. }
  1053. //
  1054. // Get text bodypart from the message object.
  1055. //
  1056. CComPtr<IBodyPart> pMsgBodyPart;
  1057. hr = m_pcdoIMessage->get_BodyPart( &pMsgBodyPart );
  1058. if( FAILED(hr) )
  1059. {
  1060. SATraceString(
  1061. "AlertEmail:SendMail get_TextBodyPart failed"
  1062. );
  1063. break;
  1064. }
  1065. //
  1066. // Get current char set from localize manager.
  1067. //
  1068. CComBSTR bstrCharSet;
  1069. hr = m_pLocInfo->get_CurrentCharSet( &bstrCharSet );
  1070. if( FAILED(hr) )
  1071. {
  1072. SATraceString(
  1073. "AlertEmail:SendMail get_CurrentCharSet failed"
  1074. );
  1075. break;
  1076. }
  1077. //
  1078. // Set char set to text bodypart with current char set.
  1079. //
  1080. // TMARSH: Hardcode charset to UTF-8.
  1081. hr = pMsgBodyPart->put_Charset( CComBSTR(L"utf-8") );
  1082. // hr = pMsgBodyPart->put_Charset( bstrCharSet );
  1083. if( FAILED(hr) )
  1084. {
  1085. SATraceString(
  1086. "AlertEmail:SendMail put_CharSet failed"
  1087. );
  1088. break;
  1089. }
  1090. CComBSTR bstrExtendMessage;
  1091. bstrExtendMessage.AppendBSTR( bstrMessage );
  1092. /* bstrExtendMessage += CComBSTR( ENTER );
  1093. bstrExtendMessage += CComBSTR( HTTPHEADER );
  1094. bstrExtendMessage += CComBSTR( m_pstrApplianceName );
  1095. hr = GetAppliancePort( &pstrPort );
  1096. if( SUCCEEDED( hr ) )
  1097. {
  1098. bstrExtendMessage += CComBSTR( pstrPort );
  1099. }
  1100. else
  1101. {
  1102. SATraceString(
  1103. "AlertEmail:SendMail GetAppliancePort failed"
  1104. );
  1105. }
  1106. */
  1107. //
  1108. // Set mail message.
  1109. //
  1110. hr = m_pcdoIMessage->put_TextBody( bstrExtendMessage );
  1111. if( FAILED(hr) )
  1112. {
  1113. SATraceString(
  1114. "AlertEmail:SendMail put_TextBody failed"
  1115. );
  1116. break;
  1117. }
  1118. //
  1119. // Send it.
  1120. //
  1121. hr = m_pcdoIMessage->Send();
  1122. }while( FALSE );
  1123. if( pstrPort!= NULL )
  1124. {
  1125. ::free( pstrPort );
  1126. }
  1127. return hr;
  1128. }
  1129. //////////////////////////////////////////////////////////////////////////////
  1130. //
  1131. // CAlertEmailConsumer::GetFullyQualifiedDomainName
  1132. //
  1133. // Description:
  1134. // This is the CAlertEmailConsumer class private method which is used
  1135. // to get local appliance name in DNS format.
  1136. //
  1137. // Arguments:
  1138. // [in,out] pstrComputerName Pointer of computer name string.
  1139. //
  1140. // Returns:
  1141. // TRUE if successful
  1142. // FALSE if not
  1143. //
  1144. // History:
  1145. // Xing Jin (i-xingj) 23-Dec-2000
  1146. //
  1147. //////////////////////////////////////////////////////////////////////////////
  1148. BOOL
  1149. CAlertEmailConsumer::GetComputerName(
  1150. LPWSTR* pstrComputerName,
  1151. COMPUTER_NAME_FORMAT nametype
  1152. )
  1153. {
  1154. BOOL bReturn = FALSE;
  1155. DWORD dwSize = 0;
  1156. DWORD dwCount = 1;
  1157. do
  1158. {
  1159. if( *pstrComputerName != NULL )
  1160. {
  1161. ::free( *pstrComputerName );
  1162. }
  1163. dwSize = MAXAPPLIANCEDNSNAME * dwCount;
  1164. *pstrComputerName = ( LPWSTR ) ::malloc( sizeof(WCHAR) * dwSize );
  1165. if( *pstrComputerName == NULL )
  1166. {
  1167. SATraceString(
  1168. "AlertEmail:GetApplianceName malloc failed"
  1169. );
  1170. break;
  1171. }
  1172. //
  1173. // Get local computer name.
  1174. //
  1175. bReturn = ::GetComputerNameEx(
  1176. nametype,
  1177. *pstrComputerName,
  1178. &dwSize
  1179. );
  1180. dwCount <<= 1;
  1181. }
  1182. while( !bReturn &&
  1183. ERROR_MORE_DATA == ::GetLastError() &&
  1184. dwCount < 32
  1185. );
  1186. return bReturn;
  1187. }
  1188. //////////////////////////////////////////////////////////////////////////////
  1189. //
  1190. // CAlertEmailConsumer::GetAppliancePort
  1191. //
  1192. // Description:
  1193. // This is the CAlertEmailConsumer class private method which is used
  1194. // to get local appliance port.
  1195. //
  1196. // Arguments:
  1197. // [in,out] pstrPort Pointer of server port string.
  1198. //
  1199. // Returns:
  1200. // TRUE if successful
  1201. // FALSE if not
  1202. //
  1203. // History:
  1204. // Xing Jin (i-xingj) 23-Dec-2000
  1205. //
  1206. //////////////////////////////////////////////////////////////////////////////
  1207. HRESULT
  1208. CAlertEmailConsumer::GetAppliancePort(
  1209. LPWSTR* pstrPort
  1210. )
  1211. {
  1212. HRESULT hr = S_OK;
  1213. try
  1214. {
  1215. do
  1216. {
  1217. CComPtr <IWbemLocator> pWbemLocator;
  1218. CComPtr <IWbemServices> pWbemServices;
  1219. CComPtr <IEnumWbemClassObject> pEnumServices;
  1220. //
  1221. // create the WBEM locator object
  1222. //
  1223. hr = ::CoCreateInstance (
  1224. CLSID_WbemLocator,
  1225. 0, //aggregation pointer
  1226. CLSCTX_INPROC_SERVER,
  1227. IID_IWbemLocator,
  1228. (PVOID*) &pWbemLocator
  1229. );
  1230. if( FAILED(hr) )
  1231. {
  1232. SATraceString(
  1233. "AlertEmail:GetAppliancePort CoCreateInstance failed"
  1234. );
  1235. break;
  1236. }
  1237. //
  1238. // allocate memory for BSTR
  1239. //
  1240. CComBSTR bstrDefaultNameSpace (DEFAULT_NAMESPACE);
  1241. if (NULL == bstrDefaultNameSpace.m_str)
  1242. {
  1243. SATraceString("AlertEmail:GetAppliancePort failed to allocate memory for DEFAULT_NAMESPACE" );
  1244. hr = E_OUTOFMEMORY;
  1245. break;
  1246. }
  1247. //
  1248. // connect to WMI
  1249. //
  1250. hr = pWbemLocator->ConnectServer (
  1251. bstrDefaultNameSpace,
  1252. NULL, //user-name
  1253. NULL, //password
  1254. 0, //current-locale
  1255. 0, //reserved
  1256. NULL, //authority
  1257. NULL, //context
  1258. &pWbemServices
  1259. );
  1260. if( hr != WBEM_S_NO_ERROR )
  1261. {
  1262. SATraceString(
  1263. "AlertEmail:GetAppliancePort ConnectServer failed"
  1264. );
  1265. break;
  1266. }
  1267. //
  1268. // Query Web server instance.
  1269. //
  1270. hr = pWbemServices->ExecQuery(
  1271. CComBSTR( QUERY_LANGUAGE ),
  1272. CComBSTR( QUERY_STRING ),
  1273. 0,
  1274. NULL,
  1275. &pEnumServices
  1276. );
  1277. if( hr != WBEM_S_NO_ERROR )
  1278. {
  1279. SATraceString(
  1280. "AlertEmail:GetAppliancePort ExecQuery failed"
  1281. );
  1282. break;
  1283. }
  1284. CComPtr <IWbemClassObject> pService;
  1285. ULONG uReturned;
  1286. //
  1287. // Now,we only care for the first match.
  1288. //
  1289. hr = pEnumServices->Next(
  1290. WBEM_NO_WAIT,
  1291. 1,
  1292. &pService,
  1293. &uReturned
  1294. );
  1295. if( hr != WBEM_S_NO_ERROR )
  1296. {
  1297. SATraceString(
  1298. "AlertEmail:GetAppliancePort nothing found"
  1299. );
  1300. break;
  1301. }
  1302. CComVariant vtServerBindings;
  1303. //
  1304. // Get the "ServerBindings" property.
  1305. //
  1306. hr = pService->Get(
  1307. CComBSTR( SERVERBINDINGSPROP ),
  1308. 0,
  1309. &vtServerBindings,
  1310. 0,
  1311. 0
  1312. );
  1313. if ( FAILED(hr) || !V_ISARRAY( &vtServerBindings ) )
  1314. {
  1315. hr = E_FAIL;
  1316. SATraceString(
  1317. "AlertEmail:GetAppliancePort get serverbindings failed"
  1318. );
  1319. break;
  1320. }
  1321. SAFEARRAY* psa;
  1322. BSTR HUGEP *pbstr;
  1323. //
  1324. // The property type is VT_ARRAY | VT_BSTR.
  1325. //
  1326. psa = V_ARRAY( &vtServerBindings );
  1327. if( psa->cDims <= 0 )
  1328. {
  1329. hr = E_FAIL;
  1330. SATraceString(
  1331. "AlertEmail:GetAppliancePort array dim error"
  1332. );
  1333. break;
  1334. }
  1335. //
  1336. // Access array data directly,it's a faster way.
  1337. //
  1338. hr = ::SafeArrayAccessData( psa, ( void HUGEP** )&pbstr );
  1339. if (FAILED(hr))
  1340. {
  1341. SATraceString(
  1342. "AlertEmail:GetAppliancePort SafeArrayAccessData failed"
  1343. );
  1344. break;
  1345. }
  1346. //
  1347. // Now we can alloc the port string.
  1348. //
  1349. *pstrPort = ( LPWSTR )malloc( sizeof(WCHAR) * MAX_COMPUTERNAME_LENGTH );
  1350. if( *pstrPort == NULL )
  1351. {
  1352. hr = E_FAIL;
  1353. SATraceString(
  1354. "AlertEmail:GetAppliancePort malloc failed"
  1355. );
  1356. break;
  1357. }
  1358. WCHAR* pszTemp1;
  1359. WCHAR* pszTemp2;
  1360. pszTemp1 = ::wcschr( pbstr[0], COLON );
  1361. pszTemp2 = ::wcsrchr( pbstr[0], COLON );
  1362. if( pszTemp2 != NULL && pszTemp1 != NULL )
  1363. {
  1364. pszTemp2[0] = ENDCODE;
  1365. ::wcscpy( *pstrPort, pszTemp1 );
  1366. }
  1367. else
  1368. {
  1369. SATraceString(
  1370. "AlertEmail:GetAppliancePort string formate error"
  1371. );
  1372. hr = E_FAIL;
  1373. }
  1374. ::SafeArrayUnaccessData( psa );
  1375. }
  1376. while( false );
  1377. }
  1378. catch (...)
  1379. {
  1380. SATraceString(
  1381. "AlertEmail:GetAppliancePort unkown exception"
  1382. );
  1383. hr = E_FAIL;
  1384. }
  1385. return hr;
  1386. }
  1387. //////////////////////////////////////////////////////////////////////////////
  1388. //
  1389. // CAlertEmailConsumer::RetrieveRegInfo
  1390. //
  1391. // Description:
  1392. // This is the CAlertEmailConsumer class private method which is used
  1393. // to retrieve alert email settings from registry.
  1394. //
  1395. // Returns:
  1396. // TRUE if successful
  1397. // FALSE if not
  1398. //
  1399. // History:
  1400. // Xing Jin (i-xingj) 23-Dec-2000
  1401. //
  1402. //////////////////////////////////////////////////////////////////////////////
  1403. BOOL
  1404. CAlertEmailConsumer::RetrieveRegInfo()
  1405. {
  1406. BOOL bReturn = TRUE;
  1407. LONG lReturn;
  1408. DWORD dwDataSize;
  1409. //
  1410. // Get the email address will be send to.
  1411. //
  1412. dwDataSize = sizeof(m_pstrMailAddress);
  1413. lReturn = ::RegQueryValueEx(
  1414. m_hAlertKey,
  1415. RECEIVEREMAILADDRESS,
  1416. NULL,
  1417. NULL,
  1418. reinterpret_cast<PBYTE>(m_pstrMailAddress),
  1419. &dwDataSize );
  1420. if( lReturn != ERROR_SUCCESS)
  1421. {
  1422. m_pstrMailAddress[0] = L'\0'; // RegQueryValueEx doesn't guarantee
  1423. // a desirable value, so clear the string.
  1424. SATraceString(
  1425. "AlertEmail:RetrieveRegInfo query address failed"
  1426. );
  1427. bReturn = FALSE;
  1428. }
  1429. else
  1430. {
  1431. _ASSERT(dwDataSize <= sizeof(m_pstrMailAddress));
  1432. //
  1433. // Validate the e-mail address length.
  1434. //
  1435. LONG lLastCharacter;
  1436. if( sizeof( m_pstrMailAddress[0] ) > dwDataSize )
  1437. {
  1438. lLastCharacter = 0;
  1439. }
  1440. else
  1441. {
  1442. lLastCharacter = dwDataSize / sizeof( m_pstrMailAddress[0] ) - 1;
  1443. }
  1444. if( sizeof(m_pstrMailAddress) == dwDataSize &&
  1445. L'\0' != m_pstrMailAddress[lLastCharacter] )
  1446. {
  1447. SATraceString( "AlertEmail:RetrieveRegInfo address too long" );
  1448. bReturn = FALSE;
  1449. }
  1450. m_pstrMailAddress[lLastCharacter] = L'\0';
  1451. }
  1452. //
  1453. // Get alert enable setting.
  1454. //
  1455. dwDataSize = sizeof( LONG );
  1456. lReturn = ::RegQueryValueEx(
  1457. m_hAlertKey,
  1458. ENABLEALERTEAMIL,
  1459. NULL,
  1460. NULL,
  1461. reinterpret_cast<PBYTE>(&m_lAlertEmailDisabled),
  1462. &dwDataSize
  1463. );
  1464. if( lReturn != ERROR_SUCCESS)
  1465. {
  1466. SATraceString(
  1467. "AlertEmail:RetrieveRegInfo query enablealertemail failed"
  1468. );
  1469. bReturn = FALSE;
  1470. }
  1471. //
  1472. // Get alert type setting.
  1473. //
  1474. dwDataSize = sizeof( LONG );
  1475. lReturn = ::RegQueryValueEx(
  1476. m_hAlertKey,
  1477. SENDEMAILTYPE,
  1478. NULL,
  1479. NULL,
  1480. reinterpret_cast<PBYTE>(&m_lCurAlertType),
  1481. &dwDataSize
  1482. );
  1483. if( lReturn != ERROR_SUCCESS)
  1484. {
  1485. SATraceString(
  1486. "AlertEmail:RetrieveRegInfo query enablealertemail failed"
  1487. );
  1488. bReturn = FALSE;
  1489. }
  1490. return bReturn;
  1491. }
  1492. //////////////////////////////////////////////////////////////////////////////
  1493. //
  1494. // CAlertEmailConsumer::RegThreadProc
  1495. //
  1496. // Description:
  1497. // This is the CAlertEmailConsumer class static method which is used
  1498. // as worker thread entry.
  1499. //
  1500. // Arguments:
  1501. // [in] pIn Point to an instance of CAlertEmailConsumer class.
  1502. //
  1503. // Returns:
  1504. // 0 if successful
  1505. // -1 if not
  1506. //
  1507. // History:
  1508. // Xing Jin (i-xingj) 23-Dec-2000
  1509. //
  1510. //////////////////////////////////////////////////////////////////////////////
  1511. DWORD WINAPI
  1512. CAlertEmailConsumer::RegThreadProc(
  1513. PVOID pIn
  1514. )
  1515. {
  1516. //
  1517. // Make transition to the per-instance method.
  1518. //
  1519. ( (CAlertEmailConsumer *) pIn )->RegThread();
  1520. return 0;
  1521. }
  1522. //////////////////////////////////////////////////////////////////////////////
  1523. //
  1524. // CAlertEmailConsumer::RegThread
  1525. //
  1526. // Description:
  1527. // This is the CAlertEmailConsumer class public method which is real
  1528. // worker thread process.
  1529. //
  1530. // History:
  1531. // Xing Jin (i-xingj) 23-Dec-2000
  1532. //
  1533. //////////////////////////////////////////////////////////////////////////////
  1534. void
  1535. CAlertEmailConsumer::RegThread()
  1536. {
  1537. HANDLE hHandleArray[2];
  1538. DWORD dwEventCount;
  1539. DWORD dwReturn;
  1540. SATraceString(
  1541. "AlertEmail:RegThread enter"
  1542. );
  1543. //
  1544. // Handle list used by WaitForMultipleObjects
  1545. //
  1546. hHandleArray[0] = m_hCloseThreadEvent;
  1547. //
  1548. // Event for RegNotifyChangeKeyValue.
  1549. //
  1550. hHandleArray[1] = ::CreateEvent( NULL, FALSE, FALSE, NULL );
  1551. if( hHandleArray[1] != NULL )
  1552. {
  1553. dwEventCount = 2;
  1554. //
  1555. // Monitor key change action.
  1556. //
  1557. ::RegNotifyChangeKeyValue( m_hAlertKey, //AlertEmail key
  1558. FALSE, //No subkey
  1559. REG_NOTIFY_CHANGE_LAST_SET, //Value change
  1560. hHandleArray[1], //Event handle
  1561. TRUE ); //APC
  1562. }
  1563. else
  1564. {
  1565. SATraceString(
  1566. "AlertEmail:RegThread CreateEvent failed"
  1567. );
  1568. dwEventCount = 1;
  1569. }
  1570. while( TRUE )
  1571. {
  1572. //
  1573. // Wait for both close and regchange event.
  1574. //
  1575. dwReturn = ::WaitForMultipleObjects( dwEventCount,
  1576. hHandleArray,
  1577. FALSE,
  1578. INFINITE );
  1579. switch( dwReturn )
  1580. {
  1581. case WAIT_OBJECT_0:
  1582. {
  1583. //
  1584. // Close thread event set in release method.
  1585. //
  1586. SATraceString(
  1587. "AlertEmail:RegThread get close event"
  1588. );
  1589. if( hHandleArray[1] != NULL )
  1590. {
  1591. ::CloseHandle( hHandleArray[1] );
  1592. }
  1593. //
  1594. // Clean up.
  1595. //
  1596. delete this;
  1597. return;
  1598. } //case WAIT_OBJECT_0:
  1599. case WAIT_OBJECT_0 + 1:
  1600. {
  1601. //
  1602. // Registry changed event.
  1603. //
  1604. SATraceString(
  1605. "AlertEmail:RegThread get reg event"
  1606. );
  1607. BOOL bReturn;
  1608. //
  1609. // Refresh alert email settings.
  1610. //
  1611. bReturn = RetrieveRegInfo();
  1612. if( bReturn == FALSE )
  1613. {
  1614. SATraceString(
  1615. "AlertEmail:RegThread RetrieveRegInfo failed"
  1616. );
  1617. }
  1618. break;
  1619. } //case WAIT_OBJECT_0 + 1:
  1620. default:
  1621. {
  1622. //
  1623. // Wait error ocupied.
  1624. //
  1625. SATraceString(
  1626. "AlertEmail:RegThread waitevent error"
  1627. );
  1628. break;
  1629. } //default:
  1630. } //switch(dwReturn)
  1631. } // While( TRUE )
  1632. return;
  1633. }
  1634. //////////////////////////////////////////////////////////////////////////////
  1635. //
  1636. // CAlertEmailConsumer::InitializeLocalManager
  1637. //
  1638. // Description:
  1639. // This is the CAlertEmailConsumer class private method which is used
  1640. // to get object of Local Manager.
  1641. //
  1642. // Returns:
  1643. // WBEM_S_NO_ERROR if successful
  1644. // WBEM_E_FAILED if not
  1645. //
  1646. // History:
  1647. // Xing Jin (i-xingj) 23-Dec-2000
  1648. //
  1649. //////////////////////////////////////////////////////////////////////////////
  1650. HRESULT CAlertEmailConsumer::InitializeLocalManager()
  1651. {
  1652. CLSID clsidLocMgr;
  1653. HRESULT hr;
  1654. hr = ::CLSIDFromProgID (
  1655. LOCALIZATION_MANAGER,
  1656. &clsidLocMgr
  1657. );
  1658. if (SUCCEEDED (hr))
  1659. {
  1660. //
  1661. // create the Localization Manager COM object
  1662. //
  1663. hr = ::CoCreateInstance (
  1664. clsidLocMgr,
  1665. NULL,
  1666. CLSCTX_INPROC_SERVER,
  1667. __uuidof (ISALocInfo),
  1668. (PVOID*) &m_pLocInfo
  1669. );
  1670. }
  1671. return hr;
  1672. }
  1673. //////////////////////////////////////////////////////////////////////////////
  1674. //
  1675. // CAlertEmailConsumer::InitializeElementManager
  1676. //
  1677. // Description:
  1678. // This is the CAlertEmailConsumer class private method which is used
  1679. // to get object of elements enum interface from Element manager.
  1680. //
  1681. // Returns:
  1682. // WBEM_S_NO_ERROR if successful
  1683. // WBEM_E_FAILED if not
  1684. //
  1685. // History:
  1686. // Xing Jin (i-xingj) 23-Dec-2000
  1687. //
  1688. //////////////////////////////////////////////////////////////////////////////
  1689. HRESULT
  1690. CAlertEmailConsumer::InitializeElementManager()
  1691. {
  1692. HRESULT hr = WBEM_S_NO_ERROR;
  1693. IDispatch *pDispatch = NULL;
  1694. IWebElementRetriever *pWebElementRetriever = NULL;
  1695. do
  1696. {
  1697. //
  1698. // Get Element Manager's CLSID.
  1699. //
  1700. CLSID clsid;
  1701. hr = ::CLSIDFromProgID (
  1702. ELEMENT_RETRIEVER,
  1703. &clsid
  1704. );
  1705. if (FAILED (hr))
  1706. {
  1707. break;
  1708. }
  1709. //
  1710. // create the WebElementRetriever now
  1711. //
  1712. hr = ::CoCreateInstance (
  1713. clsid,
  1714. NULL,
  1715. CLSCTX_LOCAL_SERVER,
  1716. IID_IWebElementRetriever,
  1717. (PVOID*) &pWebElementRetriever
  1718. );
  1719. if (FAILED (hr))
  1720. {
  1721. break;
  1722. }
  1723. //
  1724. // allocate memory for BSTR(alert definitions)
  1725. //
  1726. CComBSTR bstrAlertDefinitions (ALERTDEFINITIONS);
  1727. if (NULL == bstrAlertDefinitions.m_str)
  1728. {
  1729. hr = E_OUTOFMEMORY;
  1730. break;
  1731. }
  1732. //
  1733. // Initial now
  1734. //
  1735. hr = pWebElementRetriever->GetElements (
  1736. WEB_ELEMENT_TYPE_DEFINITION,
  1737. bstrAlertDefinitions,
  1738. &pDispatch
  1739. );
  1740. if (FAILED (hr))
  1741. {
  1742. break;
  1743. }
  1744. //
  1745. // get the enum variant
  1746. //
  1747. hr = pDispatch->QueryInterface (
  1748. IID_IWebElementEnum,
  1749. reinterpret_cast <PVOID*> (&m_pElementEnum)
  1750. );
  1751. }while( FALSE );
  1752. if( pDispatch != NULL )
  1753. {
  1754. pDispatch->Release();
  1755. }
  1756. if( pWebElementRetriever != NULL )
  1757. {
  1758. pWebElementRetriever->Release();
  1759. }
  1760. return hr;
  1761. }
  1762. //////////////////////////////////////////////////////////////////////////////
  1763. //
  1764. // CAlertEmailConsumer::InitializeCDOMessage
  1765. //
  1766. // Description:
  1767. // This is the CAlertEmailConsumer class private method which is used
  1768. // to get object of CDO::IMessage and set the configuration as using
  1769. // local SMTP server.
  1770. //
  1771. // Returns:
  1772. // WBEM_S_NO_ERROR if successful
  1773. // WBEM_E_FAILED if not
  1774. //
  1775. // History:
  1776. // Xing Jin (i-xingj) 23-Dec-2000
  1777. //
  1778. //////////////////////////////////////////////////////////////////////////////
  1779. HRESULT CAlertEmailConsumer::InitializeCDOMessage()
  1780. {
  1781. HRESULT hr = S_OK;
  1782. CComPtr <IConfiguration> pConfig;
  1783. do
  1784. {
  1785. //
  1786. // Get an object of IMessage
  1787. //
  1788. hr = CoCreateInstance(
  1789. CLSID_Message,
  1790. NULL,
  1791. CLSCTX_INPROC_SERVER,
  1792. IID_IMessage,
  1793. (PVOID*) &m_pcdoIMessage
  1794. );
  1795. if (FAILED (hr))
  1796. {
  1797. SATraceString(
  1798. "AlertEmail: InitializeCDOMessage CoCreateInstance failed"
  1799. );
  1800. break;
  1801. }
  1802. //
  1803. // Get the configuration in this message object.
  1804. //
  1805. hr = m_pcdoIMessage->get_Configuration(&pConfig);
  1806. if (FAILED (hr))
  1807. {
  1808. SATraceString(
  1809. "AlertEmail: InitializeCDOMessage get_Configuration failed"
  1810. );
  1811. break;
  1812. }
  1813. //
  1814. // Set the configuration as default setting of local
  1815. // SMTP server.
  1816. //
  1817. hr = pConfig->Load( cdoIIS, NULL );
  1818. }
  1819. while( FALSE );
  1820. return hr;
  1821. }