Source code of Windows XP (NT5)
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.

2757 lines
79 KiB

  1. //***********************************************************************
  2. // trapreg.cpp
  3. //
  4. // This file contains the implementation of the classes for the objects
  5. // that are read from the registry, manipulated and written back to the
  6. // registry.
  7. //
  8. // Author: Larry A. French
  9. //
  10. // History:
  11. // 20-Febuary-1996 Larry A. French
  12. // Totally rewrote it to fix the spagetti code and huge
  13. // methods. The original author seemed to have little or
  14. // no ability to form meaningful abstractions.
  15. //
  16. //
  17. // Copyright (C) 1995, 1996 Microsoft Corporation. All rights reserved.
  18. //
  19. //************************************************************************
  20. //
  21. // Some of the interesting class implementations contained here are:
  22. //
  23. // CTrapReg
  24. // This is the container class for the registry information. It is
  25. // composed of the configuration "parameters" and an EventLog array.
  26. //
  27. // CXEventLogArray
  28. // This class implements an array of CXEventLog objects, where the
  29. // event logs are "application", "security", "system" and so on.
  30. //
  31. // CXEventLog
  32. // This class implements a single event log. All information
  33. // relevent to an event log can be accesssed through this class.
  34. //
  35. // CXEventSourceArray
  36. // Each event log contains an event source array. The event source
  37. // represents an application that can generate an Event.
  38. //
  39. // CXEventSource
  40. // An eventsource represents an application that can generate some
  41. // number of event-log events. The event source contains a CXEventArray
  42. // and CXMessageArray. The CXEventArray contains all the events
  43. // that will be converted to traps. The CXMessageArray contains all the
  44. // possible messages that a particular event source can generate.
  45. //
  46. // CXMessageArray
  47. // This class implements an array of CXMessage objects.
  48. //
  49. // CXMessage
  50. // This class contains all the information relevent to a message
  51. // that a message source can generate.
  52. //
  53. //
  54. // CXEventArray
  55. // This class implements an array of CXEvent objects.
  56. //
  57. // CXEvent
  58. // This class represents an event that the user has selected to be
  59. // converted to a trap. The event contains a message plus some
  60. // additional information.
  61. //
  62. //**************************************************************************
  63. // The Registry:
  64. //
  65. // These classes are loaded from the registry and written back to the
  66. // registry when the user clicks OK. To understand the format of the
  67. // registry, use the registry editor while looking though the "Serialize"
  68. // and "Deserialize" member function for each of these classes.
  69. //**************************************************************************
  70. #include "stdafx.h"
  71. #include "trapreg.h"
  72. #include "regkey.h"
  73. #include "busy.h"
  74. #include "utils.h"
  75. #include "globals.h"
  76. #include "utils.h"
  77. #include "dlgsavep.h"
  78. #include "remote.h"
  79. ///////////////////////////////////////////////////////////////////
  80. // Class: CBaseArray
  81. //
  82. // This class extends the CObArray class by adding the DeleteAll
  83. // method.
  84. //
  85. //////////////////////////////////////////////////////////////////
  86. //****************************************************************
  87. // CBaseArray::DeleteAll
  88. //
  89. // Delete all the objects contained in this array.
  90. //
  91. // Parameters:
  92. // None.
  93. //
  94. // Returns:
  95. // Nothing.
  96. //
  97. //****************************************************************
  98. void CBaseArray::DeleteAll()
  99. {
  100. LONG nObjects = (LONG)GetSize();
  101. for (LONG iObject = nObjects-1; iObject >= 0; --iObject) {
  102. CObject* pObject = GetAt(iObject);
  103. delete pObject;
  104. }
  105. RemoveAll();
  106. }
  107. /////////////////////////////////////////////////////////////////////////////////////
  108. // Class: CTrapReg
  109. //
  110. // This is the container class for all the registry information for eventrap.exe.
  111. //
  112. ////////////////////////////////////////////////////////////////////////////////////
  113. CTrapReg::CTrapReg() : m_pdlgLoadProgress(FALSE), m_pbtnApply(FALSE)
  114. {
  115. m_bNeedToCloseKeys = FALSE;
  116. m_pdlgSaveProgress = NULL;
  117. m_pdlgLoadProgress = NULL;
  118. m_bDidLockRegistry = FALSE;
  119. m_bRegIsReadOnly = FALSE;
  120. SetDirty(FALSE);
  121. m_nLoadSteps = LOAD_STEPS_IN_TRAPDLG;
  122. m_bShowConfigTypeBox = TRUE;
  123. m_dwConfigType = CONFIG_TYPE_CUSTOM;
  124. }
  125. CTrapReg::~CTrapReg()
  126. {
  127. delete m_pdlgSaveProgress;
  128. delete m_pdlgLoadProgress;
  129. if (!g_bLostConnection) {
  130. if (m_bDidLockRegistry) {
  131. UnlockRegistry();
  132. }
  133. if (m_bNeedToCloseKeys) {
  134. m_regkeySource.Close();
  135. m_regkeySnmp.Close();
  136. m_regkeyEventLog.Close();
  137. }
  138. }
  139. }
  140. //*********************************************************************************
  141. // CTrapReg::SetConfigType
  142. //
  143. // Set the configuration type to CONFIG_TYPE_CUSTOM or CONFIG_TYPE_DEFAULT
  144. // When the configuration type is changed, the change is reflected in the
  145. // registry immediately so that the config tool can know whether or not it
  146. // should update the event to trap configuration.
  147. //
  148. // Parameters:
  149. // DWORD dwConfigType
  150. // This parameter must be CONFIG_TYPE_CUSTOM or CONFIG_TYPE_DEFAULT.
  151. //
  152. // Returns:
  153. // SCODE
  154. // S_OK if the configuration type was set, otherwise E_FAIL.
  155. //
  156. //*********************************************************************************
  157. SCODE CTrapReg::SetConfigType(DWORD dwConfigType)
  158. {
  159. ASSERT(dwConfigType==CONFIG_TYPE_CUSTOM || dwConfigType==CONFIG_TYPE_DEFAULT_PENDING);
  160. if (dwConfigType != m_dwConfigType) {
  161. SetDirty(TRUE);
  162. }
  163. m_dwConfigType = dwConfigType;
  164. return S_OK;
  165. }
  166. //*********************************************************************************
  167. // CTrapReg::LockRegistry
  168. //
  169. // Lock the registry to prevent two concurrent edits of the event-to-trap configuration
  170. // information.
  171. //
  172. // Parameters:
  173. // None.
  174. //
  175. // Returns:
  176. // SCODE
  177. // S_OK if successful.
  178. // E_FAIL if the configuration information was already locked.
  179. // E_REGKEY_NO_CREATE if the "CurrentlyOpen" registry key can't
  180. // be created.
  181. //
  182. //**********************************************************************************
  183. SCODE CTrapReg::LockRegistry()
  184. {
  185. if (g_bLostConnection) {
  186. return E_REGKEY_LOST_CONNECTION;
  187. }
  188. CRegistryKey regkey;
  189. if (m_regkeyEventLog.GetSubKey(SZ_REGKEY_CURRENTLY_OPEN, regkey)) {
  190. if (g_bLostConnection) {
  191. return E_REGKEY_LOST_CONNECTION;
  192. }
  193. if (AfxMessageBox(IDS_ERR_REGISTRY_BUSY, MB_YESNO | MB_ICONSTOP | MB_DEFBUTTON2) == IDNO)
  194. {
  195. regkey.Close();
  196. return E_FAIL;
  197. }
  198. }
  199. // Create the "CurrentlyOpen" key as a volatile key so that it will disappear the next
  200. // time the machine is restarted in the event that the application that locked the
  201. // event-to-trap configuration crashed before it could clear this lock.
  202. if (!m_regkeyEventLog.CreateSubKey(SZ_REGKEY_CURRENTLY_OPEN, regkey, NULL, NULL, TRUE)) {
  203. if (g_bLostConnection) {
  204. return E_REGKEY_LOST_CONNECTION;
  205. }
  206. AfxMessageBox(IDS_WARNING_CANT_WRITE_CONFIG, MB_OK | MB_ICONSTOP);
  207. return E_REGKEY_NO_CREATE;
  208. }
  209. regkey.Close();
  210. m_bDidLockRegistry = TRUE;
  211. return S_OK;
  212. }
  213. //***********************************************************************
  214. // CTrapReg::UnlockRegistry
  215. //
  216. // Unlock the event-to-trap configuration so that others can edit it.
  217. //
  218. // Parameters:
  219. // None.
  220. //
  221. // Returns:
  222. // Nothing.
  223. //
  224. //***********************************************************************
  225. void CTrapReg::UnlockRegistry()
  226. {
  227. m_regkeyEventLog.DeleteSubKey(SZ_REGKEY_CURRENTLY_OPEN);
  228. }
  229. //***********************************************************************
  230. // CTrapReg::Connect
  231. //
  232. // Connect to a registry. The registry may exist on a remote computer.
  233. //
  234. // Parameters:
  235. // LPCTSTR pszComputerName
  236. // The computer who's registry you want to edit. An empty string
  237. // specifies a request to connect to the local machine.
  238. //
  239. // Returns:
  240. // SCODE
  241. // S_OK if the connection was made.
  242. // E_FAIL if an error occurred. In this event, the appropriate
  243. // error message boxes will have already been displayed.
  244. //
  245. //***********************************************************************
  246. SCODE CTrapReg::Connect(LPCTSTR pszComputerName, BOOL bIsReconnecting)
  247. {
  248. SCODE sc;
  249. g_bLostConnection = FALSE;
  250. if (pszComputerName) {
  251. m_sComputerName = pszComputerName;
  252. }
  253. // There are eight steps here, plus there are three initial steps in
  254. // CTrapReg::Deserialize. After that the step count will be reset
  255. // and then stepped again for each log where each log will have
  256. // ten sub-steps.
  257. if (!bIsReconnecting) {
  258. m_pdlgLoadProgress->SetStepCount(LOAD_STEP_COUNT);
  259. }
  260. CRegistryValue regval;
  261. CRegistryKey regkeyEventLog;
  262. if (m_regkeySource.Connect(pszComputerName) != ERROR_SUCCESS) {
  263. if (m_regkeySource.m_lResult == ERROR_ACCESS_DENIED) {
  264. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  265. return E_ACCESS_DENIED;
  266. }
  267. goto CONNECT_FAILURE;
  268. }
  269. if (!bIsReconnecting) {
  270. if (m_pdlgLoadProgress->StepProgress()) {
  271. return S_LOAD_CANCELED;
  272. }
  273. ++m_nLoadSteps;
  274. }
  275. if (m_regkeySnmp.Connect(pszComputerName) != ERROR_SUCCESS) {
  276. if (m_regkeySnmp.m_lResult == ERROR_ACCESS_DENIED) {
  277. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  278. return E_ACCESS_DENIED;
  279. }
  280. goto CONNECT_FAILURE;
  281. }
  282. if (!bIsReconnecting) {
  283. if (m_pdlgLoadProgress->StepProgress()) {
  284. return S_LOAD_CANCELED;
  285. }
  286. ++m_nLoadSteps;
  287. }
  288. // SOFTWARE\\Microsoft\\SNMP_EVENTS
  289. if (m_regkeySnmp.Open(SZ_REGKEY_SNMP_EVENTS, KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY) != ERROR_SUCCESS) {
  290. if (m_regkeySnmp.Open(SZ_REGKEY_SNMP_EVENTS, KEY_READ) == ERROR_SUCCESS) {
  291. m_bRegIsReadOnly = TRUE;
  292. }
  293. else {
  294. // At this point we know the SNMP_EVENTS key could not be opened. This
  295. // could either be because we don't have access to the registry or we
  296. // weren't installed yet. We now check to see if we can access the
  297. // registry at all.
  298. CRegistryKey regkeyMicrosoft;
  299. if (regkeyMicrosoft.Open(SZ_REGKEY_MICROSOFT, KEY_READ) == ERROR_SUCCESS) {
  300. regkeyMicrosoft.Close();
  301. AfxMessageBox(IDS_ERR_NOT_INSTALLED, MB_OK | MB_ICONSTOP);
  302. }
  303. else {
  304. // We couldn't even access SOFTWARE\Microsoft, so we know that
  305. // we don't have access to the registry.
  306. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  307. return E_ACCESS_DENIED;
  308. }
  309. }
  310. return E_FAIL;
  311. }
  312. if (!bIsReconnecting) {
  313. if (m_pdlgLoadProgress->StepProgress()) {
  314. return S_LOAD_CANCELED;
  315. }
  316. ++m_nLoadSteps;
  317. }
  318. // SYSTEM\\CurrentControlSet\\Services\\EventLog
  319. if (m_regkeySource.Open(SZ_REGKEY_SOURCE_EVENTLOG, KEY_ENUMERATE_SUB_KEYS | KEY_READ | KEY_QUERY_VALUE ) != ERROR_SUCCESS) {
  320. m_regkeySnmp.Close();
  321. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  322. return E_ACCESS_DENIED;
  323. }
  324. if (!bIsReconnecting) {
  325. if (m_pdlgLoadProgress->StepProgress()) {
  326. return S_LOAD_CANCELED;
  327. }
  328. ++m_nLoadSteps;
  329. }
  330. if (!m_regkeySnmp.GetSubKey(SZ_REGKEY_EVENTLOG, m_regkeyEventLog)) {
  331. if (m_regkeySnmp.m_lResult == ERROR_ACCESS_DENIED) {
  332. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  333. sc = E_ACCESS_DENIED;
  334. }
  335. else {
  336. AfxMessageBox(IDS_WARNING_CANT_READ_CONFIG, MB_OK | MB_ICONSTOP);
  337. sc = E_REGKEY_NOT_FOUND;
  338. }
  339. m_regkeySnmp.Close();
  340. m_regkeySource.Close();
  341. return sc;
  342. }
  343. if (!bIsReconnecting) {
  344. if (m_pdlgLoadProgress->StepProgress()) {
  345. return S_LOAD_CANCELED;
  346. }
  347. ++m_nLoadSteps;
  348. }
  349. m_bNeedToCloseKeys = TRUE;
  350. sc = LockRegistry();
  351. if (FAILED(sc)) {
  352. if (sc == E_REGKEY_LOST_CONNECTION) {
  353. return sc;
  354. }
  355. else {
  356. return E_REGKEY_NO_CREATE;
  357. }
  358. }
  359. if (!bIsReconnecting) {
  360. if (m_pdlgLoadProgress->StepProgress()) {
  361. return S_LOAD_CANCELED;
  362. }
  363. ++m_nLoadSteps;
  364. }
  365. if (!bIsReconnecting) {
  366. if (m_pdlgLoadProgress->StepProgress()) {
  367. return S_LOAD_CANCELED;
  368. }
  369. ++m_nLoadSteps;
  370. }
  371. m_bShowConfigTypeBox = TRUE;
  372. if (FAILED(sc)) {
  373. if (sc == E_ACCESS_DENIED) {
  374. AfxMessageBox(IDS_ERR_REG_NO_ACCESS, MB_OK | MB_ICONSTOP);
  375. return E_ACCESS_DENIED;
  376. }
  377. else {
  378. goto CONNECT_FAILURE;
  379. }
  380. }
  381. if (!bIsReconnecting) {
  382. if (m_pdlgLoadProgress->StepProgress()) {
  383. return S_LOAD_CANCELED;
  384. }
  385. ++m_nLoadSteps;
  386. }
  387. return S_OK;
  388. CONNECT_FAILURE:
  389. CString sMessage;
  390. sMessage.LoadString(IDS_CANTCONNECT);
  391. if (pszComputerName != NULL) {
  392. sMessage += pszComputerName;
  393. }
  394. AfxMessageBox((LPCTSTR) sMessage, MB_OK | MB_ICONSTOP);
  395. return E_FAIL;
  396. }
  397. //****************************************************************************
  398. // CTrapReg::BuildSourceHasTrapsMap
  399. //
  400. // This method fills the m_mapEventSources CMapStringToPtr object with the
  401. // names of all the event sources that actually have events configured for them.
  402. // When this map is used later, we only need to know whether or not a particular
  403. // entry exists in the map, so the value associated with each entry is irrelevant.
  404. //
  405. // Why do we need m_mapEventSources? The reason is that we need a quick way to
  406. // determine whether or not a particular source has events configured for it.
  407. // This is used when all the event sources are being enumerated and we need to know
  408. // whether or not to load the messages for the event source (an expensive operation).
  409. // If a particular event source has events configured for it, then we need to load
  410. // the messages so that the message text can be displayed. This is because the
  411. // event configuration stored in the registry only contains the event id and not the
  412. // message text.
  413. //
  414. // Parameters:
  415. // None.
  416. //
  417. // Returns:
  418. // SCODE
  419. // S_OK if successful, otherwise E_FAIL.
  420. //
  421. //******************************************************************************
  422. SCODE CTrapReg::BuildSourceHasTrapsMap()
  423. {
  424. CRegistryKey regkey;
  425. if (!g_reg.m_regkeySnmp.GetSubKey(SZ_REGKEY_SOURCES, regkey)) {
  426. // For a fresh installation, there is no source subkey.
  427. if (g_bLostConnection) {
  428. return E_REGKEY_LOST_CONNECTION;
  429. }
  430. return S_OK;
  431. }
  432. CStringArray* pasEventSources = regkey.EnumSubKeys();
  433. regkey.Close();
  434. if (pasEventSources == NULL) {
  435. if (g_bLostConnection) {
  436. return E_REGKEY_LOST_CONNECTION;
  437. }
  438. return S_OK;
  439. }
  440. CString sEventSource;
  441. LONG nEventSources = (LONG)pasEventSources->GetSize();
  442. for (LONG iEventSource = 0; iEventSource < nEventSources; ++iEventSource) {
  443. sEventSource = pasEventSources->GetAt(iEventSource);
  444. sEventSource.MakeUpper();
  445. m_mapSourceHasTraps.SetAt(sEventSource, NULL);
  446. }
  447. delete pasEventSources;
  448. return S_OK;
  449. }
  450. //**************************************************************************
  451. // CTrapReg::Deserialize
  452. //
  453. // Read all the registry information (not including the event source messages) that
  454. // is required by eventrap.exe into this object. Reading the messages for most
  455. // event sources is delayed until the user actually requests it by selecting
  456. // an event source in the event source tree control. If an event source has
  457. // events that are being mapped into traps, then the messages for that event
  458. // source are loaded because an event description in the registry does not contain
  459. // the message text.
  460. //
  461. // Parameters:
  462. // None.
  463. //
  464. // Returns:
  465. // SCODE
  466. // S_OK if successful.
  467. // E_FAIL if a failure was detected. In the event of a failure, all
  468. // of the appropriate message boxes will have been displayed.
  469. //
  470. //***************************************************************************
  471. SCODE CTrapReg::Deserialize()
  472. {
  473. m_bSomeMessageWasNotFound = FALSE;
  474. SetDirty(FALSE);
  475. // Get the value for the configuration type.
  476. CRegistryValue regval;
  477. if (m_regkeyEventLog.GetValue(SZ_NAME_REGVAL_CONFIGTYPE, regval)) {
  478. m_dwConfigType = *(DWORD*)regval.m_pData;
  479. }
  480. else {
  481. if (g_bLostConnection) {
  482. AfxMessageBox(IDS_ERROR_NOT_RESPONDING);
  483. return E_REGKEY_LOST_CONNECTION;
  484. }
  485. // If the config type value doesn't exist, assume a custom configuration.
  486. // This can happen because the setup program doesn't necessarily create
  487. // this value.
  488. m_dwConfigType = CONFIG_TYPE_CUSTOM;
  489. }
  490. if (m_pdlgLoadProgress->StepProgress()) {
  491. return S_LOAD_CANCELED;
  492. }
  493. ++m_nLoadSteps;
  494. SCODE sc = BuildSourceHasTrapsMap();
  495. if (SUCCEEDED(sc)) {
  496. if (m_pdlgLoadProgress->StepProgress()) {
  497. return S_LOAD_CANCELED;
  498. }
  499. ++m_nLoadSteps;
  500. // Load the event log list, the current event list and so on.
  501. sc = m_params.Deserialize();
  502. if (sc == S_LOAD_CANCELED) {
  503. return sc;
  504. }
  505. if (SUCCEEDED(sc)) {
  506. if (m_pdlgLoadProgress->StepProgress()) {
  507. return S_LOAD_CANCELED;
  508. }
  509. ++m_nLoadSteps;
  510. sc = m_aEventLogs.Deserialize();
  511. if (sc == S_LOAD_CANCELED) {
  512. return sc;
  513. }
  514. if (SUCCEEDED(sc)) {
  515. if (m_nLoadSteps < LOAD_STEP_COUNT) {
  516. if (m_pdlgLoadProgress->StepProgress(LOAD_STEP_COUNT - m_nLoadSteps)) {
  517. return S_LOAD_CANCELED;
  518. }
  519. }
  520. }
  521. }
  522. }
  523. if (FAILED(sc)) {
  524. if (sc == E_REGKEY_LOST_CONNECTION) {
  525. AfxMessageBox(IDS_ERROR_NOT_RESPONDING);
  526. }
  527. else {
  528. AfxMessageBox(IDS_WARNING_CANT_READ_CONFIG);
  529. }
  530. }
  531. return sc;
  532. }
  533. //**************************************************************************
  534. // CTrapReg::GetSaveProgressStepCount
  535. //
  536. // Get the number of steps for the save progress dialog. The number of steps
  537. // is the number of events that will be written to SNMP_EVENTS\EventLog in
  538. // the registry.
  539. //
  540. // Parameters:
  541. // None.
  542. //
  543. // Returns:
  544. // The number of steps to use for the save progress dialog.
  545. //
  546. //*************************************************************************
  547. LONG CTrapReg::GetSaveProgressStepCount()
  548. {
  549. LONG nSteps = 0;
  550. LONG nEventLogs = m_aEventLogs.GetSize();
  551. for (LONG iEventLog = 0; iEventLog < nEventLogs; ++iEventLog) {
  552. CXEventLog* pEventLog = m_aEventLogs[iEventLog];
  553. LONG nEventSources = pEventLog->m_aEventSources.GetSize();
  554. for (LONG iEventSource = 0; iEventSource < nEventSources; ++iEventSource) {
  555. CXEventSource* pEventSource = pEventLog->m_aEventSources.GetAt(iEventSource);
  556. nSteps += pEventSource->m_aEvents.GetSize();
  557. }
  558. }
  559. return nSteps;
  560. }
  561. //**************************************************************************
  562. // CTrapReg::Serialize
  563. //
  564. // Write eventrap's current configuration out to the registry.
  565. //
  566. // Parameters:
  567. // None.
  568. //
  569. // Returns:
  570. // SCODE
  571. // S_OK if successful.
  572. // E_FAIL if a failure was detected. In the event of a failure, all
  573. // of the appropriate message boxes will have been displayed.
  574. //
  575. //***************************************************************************
  576. SCODE CTrapReg::Serialize()
  577. {
  578. SCODE sc;
  579. if (g_bLostConnection) {
  580. sc = Connect(m_sComputerName, TRUE);
  581. if (FAILED(sc)) {
  582. if (g_bLostConnection) {
  583. AfxMessageBox(IDS_ERROR_NOT_RESPONDING);
  584. return E_REGKEY_LOST_CONNECTION;
  585. }
  586. return S_SAVE_CANCELED;
  587. }
  588. }
  589. if (!m_bIsDirty) {
  590. // The configuration state was not changed, so there is nothing to do.
  591. return S_OK;
  592. }
  593. LONG nProgressSteps = GetSaveProgressStepCount();
  594. if (nProgressSteps > 0) {
  595. m_pdlgSaveProgress = new CDlgSaveProgress;
  596. m_pdlgSaveProgress->Create(IDD_SAVE_PROGRESS);
  597. m_pdlgSaveProgress->SetStepCount( nProgressSteps );
  598. }
  599. CRegistryValue regval;
  600. regval.Set(SZ_NAME_REGVAL_CONFIGTYPE, REG_DWORD, sizeof(DWORD), (LPBYTE)&m_dwConfigType);
  601. if (!m_regkeyEventLog.SetValue(regval)) {
  602. if (g_bLostConnection) {
  603. AfxMessageBox(IDS_ERROR_NOT_RESPONDING);
  604. sc = E_REGKEY_LOST_CONNECTION;
  605. }
  606. else {
  607. AfxMessageBox(IDS_WARNING_CANT_WRITE_CONFIG);
  608. sc = S_SAVE_CANCELED;
  609. }
  610. }
  611. else {
  612. sc = m_aEventLogs.Serialize();
  613. if (sc != S_SAVE_CANCELED) {
  614. if (SUCCEEDED(sc)) {
  615. sc = m_params.Serialize();
  616. }
  617. if (sc != S_SAVE_CANCELED)
  618. SetDirty(FALSE);
  619. if (FAILED(sc)) {
  620. if (g_bLostConnection) {
  621. AfxMessageBox(IDS_ERROR_NOT_RESPONDING);
  622. }
  623. else {
  624. AfxMessageBox(IDS_WARNING_CANT_WRITE_CONFIG);
  625. }
  626. }
  627. }
  628. }
  629. delete m_pdlgSaveProgress;
  630. m_pdlgSaveProgress = NULL;
  631. return sc;
  632. }
  633. void CTrapReg::SetDirty(BOOL bDirty)
  634. {
  635. m_bIsDirty = bDirty;
  636. if (m_pbtnApply)
  637. {
  638. m_pbtnApply->EnableWindow(m_bIsDirty);
  639. }
  640. }
  641. ///////////////////////////////////////////////////////////////////
  642. ///////////////////////////////////////////////////////////////////
  643. // Class: CTrapParams
  644. //
  645. // This class represents the information stored in the
  646. // SNMP_EVENTS\EventLog\Parameters registry key.
  647. //
  648. // Question: Why is it that the horizontal space in the gap between
  649. // the lines at the top of this header appears to be very irregular?
  650. //////////////////////////////////////////////////////////////////
  651. //****************************************************************
  652. // CTrapParams::CTrapParams
  653. //
  654. // Constructor for CTrapParams.
  655. //
  656. //
  657. // Parameters:
  658. // None.
  659. //
  660. // Returns:
  661. // Nothing.
  662. //
  663. //****************************************************************
  664. CTrapParams::CTrapParams()
  665. {
  666. m_trapsize.m_bTrimFlag = TRUE;
  667. m_trapsize.m_dwMaxTrapSize = 4096;
  668. m_trapsize.m_bTrimMessages = FALSE;
  669. }
  670. //********************************************************************
  671. // CTrapParams::Deserialize
  672. //
  673. // Read the contents of this CTrapParams object from the registry.
  674. //
  675. // Parameters:
  676. // None.
  677. //
  678. // Returns:
  679. // SCODE
  680. // S_OK if successful.
  681. // E_FAIL if there was a problem reading the required information
  682. // from the registry.
  683. //********************************************************************
  684. SCODE CTrapParams::Deserialize()
  685. {
  686. CRegistryKey regkeyParams;
  687. if (!g_reg.m_regkeySnmp.GetSubKey(SZ_REGKEY_PARAMETERS, regkeyParams)) {
  688. if (g_bLostConnection) {
  689. return E_REGKEY_LOST_CONNECTION;
  690. }
  691. else {
  692. return E_REGKEY_NOT_FOUND;
  693. }
  694. }
  695. CRegistryValue regval;
  696. // !!!CR: There is no longer any reason to load the BASE OID
  697. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_BASE_ENTERPRISE_OID, regval))
  698. goto REGISTRY_FAILURE;
  699. m_sBaseEnterpriseOID = (LPCTSTR)regval.m_pData;
  700. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_TRIMFLAG, regval))
  701. m_trapsize.m_bTrimFlag = FALSE;
  702. else
  703. m_trapsize.m_bTrimFlag = (*(DWORD*)regval.m_pData == 1);
  704. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_MAXTRAP_SIZE, regval))
  705. m_trapsize.m_dwMaxTrapSize = MAX_TRAP_SIZE;
  706. else
  707. m_trapsize.m_dwMaxTrapSize = *(DWORD*)regval.m_pData;
  708. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_TRIM_MESSAGE, regval))
  709. m_trapsize.m_bTrimMessages = TRUE;
  710. else
  711. m_trapsize.m_bTrimMessages = (*(DWORD*)regval.m_pData) != 0;
  712. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_THRESHOLDENABLED, regval))
  713. m_throttle.m_bIsEnabled = TRUE;
  714. else
  715. m_throttle.m_bIsEnabled = (*(DWORD*)regval.m_pData) != THROTTLE_DISABLED;
  716. // Threshold trap count.
  717. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_THRESHOLDCOUNT, regval) ||
  718. *(DWORD*)regval.m_pData < 2)
  719. m_throttle.m_nTraps = THRESHOLD_COUNT;
  720. else
  721. m_throttle.m_nTraps = *(DWORD*)regval.m_pData;
  722. // Threshold time in seconds
  723. if (!regkeyParams.GetValue(SZ_REGKEY_PARAMS_THRESHOLDTIME, regval))
  724. m_throttle.m_nSeconds = THRESHOLD_TIME;
  725. else
  726. m_throttle.m_nSeconds = *(DWORD*)regval.m_pData;
  727. if (regkeyParams.Close() != ERROR_SUCCESS) {
  728. goto REGISTRY_FAILURE;
  729. }
  730. return S_OK;
  731. REGISTRY_FAILURE:
  732. if (g_bLostConnection) {
  733. return E_REGKEY_LOST_CONNECTION;
  734. }
  735. else {
  736. return E_FAIL;
  737. }
  738. }
  739. //****************************************************************
  740. // CTrapParams::Serialize
  741. //
  742. // Write SNMP_EVENTS\EventLog\Parameters information to the
  743. // registry.
  744. //
  745. // Parameters:
  746. // None.
  747. //
  748. // Returns:
  749. // S_OK if everything went OK.
  750. // E_REGKEY_NOT_FOUND if an expected registry key was missing.
  751. //*****************************************************************
  752. SCODE CTrapParams::Serialize()
  753. {
  754. if (g_bLostConnection) {
  755. return E_REGKEY_LOST_CONNECTION;
  756. }
  757. // Open the Parameters key.
  758. // Create simply opens the key if already present.
  759. CRegistryKey regkey;
  760. if (!g_reg.m_regkeySnmp.CreateSubKey(SZ_REGKEY_PARAMETERS, regkey)) {
  761. if (g_bLostConnection) {
  762. return E_REGKEY_LOST_CONNECTION;
  763. }
  764. else {
  765. return E_REGKEY_NOT_FOUND;
  766. }
  767. }
  768. CRegistryValue regval;
  769. // Save the Message Length and the TrimMessage.
  770. DWORD dwTrim;
  771. if (m_trapsize.m_bTrimFlag)
  772. dwTrim = 1;
  773. else
  774. dwTrim = 0;
  775. regval.Set(SZ_REGKEY_PARAMS_TRIMFLAG, REG_DWORD, sizeof(DWORD), (LPBYTE)&dwTrim);
  776. regkey.SetValue(regval);
  777. if (g_bLostConnection) {
  778. return E_REGKEY_LOST_CONNECTION;
  779. }
  780. if (m_trapsize.m_bTrimFlag)
  781. {
  782. // Save the maximum trap size
  783. regval.Set(SZ_REGKEY_PARAMS_MAXTRAP_SIZE, REG_DWORD, sizeof(DWORD), (LPBYTE)&m_trapsize.m_dwMaxTrapSize);
  784. regkey.SetValue(regval);
  785. if (g_bLostConnection) {
  786. return E_REGKEY_LOST_CONNECTION;
  787. }
  788. // Save the trim message length
  789. DWORD dwTrimMessages = m_trapsize.m_bTrimMessages;
  790. regval.Set(SZ_REGKEY_PARAMS_TRIM_MESSAGE, REG_DWORD, sizeof(DWORD), (LPBYTE)&dwTrimMessages);
  791. regkey.SetValue(regval);
  792. if (g_bLostConnection) {
  793. return E_REGKEY_LOST_CONNECTION;
  794. }
  795. }
  796. // Threshold enabled flag
  797. DWORD dwValue = (m_throttle.m_bIsEnabled ? THROTTLE_ENABLED : THROTTLE_DISABLED);
  798. regval.Set(SZ_REGKEY_PARAMS_THRESHOLDENABLED, REG_DWORD, sizeof(DWORD), (LPBYTE)&dwValue);
  799. regkey.SetValue(regval);
  800. if (g_bLostConnection) {
  801. return E_REGKEY_LOST_CONNECTION;
  802. }
  803. // If throttle is not enabled, do not write the ThresholdCount and ThresholdTime parameters
  804. if (m_throttle.m_bIsEnabled)
  805. {
  806. // Threshold trap count.
  807. regval.Set(SZ_REGKEY_PARAMS_THRESHOLDCOUNT, REG_DWORD, sizeof(DWORD), (LPBYTE)&m_throttle.m_nTraps);
  808. regkey.SetValue(regval);
  809. if (g_bLostConnection) {
  810. return E_REGKEY_LOST_CONNECTION;
  811. }
  812. // Threshold time in seconds
  813. regval.Set(SZ_REGKEY_PARAMS_THRESHOLDTIME, REG_DWORD, sizeof(DWORD), (LPBYTE)&m_throttle.m_nSeconds);
  814. regkey.SetValue(regval);
  815. if (g_bLostConnection) {
  816. return E_REGKEY_LOST_CONNECTION;
  817. }
  818. }
  819. regkey.Close();
  820. if (g_bLostConnection) {
  821. return E_REGKEY_LOST_CONNECTION;
  822. }
  823. return S_OK;
  824. }
  825. //*******************************************************************
  826. // CTrapParams::ResetExtensionAgent
  827. //
  828. // Reset the extension agent. This is done by setting the "Threshold"
  829. // parameter to zero in the registry. The extension agent monitors this
  830. // value and will reset itself when a zero is written there.
  831. //
  832. // The user may want to reset the extension agent if its throttle limit
  833. // has been tripped.
  834. //
  835. // Parameters:
  836. // None.
  837. //
  838. // Returns:
  839. // SCODE
  840. // S_OK if successful. E_FAIL if the extension agent could not
  841. // be reset. If a failure occurs, the appropriate message box
  842. // is displayed.
  843. //
  844. //*********************************************************************
  845. SCODE CTrapParams::ResetExtensionAgent()
  846. {
  847. CRegistryKey regkey;
  848. if (!g_reg.m_regkeySnmp.GetSubKey(SZ_REGKEY_PARAMETERS, regkey)) {
  849. return E_REGKEY_NOT_FOUND;
  850. }
  851. CRegistryValue regval;
  852. // Set the "Threshold" value under the Parameters key to zero to reset
  853. // the extension agent.
  854. DWORD dwValue = THROTTLE_RESET;
  855. SCODE sc = S_OK;
  856. regval.Set(SZ_REGKEY_PARAMS_THRESHOLD, REG_DWORD, sizeof(DWORD), (LPBYTE)&dwValue);
  857. if (!regkey.SetValue(regval)) {
  858. AfxMessageBox(IDS_WARNING_CANT_WRITE_CONFIG);
  859. sc = E_FAIL;
  860. }
  861. regkey.Close();
  862. return sc;
  863. }
  864. //***********************************************************************
  865. // CTrapParams::ThrottleIsTripped
  866. //
  867. // Check the registry to determine whether or not the extension agent
  868. // throttle was tripped.
  869. //
  870. // Parameters:
  871. // None.
  872. //
  873. // Returns:
  874. // TRUE if the extension agent's throttle was tripped, FALSE otherwise.
  875. //
  876. //************************************************************************
  877. BOOL CTrapParams::ThrottleIsTripped()
  878. {
  879. CRegistryKey regkey;
  880. if (!g_reg.m_regkeySnmp.GetSubKey(SZ_REGKEY_PARAMETERS, regkey)) {
  881. return FALSE;
  882. }
  883. CRegistryValue regval;
  884. // SNMP_EVENTS\Parameters\Threshold value
  885. BOOL bThrottleIsTripped = FALSE;
  886. if (regkey.GetValue(SZ_REGKEY_PARAMS_THRESHOLD, regval)) {
  887. if (*(DWORD*)regval.m_pData == THROTTLE_TRIPPED) {
  888. bThrottleIsTripped = TRUE;
  889. }
  890. }
  891. regkey.Close();
  892. return bThrottleIsTripped;
  893. }
  894. ///////////////////////////////////////////////////////////////////
  895. // Class: CXEventLogArray
  896. //
  897. // This class implements an array of CXEventLog objects.
  898. //
  899. //////////////////////////////////////////////////////////////////
  900. //****************************************************************
  901. // CXEventLogArray::Deserialize
  902. //
  903. // Examine the registry find all the event logs and load all the
  904. // relevent information for all the event logs into this array.
  905. //
  906. // Parameters:
  907. // None.
  908. //
  909. // Returns:
  910. // S_OK if successful.
  911. // E_FAIL if a failure was detected.
  912. //
  913. //****************************************************************
  914. SCODE CXEventLogArray::Deserialize()
  915. {
  916. if (g_bLostConnection) {
  917. return E_REGKEY_LOST_CONNECTION;
  918. }
  919. CStringArray* pasEventLogs = g_reg.m_regkeySource.EnumSubKeys();
  920. // Prefix bug 445192
  921. if (pasEventLogs == NULL)
  922. return E_FAIL;
  923. SCODE sc = S_OK;
  924. // Iterate through all the event log names and create each log.
  925. LONG nEventLogs = (LONG)pasEventLogs->GetSize();
  926. if (nEventLogs > 0) {
  927. g_reg.m_nLoadStepsPerLog = LOAD_LOG_ARRAY_STEP_COUNT / nEventLogs;
  928. }
  929. LONG nUnusedSteps = LOAD_LOG_ARRAY_STEP_COUNT - (nEventLogs * g_reg.m_nLoadStepsPerLog);
  930. for (LONG iEventLog=0; iEventLog < nEventLogs; ++iEventLog)
  931. {
  932. CString sEventLog = pasEventLogs->GetAt(iEventLog);
  933. CXEventLog* pEventLog = new CXEventLog(sEventLog);
  934. sc = pEventLog->Deserialize();
  935. if ((sc==S_LOAD_CANCELED) || FAILED(sc)) {
  936. delete pEventLog;
  937. break;
  938. }
  939. else if (sc == S_NO_SOURCES) {
  940. delete pEventLog;
  941. sc = S_OK;
  942. }
  943. else {
  944. Add(pEventLog);
  945. }
  946. }
  947. delete pasEventLogs;
  948. if (g_reg.m_pdlgLoadProgress->StepProgress(nUnusedSteps)) {
  949. sc = S_LOAD_CANCELED;
  950. }
  951. return sc;
  952. }
  953. //****************************************************************
  954. // CXEventLogArray::Serialize
  955. //
  956. // Write the current configuration of all the EventLogs out to the
  957. // registry. Only those logs and sources that actually have events
  958. // are written.
  959. //
  960. // Parameters:
  961. // None.
  962. //
  963. // Returns:
  964. // S_OK if successful.
  965. // E_FAIL if a failure was detected.
  966. //
  967. //****************************************************************
  968. SCODE CXEventLogArray::Serialize()
  969. {
  970. if (g_bLostConnection) {
  971. return E_REGKEY_LOST_CONNECTION;
  972. }
  973. // This is where the eventlog stuff should be cleaned up.
  974. CRegistryKey regkey;
  975. if (!g_reg.m_regkeySnmp.CreateSubKey(SZ_REGKEY_EVENTLOG, regkey)) {
  976. if (g_bLostConnection) {
  977. return E_REGKEY_LOST_CONNECTION;
  978. }
  979. else {
  980. return E_REGKEY_NOT_FOUND;
  981. }
  982. }
  983. regkey.Close();
  984. if (!g_reg.m_regkeySnmp.CreateSubKey(SZ_REGKEY_SOURCES, regkey)) {
  985. if (g_bLostConnection) {
  986. return E_REGKEY_LOST_CONNECTION;
  987. }
  988. else {
  989. return E_REGKEY_NOT_FOUND;
  990. }
  991. }
  992. // Delete the keys for the sources and events for which we no longer
  993. // trap. I'm going to be lazy and just delete them all.
  994. // !!!CR: It could potentially save a lot of time if this was made smarter
  995. // !!!CR: so that it only replaced items that had been deleted.
  996. LONG nEventSources, iEventSource;
  997. CStringArray* pasEventSources = regkey.EnumSubKeys();
  998. nEventSources = (LONG)pasEventSources->GetSize();
  999. for (iEventSource=0; iEventSource<nEventSources; iEventSource++)
  1000. {
  1001. CString sSource;
  1002. sSource = pasEventSources->GetAt(iEventSource);
  1003. regkey.DeleteSubKey(sSource);
  1004. }
  1005. delete pasEventSources;
  1006. SCODE sc = S_OK;
  1007. LONG nEventLogs = GetSize();
  1008. for (LONG iEventLog = 0; iEventLog < nEventLogs; ++iEventLog) {
  1009. sc = GetAt(iEventLog)->Serialize(regkey);
  1010. if (sc == S_SAVE_CANCELED) {
  1011. break;
  1012. }
  1013. else if (g_bLostConnection) {
  1014. sc = E_REGKEY_LOST_CONNECTION;
  1015. break;
  1016. }
  1017. }
  1018. regkey.Close();
  1019. return sc;
  1020. }
  1021. //****************************************************************
  1022. // CXEventLogArray::FindEventSource
  1023. //
  1024. // Given the name of an event log and the name of the event source
  1025. // within the event log, return a pointer to the requested CXEventSource.
  1026. //
  1027. // Parameters:
  1028. // CString& sLog
  1029. // The name of the event log.
  1030. //
  1031. // CString& sEventSource
  1032. // The name of the event source.
  1033. //
  1034. // Returns:
  1035. // CXEventSource*
  1036. // A pointer to the requested event source if it was found. NULL
  1037. // if no such event source exists.
  1038. //
  1039. //****************************************************************
  1040. CXEventSource* CXEventLogArray::FindEventSource(CString& sLog, CString& sEventSource)
  1041. {
  1042. LONG nLogs = GetSize();
  1043. for (LONG iLog = 0; iLog < nLogs; ++iLog) {
  1044. CXEventLog* pEventLog = GetAt(iLog);
  1045. if (pEventLog->m_sName.CompareNoCase(sLog) == 0) {
  1046. return pEventLog->FindEventSource(sEventSource);
  1047. }
  1048. }
  1049. return NULL;
  1050. }
  1051. ///////////////////////////////////////////////////////////////////
  1052. // Class: CXEventLog
  1053. //
  1054. // This class contains all the information for a particular event log.
  1055. //
  1056. //////////////////////////////////////////////////////////////////
  1057. //************************************************************************
  1058. // CXEventLog::Deserialize
  1059. //
  1060. // Load the contents of this EventLog object from the registry.
  1061. //
  1062. // Parameters:
  1063. // g_reg is a global parameter.
  1064. //
  1065. // Returns:
  1066. // SCODE
  1067. // S_OK or S_NO_SOURCES if successful. E_FAIL if there was
  1068. // a failure of any kind.
  1069. //
  1070. //************************************************************************
  1071. SCODE CXEventLog::Deserialize()
  1072. {
  1073. return m_aEventSources.Deserialize(this);
  1074. }
  1075. //************************************************************************
  1076. // CXEventLog::Serialize
  1077. //
  1078. // Write the current configuration for this log to the registry.
  1079. //
  1080. // Parameters:
  1081. // CRegistryKey& regkey
  1082. // This registry key points to SOFTWARE\Microsoft\SNMP_EVENTS\EventLog
  1083. //
  1084. // Returns:
  1085. // SCODE
  1086. // S_OK or S_SAVE_CANCELED if successful. E_FAIL for an error condition.
  1087. // a failure of any kind.
  1088. //
  1089. //************************************************************************
  1090. SCODE CXEventLog::Serialize(CRegistryKey& regkey)
  1091. {
  1092. return m_aEventSources.Serialize(regkey);
  1093. }
  1094. ///////////////////////////////////////////////////////////////////
  1095. // Class: CXEventSourceArray
  1096. //
  1097. // This class implements an array of CXEventSource pointers and
  1098. // related methods.
  1099. //
  1100. //////////////////////////////////////////////////////////////////
  1101. //*************************************************************************
  1102. // CXEventSourceArray::Deserialize
  1103. //
  1104. // Load all the information pertaining to the event sources associated with
  1105. // the given event log. This information is loaded from the registry.
  1106. //
  1107. // Parameters:
  1108. // CXEventLog* pEventLog
  1109. // Pointer to the event log. The sources associated with this
  1110. // event log are loaded into this object.
  1111. //
  1112. // Returns:
  1113. // SCODE
  1114. // S_OK or S_NO_SOURCES if successful. E_FAIL if there was
  1115. // a failure of any kind.
  1116. //*************************************************************************
  1117. SCODE CXEventSourceArray::Deserialize(CXEventLog* pEventLog)
  1118. {
  1119. // Get the registry entry for this log. This registry key will be
  1120. // used to enumerate the event sources for this log.
  1121. CRegistryKey regkey;
  1122. if (!g_reg.m_regkeySource.GetSubKey(pEventLog->m_sName, regkey)) {
  1123. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerLog)) {
  1124. return S_LOAD_CANCELED;
  1125. }
  1126. if (g_bLostConnection) {
  1127. return E_REGKEY_LOST_CONNECTION;
  1128. }
  1129. else {
  1130. return E_FAIL;
  1131. }
  1132. }
  1133. SCODE sc = S_OK;
  1134. // Enumerate the event sources for this log.
  1135. CStringArray* pasSources = regkey.EnumSubKeys();
  1136. if (pasSources == NULL) {
  1137. regkey.Close();
  1138. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerLog)) {
  1139. return S_LOAD_CANCELED;
  1140. }
  1141. if (g_bLostConnection) {
  1142. return E_REGKEY_LOST_CONNECTION;
  1143. }
  1144. else {
  1145. return E_FAIL;
  1146. }
  1147. }
  1148. // Iterate though all the event sources and add them as a sub-item
  1149. // under the log.
  1150. LONG nEventSources = (LONG)pasSources->GetSize();
  1151. LONG nScaledStepSize = 0;
  1152. g_reg.m_nLoadStepsPerSource = 0;
  1153. if (nEventSources > 0) {
  1154. nScaledStepSize = (g_reg.m_nLoadStepsPerLog * 1000) / nEventSources;
  1155. g_reg.m_nLoadStepsPerSource = g_reg.m_nLoadStepsPerLog / nEventSources;
  1156. }
  1157. LONG nLoadSteps = 0;
  1158. LONG nProgress = 0;
  1159. // Set the load progress step count. Since we don't know how many events are saved
  1160. // for each event source, we will assume some small number for LOAD_STEPS_FOR_SOURCE
  1161. // and divide the actual number of steps up as evenly as possible once we know the actual
  1162. // event count.
  1163. for (LONG iEventSource=0; iEventSource< nEventSources; ++iEventSource)
  1164. {
  1165. nProgress += nScaledStepSize;
  1166. g_reg.m_nLoadStepsPerSource = nProgress / 1000;
  1167. if (g_reg.m_nLoadStepsPerSource > 0) {
  1168. nProgress -= g_reg.m_nLoadStepsPerSource * 1000;
  1169. nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1170. }
  1171. CString sEventSource = pasSources->GetAt(iEventSource);
  1172. CXEventSource* pEventSource = new CXEventSource(pEventLog, sEventSource);
  1173. sc = pEventSource->Deserialize(regkey);
  1174. if ((sc==S_LOAD_CANCELED) || FAILED(sc)) {
  1175. delete pEventSource;
  1176. break;
  1177. }
  1178. else if (sc == S_NO_EVENTS) {
  1179. // If there are no events, then this is not a valid event source.
  1180. delete pEventSource;
  1181. sc = S_OK;
  1182. }
  1183. else {
  1184. Add(pEventSource);
  1185. }
  1186. }
  1187. delete pasSources;
  1188. if (SUCCEEDED(sc)) {
  1189. // We only close the registry key if we succeeded to avoid hanging if we loose
  1190. // a remote connection.
  1191. regkey.Close();
  1192. if (GetSize() == 0) {
  1193. sc = S_NO_SOURCES;
  1194. }
  1195. }
  1196. if (nLoadSteps < g_reg.m_nLoadStepsPerLog) {
  1197. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerLog - nLoadSteps)) {
  1198. return S_LOAD_CANCELED;
  1199. }
  1200. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerLog - nLoadSteps;
  1201. }
  1202. return sc;
  1203. }
  1204. //************************************************************************
  1205. // CXEventSourceArray::Serialize
  1206. //
  1207. // Write the current configuration for this event source array to the registry.
  1208. //
  1209. // Parameters:
  1210. // CRegistryKey& regkey
  1211. // This registry key points to SOFTWARE\Microsoft\SNMP_EVENTS\EventLog\Sources
  1212. //
  1213. // Returns:
  1214. // SCODE
  1215. // S_OK or S_SAVE_CANCELED if successful. E_FAIL for an error condition.
  1216. // a failure of any kind.
  1217. //
  1218. //************************************************************************
  1219. SCODE CXEventSourceArray::Serialize(CRegistryKey& regkey)
  1220. {
  1221. // Write the subkeys under SNMP_EVENTS\EventLog
  1222. SCODE sc = S_OK;
  1223. LONG nEventSources = GetSize();
  1224. for (LONG iEventSource = 0; iEventSource < nEventSources; ++iEventSource) {
  1225. SCODE scTemp = GetAt(iEventSource)->Serialize(regkey);
  1226. if (g_bLostConnection) {
  1227. sc = E_REGKEY_LOST_CONNECTION;
  1228. break;
  1229. }
  1230. if (FAILED(scTemp)) {
  1231. sc = E_FAIL;
  1232. break;
  1233. }
  1234. if (scTemp == S_SAVE_CANCELED) {
  1235. sc = S_SAVE_CANCELED;
  1236. break;
  1237. }
  1238. }
  1239. return sc;
  1240. }
  1241. //************************************************************************
  1242. // CXEventSourceArray::FindEventSource
  1243. //
  1244. // Given an event source name, find the specified event source in this
  1245. // event source array.
  1246. //
  1247. // Parameters:
  1248. // CString& sEventSource
  1249. // The name of the event source to search for.
  1250. //
  1251. // Returns:
  1252. // CXEventSource*
  1253. // Pointer to the event source if it is found, otherwise NULL.
  1254. //
  1255. //***********************************************************************
  1256. CXEventSource* CXEventSourceArray::FindEventSource(CString& sEventSource)
  1257. {
  1258. LONG nSources = GetSize();
  1259. for (LONG iSource = 0; iSource < nSources; ++iSource) {
  1260. CXEventSource* pEventSource = GetAt(iSource);
  1261. if (pEventSource->m_sName.CompareNoCase(sEventSource)==0) {
  1262. return pEventSource;
  1263. }
  1264. }
  1265. return NULL;
  1266. }
  1267. ///////////////////////////////////////////////////////////////////
  1268. // Class: CXEventSource
  1269. //
  1270. // This class implements an an event source object. An event source
  1271. // corresponds to an application that can generate events. The
  1272. // event sources are enumerated from the registry in
  1273. // "SYSTEM\CurrentControlSet\Services\EventLogs" under each particular
  1274. // eventlog found there.
  1275. //
  1276. // An event source has an array of messages and an array of events
  1277. // associated with it.
  1278. //
  1279. // The message array comes from the message .DLL file(s) pointed to by
  1280. // the "EventMessageFile" value attached to the source's key in the registry.
  1281. // The message array is read-only in the sense that it is loaded from the
  1282. // registry and never written back to it.
  1283. //
  1284. // The event array comes from SNMP_EVENTS\EventLog\<source-subkey>. These
  1285. // events are loaded when the configuration program starts up and written
  1286. // back out when the user clicks "OK". Note that the events stored in the
  1287. // registry contain the event ID, but not the message text. The message text
  1288. // for an event is found by searching the message array in the CXEventSource
  1289. // object for the event's ID.
  1290. //
  1291. //////////////////////////////////////////////////////////////////
  1292. //*************************************************************************
  1293. // CXEventSource::CXEventSource
  1294. //
  1295. // Construct the CXEventSource object.
  1296. //
  1297. // Parameters:
  1298. // CXEventLog* pEventLog
  1299. // Pointer to the event log that contains this event source.
  1300. //
  1301. // CString& sName
  1302. // The name of this event source.
  1303. //
  1304. // Returns:
  1305. // Nothing.
  1306. //
  1307. //*************************************************************************
  1308. CXEventSource::CXEventSource(CXEventLog* pEventLog, CString& sName)
  1309. {
  1310. m_pEventLog = pEventLog;
  1311. m_sName = sName;
  1312. m_aMessages.Initialize(this);
  1313. }
  1314. //************************************************************************
  1315. // CXEventSource::~CXEventSource
  1316. //
  1317. // Destroy thus event source object.
  1318. //
  1319. // Parameters:
  1320. // None.
  1321. //
  1322. // Returns:
  1323. // Nothing.
  1324. //
  1325. //************************************************************************
  1326. CXEventSource::~CXEventSource()
  1327. {
  1328. // We must explicitly delete the contents of the event array and message
  1329. // array. Note that this is different behavior from the CXEventLogArray
  1330. // and CXEventSourceArray. This is because it was useful to create
  1331. // message and event arrays as temporary containers for a set of pointers.
  1332. // Thus, there were situations where you did not want to delete the
  1333. // objects contained in these arrays when the arrays were destroyed.
  1334. m_aEvents.DeleteAll();
  1335. m_aMessages.DeleteAll();
  1336. }
  1337. //**********************************************************************
  1338. // CXEventSource::Deserialize
  1339. //
  1340. // Load this event source from the registry given the registry key
  1341. // for the event log that contains this source.
  1342. //
  1343. // Parameters:
  1344. // CRegistryKey& regkeyLog
  1345. // An open registry key for the event log containing this
  1346. // event source. This key points to somewhere in
  1347. // SYSTEM\CurrentControlSet\Services\EventLog
  1348. //
  1349. // Returns:
  1350. // SCODE
  1351. // S_OK = the source has events and no errors were encountered.
  1352. // S_NO_EVENTS = the source has no events and no errors were encountered.
  1353. // E_FAIL = an condition was encountered.
  1354. //
  1355. //***********************************************************************
  1356. SCODE CXEventSource::Deserialize(CRegistryKey& regkeyLog)
  1357. {
  1358. CRegistryKey regkeySource;
  1359. if (!regkeyLog.GetSubKey(m_sName, regkeySource)) {
  1360. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource)) {
  1361. return S_LOAD_CANCELED;
  1362. }
  1363. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1364. if (g_bLostConnection) {
  1365. return E_REGKEY_LOST_CONNECTION;
  1366. }
  1367. else {
  1368. return E_FAIL;
  1369. }
  1370. }
  1371. SCODE sc = E_FAIL;
  1372. if (SUCCEEDED(GetLibPath(regkeySource))) {
  1373. sc = m_aEvents.Deserialize(this);
  1374. }
  1375. else {
  1376. if (g_bLostConnection) {
  1377. return E_REGKEY_LOST_CONNECTION;
  1378. }
  1379. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource)) {
  1380. return S_LOAD_CANCELED;
  1381. }
  1382. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1383. sc = S_NO_EVENTS;
  1384. }
  1385. regkeySource.Close();
  1386. if (g_bLostConnection) {
  1387. return E_REGKEY_LOST_CONNECTION;
  1388. }
  1389. // Delay deserializing the messages for this source until they are
  1390. // needed.
  1391. return sc;
  1392. }
  1393. #if 0
  1394. //*************************************************************************
  1395. // CXEventSource::GetLibPath
  1396. //
  1397. // Get the path the the EventMessageFile for this event source.
  1398. //
  1399. // Parameters:
  1400. // CRegistryKey& regkeySource
  1401. // An open registry key corresponding to this source in
  1402. // SYSTEM\CurrentControlSet\Services\EventLog\<event log>
  1403. //
  1404. // Returns:
  1405. // SCODE
  1406. // S_OK if successful, otherwise E_FAIL.
  1407. //
  1408. //*************************************************************************
  1409. SCODE CXEventSource::GetLibPath(CRegistryKey& regkeySource)
  1410. {
  1411. CRegistryValue regval;
  1412. if (!regkeySource.GetValue(SZ_REGKEY_SOURCE_EVENT_MESSAGE_FILE, regval))
  1413. return E_FAIL;
  1414. TCHAR szLibPath[MAX_STRING];
  1415. if (ExpandEnvironmentStrings((LPCTSTR)regval.m_pData, szLibPath, sizeof(szLibPath)) == 0)
  1416. return E_FAIL;
  1417. m_sLibPath = szLibPath;
  1418. return S_OK;
  1419. }
  1420. #else
  1421. //*************************************************************************
  1422. // CXEventSource::GetLibPath
  1423. //
  1424. // Get the path the the EventMessageFile for this event source.
  1425. //
  1426. // Parameters:
  1427. // CRegistryKey& regkeySource
  1428. // An open registry key corresponding to this source in
  1429. // SYSTEM\CurrentControlSet\Services\EventLog\<event log>
  1430. //
  1431. // Returns:
  1432. // SCODE
  1433. // S_OK if successful, otherwise E_FAIL.
  1434. //
  1435. //*************************************************************************
  1436. SCODE CXEventSource::GetLibPath(CRegistryKey& regkeySource)
  1437. {
  1438. static CEnvCache cache;
  1439. CRegistryValue regval;
  1440. if (!regkeySource.GetValue(SZ_REGKEY_SOURCE_EVENT_MESSAGE_FILE, regval))
  1441. return E_FAIL;
  1442. SCODE sc = S_OK;
  1443. if (g_reg.m_sComputerName.IsEmpty()) {
  1444. // Editing the local computer computer's registry, so the local environment
  1445. // variables are in effect.
  1446. TCHAR szLibPath[MAX_STRING];
  1447. if (ExpandEnvironmentStrings((LPCTSTR)regval.m_pData, szLibPath, sizeof(szLibPath)/sizeof(szLibPath[0]))) {
  1448. m_sLibPath = szLibPath;
  1449. }
  1450. else {
  1451. sc = E_FAIL;
  1452. }
  1453. }
  1454. else {
  1455. // Editing a remote computer's registry, so the remote environment strings are in
  1456. // effect. Also, file paths must be mapped to the UNC path for the machine. For
  1457. // example, C:Foo will be mapped to \\Machine\C$\Foo
  1458. m_sLibPath = regval.m_pData;
  1459. sc = RemoteExpandEnvStrings(g_reg.m_sComputerName, cache, m_sLibPath);
  1460. if (SUCCEEDED(sc)) {
  1461. sc = MapPathToUNC(g_reg.m_sComputerName, m_sLibPath);
  1462. }
  1463. }
  1464. return S_OK;
  1465. }
  1466. #endif
  1467. //************************************************************************
  1468. // CXEventSource::Serialize
  1469. //
  1470. // Write the configuration information for this event source to the registry.
  1471. //
  1472. // Parameters:
  1473. // CRegistryKey& regkeyParent
  1474. // An open registry key pointing to SNMP_EVENTS\EventLog\Sources
  1475. //
  1476. // Returns:
  1477. // SCODE
  1478. // S_OK if successful.
  1479. // S_SAVE_CANCELED if no errors, but the user canceled the save.
  1480. //
  1481. //************************************************************************
  1482. SCODE CXEventSource::Serialize(CRegistryKey& regkeyParent)
  1483. {
  1484. if (g_bLostConnection) {
  1485. return E_REGKEY_LOST_CONNECTION;
  1486. }
  1487. SCODE sc = S_OK;
  1488. if (m_aEvents.GetSize() > 0) {
  1489. CRegistryKey regkey;
  1490. if (!regkeyParent.CreateSubKey(m_sName, regkey)) {
  1491. if (g_bLostConnection) {
  1492. return E_REGKEY_LOST_CONNECTION;
  1493. }
  1494. else {
  1495. return E_REGKEY_NOT_FOUND;
  1496. }
  1497. }
  1498. CString sEnterpriseOID;
  1499. GetEnterpriseOID(sEnterpriseOID);
  1500. CRegistryValue regval;
  1501. regval.Set(SZ_REGKEY_SOURCE_ENTERPRISE_OID,
  1502. REG_SZ, (sEnterpriseOID.GetLength() + 1) * sizeof(TCHAR),
  1503. (LPBYTE)(LPCTSTR)sEnterpriseOID);
  1504. regkey.SetValue(regval);
  1505. DWORD dwAppend = 1;
  1506. regval.Set(SZ_REGKEY_SOURCE_APPEND, REG_DWORD, sizeof(DWORD), (LPBYTE) &dwAppend);
  1507. regkey.SetValue(regval);
  1508. sc = m_aEvents.Serialize(regkey);
  1509. regkey.Close();
  1510. }
  1511. if (g_bLostConnection) {
  1512. return E_REGKEY_LOST_CONNECTION;
  1513. }
  1514. return sc;
  1515. }
  1516. //*******************************************************************
  1517. // CXEventSource::GetEnterpriseOID
  1518. //
  1519. // Get the enterprise OID for this event source. The enterprise OID
  1520. // is composed of a prefix and suffix string concatenated together. The
  1521. // prefix string is an ASCII decimal value for the length of the suffix
  1522. // string. The suffix string is composed by separating each character of
  1523. // the name of this source by a "." character.
  1524. //
  1525. // Parameters:
  1526. // CString& sEnterpriseOID
  1527. // A reference to the string where the enterprise OID for this
  1528. // source will be returned.
  1529. //
  1530. // Returns:
  1531. // The enterprise OID in via the sEnterpriseOID reference.
  1532. //
  1533. //********************************************************************
  1534. void CXEventSource::GetEnterpriseOID(CString& sEnterpriseOID, BOOL bGetFullID)
  1535. {
  1536. CString sValue;
  1537. // Form the prefix string in sEnterpriseOID and compute the length
  1538. // of the prefix and suffix strings.
  1539. DecString(sValue, m_sName.GetLength());
  1540. if (bGetFullID) {
  1541. sEnterpriseOID = g_reg.m_params.m_sBaseEnterpriseOID + _T('.') + sValue;
  1542. }
  1543. else {
  1544. sEnterpriseOID = sValue;
  1545. }
  1546. // Append the suffix string to the prefix string by getting a pointer to
  1547. // the sEnterpriseOID buffer and allocating enough space to hold the
  1548. // combined strings.
  1549. LPCTSTR pszSrc = m_sName;
  1550. // Append the suffix by copying it to the destination buffer and inserting the
  1551. // "." separator characters as we go.
  1552. LONG iCh;
  1553. while (iCh = *pszSrc++) {
  1554. switch(sizeof(TCHAR)) {
  1555. case 1:
  1556. iCh &= 0x0ff;
  1557. break;
  1558. case 2:
  1559. iCh &= 0x0ffffL;
  1560. break;
  1561. default:
  1562. ASSERT(FALSE);
  1563. break;
  1564. }
  1565. DecString(sValue, iCh);
  1566. sEnterpriseOID += _T('.');
  1567. sEnterpriseOID += sValue;
  1568. }
  1569. }
  1570. ///////////////////////////////////////////////////////////////////
  1571. // Class: CXEventArray
  1572. //
  1573. // This class implements an array of pointers to CXEvent objects.
  1574. // The events contained in this array correspond to the events that
  1575. // the user has configured in the main dialog. Don't confuse events
  1576. // with messages. Events are the subset of the messages that the
  1577. // user has selected to be translated into traps.
  1578. //
  1579. // For further information on how this CXEventArray fits into the
  1580. // scheme of things, please see the CXEventSource class header.
  1581. //////////////////////////////////////////////////////////////////
  1582. //************************************************************************
  1583. // CXEventArray::Deserialize
  1584. //
  1585. // Read an array of events from the registry for the given
  1586. // source.
  1587. //
  1588. // Parameters:
  1589. // CXEventSource* pEventSource
  1590. // Pointer to the event source who's events should be read.
  1591. //
  1592. // Returns:
  1593. // SCODE
  1594. // S_OK if successful.
  1595. // E_FAIL if an error occurs.
  1596. //
  1597. //************************************************************************
  1598. SCODE CXEventArray::Deserialize(CXEventSource* pEventSource)
  1599. {
  1600. if (!g_reg.SourceHasTraps(pEventSource->m_sName)) {
  1601. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource)) {
  1602. return S_LOAD_CANCELED;
  1603. }
  1604. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1605. return S_OK;
  1606. }
  1607. // Control comes here if we know that there are events configured
  1608. // for the event source that this event array is part of. We now
  1609. // need to load the events for this source by enumerating them
  1610. // from SNMP_EVENTS\EventLog\<event source>
  1611. CString sKey;
  1612. sKey = sKey + SZ_REGKEY_SOURCES + _T("\\") + pEventSource->m_sName;
  1613. CRegistryKey regkey;
  1614. if (!g_reg.m_regkeySnmp.GetSubKey(sKey, regkey)) {
  1615. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource)) {
  1616. return S_LOAD_CANCELED;
  1617. }
  1618. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1619. return S_OK;
  1620. }
  1621. // Enumerate the events for this source
  1622. CStringArray* pasEvents = regkey.EnumSubKeys();
  1623. if (pasEvents == NULL) {
  1624. if (g_bLostConnection) {
  1625. return E_REGKEY_LOST_CONNECTION;
  1626. }
  1627. regkey.Close();
  1628. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource)) {
  1629. return S_LOAD_CANCELED;
  1630. }
  1631. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource;
  1632. return E_FAIL;
  1633. }
  1634. // Iterate though all the events and add them as a sub-item
  1635. // under the event source.
  1636. LONG nEvents = (LONG)pasEvents->GetSize();
  1637. LONG nStepsDone = 0;
  1638. LONG nEventsPerStep = 0;
  1639. if (g_reg.m_nLoadStepsPerSource > 0) {
  1640. nEventsPerStep = nEvents / g_reg.m_nLoadStepsPerSource;
  1641. }
  1642. for (LONG iEvent=0; iEvent< nEvents; ++iEvent)
  1643. {
  1644. CString sEvent = pasEvents->GetAt(iEvent);
  1645. CXEvent* pEvent = new CXEvent(pEventSource);
  1646. SCODE sc = pEvent->Deserialize(regkey, sEvent);
  1647. if (sc == E_MESSAGE_NOT_FOUND) {
  1648. delete pEvent;
  1649. if (!g_reg.m_bSomeMessageWasNotFound) {
  1650. AfxMessageBox(IDS_ERR_MESSAGE_NOT_FOUND, MB_OK | MB_ICONEXCLAMATION);
  1651. g_reg.m_bSomeMessageWasNotFound = TRUE;
  1652. g_reg.SetDirty(TRUE);
  1653. }
  1654. continue;
  1655. }
  1656. if ((sc == S_LOAD_CANCELED) || FAILED(sc) ) {
  1657. delete pEvent;
  1658. delete pasEvents;
  1659. return sc;
  1660. }
  1661. if (nEventsPerStep > 0) {
  1662. if ((iEvent % nEventsPerStep) == (nEventsPerStep - 1)) {
  1663. if (g_reg.m_pdlgLoadProgress->StepProgress()) {
  1664. delete pasEvents;
  1665. return S_LOAD_CANCELED;
  1666. }
  1667. ++g_reg.m_nLoadSteps;
  1668. ++nStepsDone;
  1669. }
  1670. }
  1671. }
  1672. delete pasEvents;
  1673. regkey.Close();
  1674. if (nStepsDone < g_reg.m_nLoadStepsPerSource) {
  1675. if (g_reg.m_pdlgLoadProgress->StepProgress(g_reg.m_nLoadStepsPerSource - nStepsDone)) {
  1676. return S_LOAD_CANCELED;
  1677. }
  1678. g_reg.m_nLoadSteps += g_reg.m_nLoadStepsPerSource - nStepsDone;
  1679. }
  1680. return S_OK;
  1681. }
  1682. //************************************************************************
  1683. // CXEventArray::Serialize
  1684. //
  1685. // Write the current configuration for the events contained in this array
  1686. // out to the registry.
  1687. //
  1688. // Parameters:
  1689. // CRegistryKey& regkeyParent
  1690. // An open registry key for the source that owns these events.
  1691. // The source key is located in SNMP_EVENTS\EventLogs\<source-key>
  1692. //
  1693. // Returns:
  1694. // SCODE
  1695. // S_OK = All events saved without errors.
  1696. // S_SAVE_CANCELED = No errors, but the user canceled the save.
  1697. // E_FAIL = An error occurs.
  1698. //
  1699. //************************************************************************
  1700. SCODE CXEventArray::Serialize(CRegistryKey& regkeyParent)
  1701. {
  1702. SCODE sc = S_OK;
  1703. LONG nEvents = GetSize();
  1704. for (LONG iEvent = 0; iEvent < nEvents; ++iEvent) {
  1705. SCODE scTemp = GetAt(iEvent)->Serialize(regkeyParent);
  1706. if (scTemp == S_SAVE_CANCELED) {
  1707. sc = S_SAVE_CANCELED;
  1708. break;
  1709. }
  1710. if (FAILED(scTemp)) {
  1711. if (g_bLostConnection) {
  1712. sc = E_REGKEY_LOST_CONNECTION;
  1713. }
  1714. else {
  1715. sc = E_FAIL;
  1716. }
  1717. break;
  1718. }
  1719. }
  1720. return sc;
  1721. }
  1722. //***********************************************************************
  1723. // CXEventArray::Add
  1724. //
  1725. // Add an event pointer to this array. Note that there is no assumption
  1726. // that the array owns the pointer. Someone must explicitly call the DeleteAll
  1727. // member to delete the pointers stored in this array.
  1728. //
  1729. // Parameters:
  1730. // CXEvent* pEvent
  1731. // Pointer to the event to add to this array.
  1732. //
  1733. // Returns:
  1734. // Nothing.
  1735. //
  1736. //***********************************************************************
  1737. void CXEventArray::Add(CXEvent* pEvent)
  1738. {
  1739. CBaseArray::Add(pEvent);
  1740. }
  1741. //***********************************************************************
  1742. // CXEventArray::FindEvent
  1743. //
  1744. // Given an event id, find the corresponding event in this array.
  1745. //
  1746. // Note that this array should never contain duplicate events.
  1747. //
  1748. // Parameters:
  1749. // DWORD dwId
  1750. // The event ID.
  1751. //
  1752. // Returns:
  1753. // CXEvent*
  1754. // A pointer to the desired event. NULL if the event was
  1755. // not found.
  1756. //
  1757. //***********************************************************************
  1758. CXEvent* CXEventArray::FindEvent(DWORD dwId)
  1759. {
  1760. LONG nEvents = GetSize();
  1761. for (LONG iEvent=0; iEvent < nEvents; ++iEvent) {
  1762. CXEvent* pEvent = GetAt(iEvent);
  1763. if (pEvent->m_message.m_dwId == dwId) {
  1764. return pEvent;
  1765. }
  1766. }
  1767. return NULL;
  1768. }
  1769. //***********************************************************************
  1770. // CXEventArray::FindEvent
  1771. //
  1772. // Given an event pointer, remove the event from this array.
  1773. //
  1774. // Parameters:
  1775. // CXEvent* pEventRemove
  1776. // A pointer to the event to remove.
  1777. //
  1778. // Returns:
  1779. // SCODE
  1780. // S_OK if the event was removed.
  1781. // E_FAIL if the event was not found in this array.
  1782. //
  1783. //***********************************************************************
  1784. SCODE CXEventArray::RemoveEvent(CXEvent* pEventRemove)
  1785. {
  1786. // Iterate through the event array to search for the specified event.
  1787. LONG nEvents = GetSize();
  1788. for (LONG iEvent=0; iEvent < nEvents; ++iEvent) {
  1789. CXEvent* pEvent = GetAt(iEvent);
  1790. if (pEvent == pEventRemove) {
  1791. RemoveAt(iEvent);
  1792. return S_OK;
  1793. }
  1794. }
  1795. return E_FAIL;
  1796. }
  1797. ///////////////////////////////////////////////////////////////////
  1798. // Class: CXEvent
  1799. //
  1800. // This class implements an event. Events are the subset of the
  1801. // messages that the user selects to be translated into traps.
  1802. // Events, and not messages, are what the user configures.
  1803. //
  1804. // For further information on how this class fits into the
  1805. // scheme of things, please see the CXEventSource class header.
  1806. //////////////////////////////////////////////////////////////////
  1807. //*********************************************************************
  1808. // CXEvent::CXEvent
  1809. //
  1810. // Construct the event.
  1811. //
  1812. // Parameters:
  1813. // CXEventSource* pEventSource
  1814. // Pointer to the event source that has the potential to generate
  1815. // this event.
  1816. //
  1817. // Returns:
  1818. // Nothing.
  1819. //
  1820. //*********************************************************************
  1821. CXEvent::CXEvent(CXEventSource* pEventSource) : m_message(pEventSource)
  1822. {
  1823. m_dwCount = 0;
  1824. m_dwTimeInterval = 0;
  1825. m_pEventSource = pEventSource;
  1826. m_pEventSource->m_aEvents.Add(this);
  1827. }
  1828. //**********************************************************************
  1829. // CXEvent::CXEvent
  1830. //
  1831. // Construct an event. This form of the constructor creates an event
  1832. // directly from a CXMessage object. This is possible because the
  1833. // CXMessage object contains a back-pointer to its source.
  1834. //
  1835. // Parameters:
  1836. // CXMessage* pMessage
  1837. // Pointer to the message that is used as the event template.
  1838. //
  1839. // Returns:
  1840. // Nothing.
  1841. //**********************************************************************
  1842. CXEvent::CXEvent(CXMessage* pMessage) : m_message(pMessage->m_pEventSource)
  1843. {
  1844. m_pEventSource = pMessage->m_pEventSource;
  1845. m_message = *pMessage;
  1846. m_dwCount = 0;
  1847. m_dwTimeInterval = 0;
  1848. m_pEventSource->m_aEvents.Add(this);
  1849. }
  1850. //**********************************************************************
  1851. // CXEvent::~CXEvent
  1852. //
  1853. // Destroy this event.
  1854. //
  1855. // Parameters:
  1856. // None.
  1857. //
  1858. // Returns:
  1859. // Nothing.
  1860. //**********************************************************************
  1861. CXEvent::~CXEvent()
  1862. {
  1863. // Remove this event from the source
  1864. m_pEventSource->m_aEvents.RemoveEvent(this);
  1865. }
  1866. //**********************************************************************
  1867. // CXEvent::Deserialize
  1868. //
  1869. // Read this event from the registry.
  1870. //
  1871. // Parameters:
  1872. // CRegistryKey& regkeyParent
  1873. // An open registry key pointing to the event source in
  1874. // SNMP_EVENTS\EventLog
  1875. //
  1876. // CString& sName
  1877. // The name of the event to load.
  1878. //
  1879. // Returns:
  1880. // SCODE
  1881. // S_OK if successful.
  1882. // E_FAIL if an error occurred.
  1883. //
  1884. //*********************************************************************
  1885. SCODE CXEvent::Deserialize(CRegistryKey& regkeyParent, CString& sName)
  1886. {
  1887. CRegistryKey regkey;
  1888. if (!regkeyParent.GetSubKey(sName, regkey)) {
  1889. return E_FAIL;
  1890. }
  1891. SCODE sc = E_FAIL;
  1892. CRegistryValue regval;
  1893. // Get the count and time interval.
  1894. m_dwCount = 0;
  1895. m_dwTimeInterval = 0;
  1896. if (regkey.GetValue(SZ_REGKEY_EVENT_COUNT, regval)) {
  1897. m_dwCount = *(DWORD*)regval.m_pData;
  1898. if (regkey.GetValue(SZ_REGKEY_EVENT_TIME, regval)) {
  1899. m_dwTimeInterval = *(DWORD*)regval.m_pData;
  1900. }
  1901. }
  1902. if (regkey.GetValue(SZ_REGKEY_EVENT_FULLID, regval)) {
  1903. DWORD dwFullId = *(DWORD*)regval.m_pData;
  1904. CXMessage* pMessage = m_pEventSource->FindMessage(dwFullId);
  1905. if (pMessage == NULL) {
  1906. sc = E_MESSAGE_NOT_FOUND;
  1907. }
  1908. else {
  1909. m_message = *pMessage;
  1910. sc = S_OK;
  1911. }
  1912. }
  1913. regkey.Close();
  1914. return sc;
  1915. }
  1916. //**********************************************************************
  1917. // CXEvent::Deserialize
  1918. //
  1919. // Write the configuration for this event to the registry.
  1920. //
  1921. // Parameters:
  1922. // CRegistryKey& regkeyParent
  1923. // An open registry key pointing to the event source in
  1924. // SNMP_EVENTS\EventLog
  1925. //
  1926. // Returns:
  1927. // SCODE
  1928. // S_OK = the event was successful written out.
  1929. // S_SAVE_CANCELED = no errors, but the user canceled the save.
  1930. // E_FAIL = if an error occurred.
  1931. //
  1932. //*********************************************************************
  1933. SCODE CXEvent::Serialize(CRegistryKey& regkeyParent)
  1934. {
  1935. if (g_reg.m_pdlgSaveProgress) {
  1936. if (g_reg.m_pdlgSaveProgress->StepProgress()) {
  1937. return S_SAVE_CANCELED;
  1938. }
  1939. }
  1940. CRegistryKey regkey;
  1941. CString sName;
  1942. GetName(sName);
  1943. if (!regkeyParent.CreateSubKey(sName, regkey)) {
  1944. return E_REGKEY_NO_CREATE;
  1945. }
  1946. CRegistryValue regval;
  1947. if (m_dwCount > 0) {
  1948. regval.Set(SZ_REGKEY_EVENT_COUNT, REG_DWORD, sizeof(DWORD), (LPBYTE) &m_dwCount);
  1949. regkey.SetValue(regval);
  1950. if (m_dwTimeInterval > 0) {
  1951. regval.Set(SZ_REGKEY_EVENT_TIME, REG_DWORD, sizeof(DWORD), (LPBYTE) &m_dwTimeInterval);
  1952. regkey.SetValue(regval);
  1953. }
  1954. }
  1955. regval.Set(SZ_REGKEY_EVENT_FULLID, REG_DWORD, sizeof(DWORD), (LPBYTE) &m_message.m_dwId);
  1956. regkey.SetValue(regval);
  1957. regkey.Close();
  1958. return S_OK;
  1959. }
  1960. //*************************************************************************
  1961. // CXEvent::GetCount
  1962. //
  1963. // Get the ASCII decimal value for the m_dwCount member.
  1964. //
  1965. // Using this method to do the conversion ensures that the count value is
  1966. // presented to the user in a consistent form throughout the program.
  1967. //
  1968. // Parameters:
  1969. // CString& sText
  1970. // This is where the count value is returned.
  1971. //
  1972. // Returns:
  1973. // The ASCII value for the count is returned via sText.
  1974. //
  1975. // Note: m_dwCount and m_dwTimeInterval work together. A trap is sent only if
  1976. // m_dwCount events are registered withing m_dwTimeInterval seconds.
  1977. //*************************************************************************
  1978. void CXEvent::GetCount(CString& sText)
  1979. {
  1980. DecString(sText, (long) m_dwCount);
  1981. }
  1982. //*************************************************************************
  1983. // CXEvent::GetTimeInterval
  1984. //
  1985. // Get the ASCII decimal value for the m_dwTimeInterval member.
  1986. //
  1987. // Using this method to do the conversion ensures that the time-interval value is
  1988. // presented to the user in a consistent form throughout the program.
  1989. //
  1990. // Parameters:
  1991. // CString& sText
  1992. // This is where the count value is returned.
  1993. //
  1994. // Returns:
  1995. // The ASCII value for the count is returned via sText.
  1996. //
  1997. // Note: m_dwCount and m_dwTimeInterval work together. A trap is sent only if
  1998. // m_dwCount events are registered withing m_dwTimeInterval seconds.
  1999. //*************************************************************************
  2000. void CXEvent::GetTimeInterval(CString& sText)
  2001. {
  2002. DecString(sText, (long) m_dwTimeInterval);
  2003. }
  2004. ///////////////////////////////////////////////////////////////////
  2005. // Class: CXMessage
  2006. //
  2007. // This class implements a message. Each event source has some
  2008. // number of messages associated with it. A user may select some
  2009. // subset of the messages to be converted into "events". The user
  2010. // configures events, not messages.
  2011. //
  2012. // For further information on how this class fits into the
  2013. // scheme of things, please see the CXEventSource class header.
  2014. //////////////////////////////////////////////////////////////////
  2015. CXMessage::CXMessage(CXEventSource* pEventSource)
  2016. {
  2017. m_pEventSource = pEventSource;
  2018. }
  2019. CXMessage& CXMessage::operator=(CXMessage& message)
  2020. {
  2021. m_pEventSource = message.m_pEventSource;
  2022. m_dwId = message.m_dwId;
  2023. m_sText = message.m_sText;
  2024. return *this;
  2025. }
  2026. //***************************************************************************
  2027. //
  2028. // CMessage::GetSeverity
  2029. //
  2030. // Get the severity level of the event. This is the human-readable string
  2031. // corresponding to the top two bits of the event ID.
  2032. //
  2033. // Parameters:
  2034. // CString& sSeverity
  2035. // A reference to the place to return the severity string.
  2036. //
  2037. // Returns:
  2038. // Nothing.
  2039. //
  2040. // Status:
  2041. //
  2042. //***************************************************************************
  2043. void CXMessage::GetSeverity(CString& sSeverity)
  2044. {
  2045. MapEventToSeverity(m_dwId, sSeverity);
  2046. }
  2047. //***************************************************************************
  2048. //
  2049. // CMessage::GetTrappingString
  2050. //
  2051. // This method returns the trapping string "yes" if the event is being
  2052. // trapped and "no" if its not being trapped.
  2053. //
  2054. // Parameters:
  2055. // CString& sTrapping
  2056. // A reference to the place to return the trapping string.
  2057. //
  2058. // Returns:
  2059. // Nothing.
  2060. //
  2061. // Status:
  2062. //
  2063. //***************************************************************************
  2064. void CXMessage::IsTrapping(CString& sIsTrapping)
  2065. {
  2066. CXEvent* pEvent = m_pEventSource->FindEvent(m_dwId);
  2067. sIsTrapping.LoadString( pEvent != NULL ? IDS_IS_TRAPPING : IDS_NOT_TRAPPING);
  2068. }
  2069. //****************************************************************************
  2070. //
  2071. // CMessage::SetAndCleanText
  2072. //
  2073. // Set the m_sText data member to a cleaned up version of a source string.
  2074. // The text is cleaned by converting all funny whitespace characters such
  2075. // as carriage return, tabs and so on to ordinary space characters. All
  2076. // leading space is stripped from the beginning of the string.
  2077. //
  2078. //****************************************************************************
  2079. void CXMessage::SetAndCleanText(PMESSAGE_RESOURCE_ENTRY pEntry)
  2080. {
  2081. BOOL bIsLeadingSpace = TRUE;
  2082. USHORT i;
  2083. if (pEntry->Flags == 0x00000) // ANSI char set
  2084. {
  2085. CHAR *pszSrc = (CHAR *)pEntry->Text;
  2086. CHAR chSrc;
  2087. LPTSTR pszDst = m_sText.GetBuffer(strlen(pszSrc) + 1);
  2088. for (i=0; i<pEntry->Length && *pszSrc; i++, pszSrc++)
  2089. {
  2090. chSrc = *pszSrc;
  2091. if (chSrc >= 0x09 && chSrc <= 0x0d)
  2092. chSrc = ' ';
  2093. if (chSrc == ' ' && bIsLeadingSpace)
  2094. continue;
  2095. *pszDst++ = (TCHAR)chSrc;
  2096. if (bIsLeadingSpace) // testing only is less costly
  2097. bIsLeadingSpace = FALSE;
  2098. }
  2099. *pszDst = _T('\0');
  2100. }
  2101. else // UNICODE char set
  2102. {
  2103. wchar_t *pwszSrc = (wchar_t *)pEntry->Text;
  2104. wchar_t wchSrc;
  2105. LPTSTR pszDst = m_sText.GetBuffer(wcslen(pwszSrc) + 1);
  2106. for (i=0; i<pEntry->Length/sizeof(wchar_t) && *pwszSrc; i++, pwszSrc++)
  2107. {
  2108. wchSrc = *pwszSrc;
  2109. if (wchSrc >= (wchar_t)0x09 && wchSrc <= (wchar_t)0x0d)
  2110. wchSrc = (wchar_t)' ';
  2111. if (wchSrc == (wchar_t)' ' && bIsLeadingSpace)
  2112. continue;
  2113. *pszDst++ = (TCHAR)wchSrc;
  2114. if (bIsLeadingSpace) // testing only is less costly
  2115. bIsLeadingSpace = FALSE;
  2116. }
  2117. *pszDst = _T('\0');
  2118. }
  2119. m_sText.ReleaseBuffer();
  2120. }
  2121. //****************************************************************************
  2122. // CXMessage::GetShortId
  2123. //
  2124. // This method returns the message's "short ID" that users see for events and
  2125. // messages. The short ID is the ASCII decimal value for the low-order 16 bits
  2126. // of the message ID.
  2127. //
  2128. // Using this method to do the conversion ensures that the short-ID value is
  2129. // presented to the user in a consistent form throughout the program.
  2130. //
  2131. // Parameters:
  2132. // CString& sShortId
  2133. // This is where the ID string is returned.
  2134. //
  2135. // Returns:
  2136. // The message ID string is returned via sShortId
  2137. //
  2138. //****************************************************************************
  2139. void CXMessage::GetShortId(CString& sShortId)
  2140. {
  2141. TCHAR szBuffer[MAX_STRING];
  2142. _ltot((LONG) LOWORD(m_dwId), szBuffer, 10);
  2143. sShortId = szBuffer;
  2144. }
  2145. ///////////////////////////////////////////////////////////////////
  2146. // Class: CXMessageArray
  2147. //
  2148. // This class implements an array of pointers to CXMessage objects.
  2149. //
  2150. // For further information on how this CXMessageArray fits into the
  2151. // scheme of things, please see the CXEventSource class header.
  2152. //////////////////////////////////////////////////////////////////
  2153. //****************************************************************
  2154. // CXMessageArray::CXMessageArray
  2155. //
  2156. // Constructor.
  2157. //
  2158. // Parameters:
  2159. // None.
  2160. //
  2161. // Returns:
  2162. // Nothing.
  2163. //
  2164. //****************************************************************
  2165. CXMessageArray::CXMessageArray()
  2166. {
  2167. m_bDidLoadMessages = FALSE;
  2168. m_pEventSource = NULL;
  2169. }
  2170. //*******************************************************************
  2171. // CXMessageArray::FindMessage
  2172. //
  2173. // Search this array for a message given its ID.
  2174. //
  2175. // Parameters:
  2176. // DWORD dwId
  2177. // The full message ID
  2178. //
  2179. // Returns:
  2180. // CXMessage*
  2181. // Pointer to the message if it was found. NULL if it was
  2182. // not found.
  2183. //
  2184. // Note:
  2185. // Duplicate messages are not allowed in the array, but no code
  2186. // enforces this for the sake of efficiency.
  2187. //
  2188. //*******************************************************************
  2189. CXMessage* CXMessageArray::FindMessage(DWORD dwId)
  2190. {
  2191. if (!m_bDidLoadMessages) {
  2192. if (FAILED(LoadMessages())) {
  2193. return NULL;
  2194. }
  2195. }
  2196. LONG nMessages = GetSize();
  2197. for (LONG iMessage = 0; iMessage < nMessages; ++iMessage) {
  2198. CXMessage* pMessage = GetAt(iMessage);
  2199. if (pMessage->m_dwId == dwId) {
  2200. return pMessage;
  2201. }
  2202. }
  2203. return NULL;
  2204. }
  2205. //****************************************************************************
  2206. //
  2207. // XProcessMsgTable
  2208. //
  2209. // This function processes a the message table contained in a message .DLL file
  2210. // and adds all the messages it contains to the given CXMessageArray object.
  2211. //
  2212. // Parameters:
  2213. // HANDLE hModule
  2214. // The module handle for the .DLL file.
  2215. //
  2216. // LPCTSTR lpszType
  2217. // Ignored.
  2218. //
  2219. // LPTSTR lpszName
  2220. // The name of the module.
  2221. //
  2222. // LONG lParam
  2223. // A pointer to a CXMessageArray object where the messages will be
  2224. // stored.
  2225. //
  2226. // Returns:
  2227. // BOOL
  2228. // Always returns TRUE.
  2229. //
  2230. //
  2231. //****************************************************************************
  2232. static BOOL CALLBACK XProcessMsgTable(HANDLE hModule, LPCTSTR lpszType,
  2233. LPTSTR lpszName, LONG_PTR lParam)
  2234. {
  2235. CXMessageArray* paMessages = (CXMessageArray*)(LPVOID) (LONG_PTR)lParam;
  2236. // Found a message table. Process it!
  2237. HRSRC hResource = FindResource((HINSTANCE)hModule, lpszName,
  2238. RT_MESSAGETABLE);
  2239. if (hResource == NULL)
  2240. return TRUE;
  2241. HGLOBAL hMem = LoadResource((HINSTANCE)hModule, hResource);
  2242. if (hMem == NULL)
  2243. return TRUE;
  2244. PMESSAGE_RESOURCE_DATA pMsgTable = (PMESSAGE_RESOURCE_DATA)::LockResource(hMem);
  2245. if (pMsgTable == NULL)
  2246. return TRUE;
  2247. ULONG ulBlock, ulId, ulOffset;
  2248. for (ulBlock=0; ulBlock<pMsgTable->NumberOfBlocks; ulBlock++)
  2249. {
  2250. ulOffset = pMsgTable->Blocks[ulBlock].OffsetToEntries;
  2251. for (ulId = pMsgTable->Blocks[ulBlock].LowId;
  2252. ulId <= pMsgTable->Blocks[ulBlock].HighId; ulId++)
  2253. {
  2254. PMESSAGE_RESOURCE_ENTRY pEntry =
  2255. (PMESSAGE_RESOURCE_ENTRY)((ULONG_PTR)pMsgTable + ulOffset);
  2256. CXMessage *pMessage = new CXMessage(paMessages->m_pEventSource);
  2257. pMessage->m_dwId = (DWORD) ulId;
  2258. pMessage->SetAndCleanText(pEntry);
  2259. paMessages->Add(pMessage);
  2260. ulOffset += pEntry->Length;
  2261. }
  2262. }
  2263. return TRUE;
  2264. }
  2265. //****************************************************************************
  2266. // CXMessageArray::LoadMessages
  2267. //
  2268. // Load the messages from the message .DLL file(s) for the source into this
  2269. // message array.
  2270. //
  2271. // Parameters:
  2272. // None.
  2273. //
  2274. // Returns:
  2275. // SCODE
  2276. // S_OK if successful.
  2277. // E_FAIL if an error occurs.
  2278. //
  2279. //*****************************************************************************
  2280. SCODE CXMessageArray::LoadMessages()
  2281. {
  2282. ASSERT(m_pEventSource != NULL);
  2283. if (m_bDidLoadMessages) {
  2284. return S_OK;
  2285. }
  2286. CBusy busy;
  2287. CString sLibPathList = m_pEventSource->m_sLibPath;
  2288. CString sLibPath;
  2289. while (GetNextPath(sLibPathList, sLibPath) != E_FAIL) {
  2290. // Load the library and get a list of all the messages.
  2291. HINSTANCE hInstMsgFile = LoadLibraryEx((LPCTSTR) sLibPath, NULL,
  2292. LOAD_LIBRARY_AS_DATAFILE);
  2293. if (hInstMsgFile == NULL) {
  2294. TCHAR szMessage[MAX_STRING];
  2295. CString sFormat;
  2296. sFormat.LoadString(IDS_ERR_LOAD_MESSAGE_FILE_FAILED);
  2297. _stprintf(szMessage, (LPCTSTR) sFormat, (LPCTSTR) sLibPath);
  2298. AfxMessageBox(szMessage, MB_OK | MB_ICONSTOP);
  2299. continue;
  2300. }
  2301. EnumResourceNames(hInstMsgFile, RT_MESSAGETABLE,
  2302. (ENUMRESNAMEPROC)XProcessMsgTable, (LONG_PTR) this);
  2303. GetLastError();
  2304. FreeLibrary(hInstMsgFile);
  2305. }
  2306. m_bDidLoadMessages = TRUE;
  2307. return S_OK;
  2308. }
  2309. //**************************************************************
  2310. // CXMessageArray::GetNextPath
  2311. //
  2312. // This function extracts the next path element from a list
  2313. // of semi-colon separated paths. It also removes the extracted
  2314. // element and the semi-colon from the path list.
  2315. //
  2316. // Paramters:
  2317. // CString& sPathlist
  2318. // A reference to a string consisting of one or more paths separated
  2319. // by semi-colons.
  2320. //
  2321. // CString& sPath
  2322. // A reference to the place where the extracted path string
  2323. // will be returned.
  2324. //
  2325. // Returns:
  2326. // SCODE
  2327. // S_OK if a path was extracted, E_FAIL otherwise.
  2328. //
  2329. // The path is returned via sPath. sPathlist is updated
  2330. // so that sPath and the trailing semi-colon is removed
  2331. //
  2332. //**************************************************************
  2333. SCODE CXMessageArray::GetNextPath(CString& sPathlist, CString& sPath)
  2334. {
  2335. CString sPathTemp;
  2336. sPath.Empty();
  2337. while (sPath.IsEmpty() && !sPathlist.IsEmpty()) {
  2338. // Copy the next path from the sPathlist to sPath and
  2339. // remove it from sPathlist
  2340. INT ich = sPathlist.Find(_T(';'));
  2341. if (ich == -1) {
  2342. sPathTemp = sPathlist;
  2343. sPathlist = _T("");
  2344. }
  2345. else {
  2346. sPathTemp = sPathlist.Left(ich);
  2347. sPathlist = sPathlist.Right( sPathlist.GetLength() - (ich + 1));
  2348. }
  2349. // Trim any leading or trailing space characters from
  2350. // the path.
  2351. // Find the first non-space character
  2352. LPTSTR pszStart = sPathTemp.GetBuffer(sPathTemp.GetLength() + 1);
  2353. while (*pszStart) {
  2354. if (!_istspace(*pszStart)) {
  2355. break;
  2356. }
  2357. ++pszStart;
  2358. }
  2359. // here, pszStart either points to the 1st non-space character or a string
  2360. // of zero length
  2361. // Find the first non-space character in reverse direction
  2362. LPTSTR pszEnd = pszStart + _tcslen(pszStart); // point to the null character
  2363. if (pszStart != pszEnd)
  2364. {
  2365. pszEnd--; // point to the last character
  2366. while (_istspace(*pszEnd))
  2367. {
  2368. pszEnd--;
  2369. }
  2370. // here, pszEnd points to the first non-space character in reverse direction
  2371. pszEnd++;
  2372. *pszEnd = _T('\0');
  2373. }
  2374. sPath = pszStart;
  2375. sPathTemp.ReleaseBuffer();
  2376. }
  2377. if (sPath.IsEmpty()) {
  2378. return E_FAIL;
  2379. }
  2380. else {
  2381. return S_OK;
  2382. }
  2383. }