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.

2219 lines
54 KiB

  1. //***************************************************************************
  2. //
  3. // NTEVTLOGF.CPP
  4. //
  5. // Module: WBEM NT EVENT PROVIDER
  6. //
  7. // Purpose: Contains the Eventlog classes
  8. //
  9. // Copyright (c) 1996-2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. #include <time.h>
  14. #include <io.h>
  15. #include <wbemtime.h>
  16. CEventlogFileAttributes::CEventlogFileAttributes(const wchar_t* log):
  17. m_logname(log),
  18. m_retention (0),
  19. m_fileSz (15000*1024)
  20. {
  21. m_sources.SetSize(0, 10);
  22. }
  23. CEventlogFileAttributes::~CEventlogFileAttributes()
  24. {
  25. LONG count = m_sources.GetSize();
  26. if (count > 0)
  27. {
  28. for (LONG x = 0; x < count; x++)
  29. {
  30. delete m_sources[x];
  31. }
  32. m_sources.RemoveAll();
  33. }
  34. }
  35. DWORD CEventlogFileAttributes::EventLogOperation (const wchar_t* archive, BOOL bClear,
  36. WbemProvErrorObject &a_ErrorObject, BOOL &bSuccess)
  37. {
  38. DWORD retVal = ERROR_SUCCESS;
  39. HANDLE hEventLog = OpenEventLog(NULL, m_logname);
  40. if (hEventLog == NULL)
  41. {
  42. if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  43. {
  44. CEventLogFile::SetSecurityLogPrivilege();
  45. hEventLog = OpenEventLog(NULL, m_logname);
  46. }
  47. }
  48. if (hEventLog == NULL)
  49. {
  50. retVal = GetLastError();
  51. DebugOut(
  52. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  53. _T(__FILE__),__LINE__,
  54. L"CEventlogFileAttributes::EventLogOperation:Failed to OpenEventLog %s with error %lx.\r\n",
  55. m_logname, retVal
  56. ) ;
  57. )
  58. if (retVal == ERROR_PRIVILEGE_NOT_HELD)
  59. {
  60. retVal = 0;
  61. bSuccess = FALSE;
  62. a_ErrorObject.SetWbemStatus ( WBEM_E_ACCESS_DENIED ) ;
  63. a_ErrorObject.SetMessage ( L"Failed to open the logfile" ) ;
  64. a_ErrorObject.SetPrivilegeFailed();
  65. a_ErrorObject.SetSecurityPrivRequired();
  66. a_ErrorObject.SetSecurityPrivFailed();
  67. if (!bClear)
  68. {
  69. a_ErrorObject.SetBackupPrivRequired();
  70. }
  71. }
  72. }
  73. else
  74. {
  75. if (bClear)
  76. {
  77. if (!ClearEventLog(hEventLog, archive))
  78. {
  79. retVal = GetLastError();
  80. DebugOut(
  81. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  82. _T(__FILE__),__LINE__,
  83. L"CEventlogFileAttributes::EventLogOperation:Failed to ClearEventLog %s with error %lx.\r\n",
  84. m_logname, retVal
  85. ) ;
  86. )
  87. }
  88. }
  89. else
  90. {
  91. if (archive == NULL)
  92. {
  93. retVal = ERROR_INVALID_PARAMETER;
  94. }
  95. else if (!BackupEventLog(hEventLog, archive))
  96. {
  97. retVal = GetLastError();
  98. if (retVal == ERROR_PRIVILEGE_NOT_HELD)
  99. {
  100. retVal = 0;
  101. CEventLogFile::SetSecurityLogPrivilege(FALSE, SE_BACKUP_NAME);
  102. if (!BackupEventLog(hEventLog, archive))
  103. {
  104. retVal = GetLastError();
  105. DebugOut(
  106. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  107. _T(__FILE__),__LINE__,
  108. L"CEventlogFileAttributes::EventLogOperation:Failed even after privilege set to BackupEventLog %s with error %lx.\r\n",
  109. m_logname, retVal
  110. ) ;
  111. )
  112. if (retVal == ERROR_PRIVILEGE_NOT_HELD)
  113. {
  114. retVal = 0;
  115. bSuccess = FALSE;
  116. a_ErrorObject.SetWbemStatus ( WBEM_E_ACCESS_DENIED ) ;
  117. a_ErrorObject.SetMessage ( L"Opened the logfile but failed to back it up, privilege error" ) ;
  118. a_ErrorObject.SetPrivilegeFailed();
  119. a_ErrorObject.SetBackupPrivRequired();
  120. a_ErrorObject.SetBackupPrivFailed();
  121. }
  122. }
  123. else
  124. {
  125. DebugOut(
  126. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  127. _T(__FILE__),__LINE__,
  128. L"CEventlogFileAttributes::EventLogOperation:After privilege set, BackupEventLog %s succeeded.\r\n",
  129. m_logname
  130. ) ;
  131. )
  132. }
  133. }
  134. DebugOut(
  135. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  136. _T(__FILE__),__LINE__,
  137. L"CEventlogFileAttributes::EventLogOperation:Failed to BackupEventLog %s with error %lx.\r\n",
  138. m_logname, retVal
  139. ) ;
  140. )
  141. }
  142. }
  143. CloseEventLog(hEventLog);
  144. }
  145. return retVal;
  146. }
  147. BOOL CEventlogFileAttributes::GenerateInstance(IWbemClassObject* pClassObj, IWbemClassObject* pAClassObj, IWbemClassObject** ppInst)
  148. {
  149. if (pClassObj == NULL)
  150. {
  151. DebugOut(
  152. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  153. _T(__FILE__),__LINE__,
  154. L"CEventlogFileAttributes::GenerateInstance:Invalid parameter - Return FALSE\r\n"
  155. ) ;
  156. )
  157. return FALSE;
  158. }
  159. if (ReadRegistry() != ERROR_SUCCESS)
  160. {
  161. DebugOut(
  162. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  163. _T(__FILE__),__LINE__,
  164. L"CEventlogFileAttributes::GenerateInstance:Failed to read registry values - Return FALSE\r\n"
  165. ) ;
  166. )
  167. return FALSE;
  168. }
  169. HRESULT hr = pClassObj->SpawnInstance(0, ppInst);
  170. if (FAILED(hr))
  171. {
  172. DebugOut(
  173. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  174. _T(__FILE__),__LINE__,
  175. L"CEventlogFileAttributes::GenerateInstance:Failed to spawn instance - Return FALSE\r\n"
  176. ) ;
  177. )
  178. return FALSE;
  179. }
  180. //set the key properties, they are all in the super class
  181. if (!SetSuperClassProperties(*ppInst))
  182. {
  183. //can't set the key, just return
  184. DebugOut(
  185. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  186. _T(__FILE__),__LINE__,
  187. L"CEventlogFileAttributes::GenerateInstance:Failed to set key values - Return FALSE\r\n"
  188. ) ;
  189. )
  190. (*ppInst)->Release();
  191. return FALSE;
  192. }
  193. //set the evtlog properties...
  194. VARIANT v;
  195. VariantInit(&v);
  196. v.vt = VT_BSTR;
  197. v.bstrVal = m_logname.AllocSysString();
  198. hr = (*ppInst)->Put(PROP_LOGNAME, 0, &v, 0);
  199. VariantClear(&v); // will call free v.bstrVal
  200. VariantInit(&v);
  201. v.vt = VT_I4;
  202. v.lVal = m_fileSz;
  203. hr = (*ppInst)->Put(PROP_MAXSZ, 0, &v, 0);
  204. VariantClear(&v);
  205. VariantInit(&v);
  206. v.vt = VT_I4;
  207. if ((m_retention > 0) && (m_retention < EVT_NEVER_AGE))
  208. {
  209. //turn into days
  210. v.lVal = m_retention/EVT_UNITS_FROM_DAYS;
  211. if (v.lVal > MAX_EVT_AGE)
  212. {
  213. v.lVal = MAX_EVT_AGE;
  214. }
  215. }
  216. else
  217. {
  218. v.lVal = m_retention;
  219. }
  220. hr = (*ppInst)->Put(PROP_RETENTION, 0, &v, 0);
  221. if (pAClassObj)
  222. {
  223. SetRetentionStr(pAClassObj, *ppInst, (DWORD)v.lVal);
  224. }
  225. VariantClear(&v);
  226. HANDLE hEventLog = OpenEventLog(NULL, m_logname);
  227. if (hEventLog == NULL)
  228. {
  229. if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  230. {
  231. CEventLogFile::SetSecurityLogPrivilege();
  232. hEventLog = OpenEventLog(NULL, m_logname);
  233. }
  234. }
  235. if (hEventLog != NULL)
  236. {
  237. DWORD num_recs = 0;
  238. if (GetNumberOfEventLogRecords(hEventLog, &num_recs))
  239. {
  240. VariantInit(&v);
  241. v.vt = VT_I4;
  242. v.lVal = num_recs;
  243. hr = (*ppInst)->Put(PROP_NUMRECS, 0, &v, 0);
  244. VariantClear(&v);
  245. }
  246. CloseEventLog(hEventLog);
  247. }
  248. LONG count = m_sources.GetSize();
  249. if (count > 0)
  250. {
  251. SAFEARRAYBOUND rgsabound[1];
  252. SAFEARRAY* psa = NULL;
  253. BSTR* pBstr = NULL;
  254. rgsabound[0].lLbound = 0;
  255. VariantInit(&v);
  256. rgsabound[0].cElements = count;
  257. psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  258. if (NULL != psa)
  259. {
  260. if (SUCCEEDED(SafeArrayAccessData(psa, (void **)&pBstr)))
  261. {
  262. for (LONG x = 0; x < count; x++)
  263. {
  264. pBstr[x] = m_sources[x]->AllocSysString();
  265. delete m_sources[x];
  266. m_sources[x] = NULL;
  267. }
  268. m_sources.RemoveAll();
  269. SafeArrayUnaccessData(psa);
  270. v.vt = VT_ARRAY|VT_BSTR;
  271. v.parray = psa;
  272. hr = (*ppInst)->Put(PROP_SOURCES, 0, &v, 0);
  273. }
  274. }
  275. VariantClear(&v);
  276. }
  277. return TRUE;
  278. }
  279. ULONG CEventlogFileAttributes::GetIndex(wchar_t* indexStr, BOOL* bError)
  280. {
  281. #if 0
  282. __int64 val = _wtoi64(indexStr);
  283. #else
  284. int val = _wtoi(indexStr);
  285. #endif
  286. *bError = FALSE;
  287. ULONG index = 0;
  288. switch (val)
  289. {
  290. case 0: //Always overwrite
  291. {
  292. index = 0;
  293. break;
  294. }
  295. case 1: //1-365
  296. {
  297. index = 1;
  298. break;
  299. }
  300. case EVT_NEVER_AGE: //0xffffffff
  301. {
  302. index = 2;
  303. break;
  304. }
  305. default:
  306. {
  307. *bError = TRUE;
  308. }
  309. }
  310. return index;
  311. }
  312. void CEventlogFileAttributes::SetRetentionStr(IWbemClassObject* pClassObj, IWbemClassObject* pInstObj, DWORD dwVal)
  313. {
  314. CStringW strRetentionArray[RETENTION_ARRAY_LEN];
  315. if (CEventlogRecord::SetEnumArray(pClassObj, PROP_RETENTION_STR,(CStringW*) strRetentionArray,
  316. RETENTION_ARRAY_LEN, (GetIndexFunc)GetIndex))
  317. {
  318. BSTR retStr = NULL;
  319. if (dwVal == 0)
  320. {
  321. retStr = strRetentionArray[0].AllocSysString();
  322. }
  323. else if (dwVal == EVT_NEVER_AGE)
  324. {
  325. retStr = strRetentionArray[2].AllocSysString();
  326. }
  327. else
  328. {
  329. retStr = strRetentionArray[1].AllocSysString();
  330. }
  331. if (retStr != NULL)
  332. {
  333. VARIANT v;
  334. VariantInit (&v);
  335. v.vt = VT_BSTR;
  336. v.bstrVal = retStr;
  337. HRESULT hr = pInstObj->Put(PROP_RETENTION_STR, 0, &v, 0);
  338. VariantClear(&v);
  339. }
  340. }
  341. }
  342. BOOL CEventlogFileAttributes::SetSuperClassProperties(IWbemClassObject* pInst)
  343. {
  344. //failure to set any key property
  345. //is an error, return FALSE!!
  346. VARIANT v;
  347. VariantInit(&v);
  348. v.vt = VT_BSTR;
  349. v.bstrVal = m_logpath.AllocSysString();
  350. HRESULT hr = pInst->Put(PROP_NAME, 0, &v, 0);
  351. VariantClear(&v);
  352. if (FAILED(hr))
  353. {
  354. return FALSE;
  355. }
  356. VariantInit(&v);
  357. v.vt = VT_BSTR;
  358. v.bstrVal = SysAllocString(VAL_FS_CRE_CLASS);
  359. hr = pInst->Put(PROP_FS_CRE_CLASS, 0, &v, 0);
  360. VariantClear(&v);
  361. VariantInit(&v);
  362. v.vt = VT_BSTR;
  363. v.bstrVal = SysAllocString(NTEVTLOG_CLASS);
  364. hr = pInst->Put(PROP_CRE_CLASS, 0, &v, 0);
  365. VariantClear(&v);
  366. VariantInit(&v);
  367. v.vt = VT_BSTR;
  368. v.bstrVal = SysAllocString(COMP_CLASS);
  369. hr = pInst->Put(PROP_CS_CRE_CLASS, 0, &v, 0);
  370. VariantClear(&v);
  371. return TRUE;
  372. }
  373. DWORD CEventlogFileAttributes::UpdateRegistry(IWbemClassObject* pInst)
  374. {
  375. if (NULL == pInst)
  376. {
  377. return ERROR_INVALID_PARAMETER;
  378. }
  379. //get the data to be written
  380. VARIANT v;
  381. HRESULT hr = pInst->Get(PROP_RETENTION, 0, &v,NULL, NULL);
  382. if (SUCCEEDED(hr))
  383. {
  384. m_retention = (DWORD)v.lVal;
  385. VariantClear(&v);
  386. if ((m_retention > MAX_EVT_AGE) && (m_retention < EVT_NEVER_AGE))
  387. {
  388. DebugOut(
  389. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  390. _T(__FILE__),__LINE__,
  391. L"CEventlogFileAttributes::UpdateRegistry:Retention Data not in range\r\n"
  392. ) ;
  393. )
  394. return ERROR_INVALID_DATA;
  395. }
  396. if ((m_retention > 0) && (m_retention < EVT_NEVER_AGE))
  397. {
  398. m_retention = m_retention * EVT_UNITS_FROM_DAYS;
  399. }
  400. }
  401. else
  402. {
  403. DebugOut(
  404. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  405. _T(__FILE__),__LINE__,
  406. L"CEventlogFileAttributes::UpdateRegistry:Failed to get retention value from instance\r\n"
  407. ) ;
  408. )
  409. return (DWORD)hr;
  410. }
  411. hr = pInst->Get(PROP_MAXSZ, 0, &v,NULL, NULL);
  412. if (SUCCEEDED(hr))
  413. {
  414. m_fileSz = (DWORD)v.lVal;
  415. VariantClear(&v);
  416. if (m_fileSz < FILE_CHUNK_SZ)
  417. {
  418. m_fileSz = FILE_CHUNK_SZ;
  419. }
  420. else if (m_fileSz > MAX_EVT_LOG_SZ)
  421. {
  422. m_fileSz = MAX_EVT_LOG_SZ;
  423. }
  424. else
  425. {
  426. DWORD rem = m_fileSz % FILE_CHUNK_SZ;
  427. if (rem != 0)
  428. {
  429. //need to round up to nearest file chunk size
  430. DWORD x = m_fileSz / FILE_CHUNK_SZ;
  431. m_fileSz = (++x) * FILE_CHUNK_SZ;
  432. }
  433. }
  434. }
  435. else
  436. {
  437. DebugOut(
  438. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  439. _T(__FILE__),__LINE__,
  440. L"CEventlogFileAttributes::UpdateRegistry:Failed to get MaxFileSize value from instance\r\n"
  441. ) ;
  442. )
  443. return (DWORD)hr;
  444. }
  445. DWORD retVal;
  446. CStringW strKey(EVENTLOG_BASE);
  447. strKey += CStringW(L'\\');
  448. strKey += m_logname;
  449. HKEY hkResult;
  450. //open the logfile's key for setting values
  451. LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  452. strKey, 0,
  453. KEY_SET_VALUE,
  454. &hkResult);
  455. if (status != ERROR_SUCCESS)
  456. {
  457. // indicate error
  458. DebugOut(
  459. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  460. _T(__FILE__),__LINE__,
  461. L"CEventlogFileAttributes::UpdateRegistry:Open registry to set new values. Error %lx\r\n",
  462. status
  463. ) ;
  464. )
  465. return status;
  466. }
  467. //set the values we read in...
  468. status = RegSetValueEx(hkResult,
  469. EVTLOG_REG_MAXSZ_VALUE, 0, REG_DWORD,
  470. (CONST BYTE *) &m_fileSz, sizeof(DWORD));
  471. if (status != ERROR_SUCCESS)
  472. {
  473. // indicate error
  474. DebugOut(
  475. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  476. _T(__FILE__),__LINE__,
  477. L"CEventlogFileAttributes::UpdateRegistry:Failed to set new size. Error %lx\r\n",
  478. status
  479. ) ;
  480. )
  481. retVal = status;
  482. }
  483. else
  484. {
  485. retVal =(DWORD) RegSetValueEx(hkResult,
  486. EVTLOG_REG_RETENTION_VALUE, 0, REG_DWORD,
  487. (CONST BYTE *) &m_retention, sizeof(DWORD));
  488. if (retVal != ERROR_SUCCESS)
  489. {
  490. DebugOut(
  491. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  492. _T(__FILE__),__LINE__,
  493. L"CEventlogFileAttributes::UpdateRegistry:Failed to set new retention policy. Error %lx\r\n",
  494. retVal
  495. ) ;
  496. )
  497. }
  498. }
  499. RegCloseKey(hkResult);
  500. return retVal;
  501. }
  502. DWORD CEventlogFileAttributes::ReadRegistry()
  503. {
  504. DWORD retVal;
  505. CStringW strKey(EVENTLOG_BASE);
  506. strKey += CStringW(L'\\');
  507. strKey += m_logname;
  508. HKEY hkResult;
  509. //open the logfile's key for read
  510. LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  511. strKey, 0,
  512. KEY_QUERY_VALUE,
  513. &hkResult);
  514. if (status != ERROR_SUCCESS)
  515. {
  516. // indicate error
  517. DebugOut(
  518. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  519. _T(__FILE__),__LINE__,
  520. L"CEventlogFileAttributes::ReadRegistry:Failed to open registry. Error %lx\r\n",
  521. status
  522. ) ;
  523. )
  524. retVal = status;
  525. }
  526. else
  527. {
  528. //first get the file value
  529. m_logpath = CEventLogFile::GetFileName(hkResult);
  530. DWORD datalen;
  531. DWORD dwType;
  532. wchar_t* data;
  533. if (m_logpath.IsEmpty())
  534. {
  535. DebugOut(
  536. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  537. _T(__FILE__),__LINE__,
  538. L"CEventlogFileAttributes::ReadRegistry:Failed to resolve log file name\r\n"
  539. ) ;
  540. )
  541. retVal = ERROR_INVALID_DATA;
  542. }
  543. else
  544. {
  545. datalen = sizeof(m_fileSz);
  546. status = RegQueryValueEx(hkResult, EVTLOG_REG_MAXSZ_VALUE,
  547. 0, &dwType, (LPBYTE) &m_fileSz, &datalen);
  548. if ( ERROR_SUCCESS == status )
  549. {
  550. retVal = 0;
  551. }
  552. else if ( ERROR_FILE_NOT_FOUND == status )
  553. {
  554. //
  555. // we assume 512KB (same story with nt event viewer)
  556. // was set in constructor
  557. //
  558. retVal = 0;
  559. }
  560. else if( REG_DWORD != dwType )
  561. {
  562. retVal = ERROR_INVALID_DATA;
  563. }
  564. else
  565. {
  566. DebugOut(
  567. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  568. _T(__FILE__),__LINE__,
  569. L"CEventlogFileAttributes::ReadRegistry:Failed to read size. Error %lx\r\n",
  570. status
  571. ) ;
  572. )
  573. retVal = status;
  574. }
  575. if ( 0 == retVal )
  576. {
  577. datalen = sizeof(m_retention);
  578. status = RegQueryValueEx(hkResult, EVTLOG_REG_RETENTION_VALUE,
  579. 0, &dwType, (LPBYTE) &m_retention, &datalen);
  580. if ( ERROR_SUCCESS == status )
  581. {
  582. retVal = 0;
  583. }
  584. else if ( ERROR_FILE_NOT_FOUND == status )
  585. {
  586. //
  587. // we assume 7 dyas (same story with nt event viewer)
  588. // was set in constructor
  589. //
  590. retVal = 0;
  591. }
  592. else if( REG_DWORD != dwType )
  593. {
  594. retVal = ERROR_INVALID_DATA;
  595. }
  596. else
  597. {
  598. DebugOut(
  599. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  600. _T(__FILE__),__LINE__,
  601. L"CEventlogFileAttributes::ReadRegistry:Failed to read retention. Error %lx\r\n",
  602. status
  603. ) ;
  604. )
  605. retVal = status;
  606. }
  607. }
  608. }
  609. if (retVal == 0)
  610. {
  611. data = new wchar_t[MAX_PATH + 1];
  612. datalen = (MAX_PATH + 1) * sizeof(wchar_t);
  613. status = RegQueryValueEx(hkResult, EVTLOG_REG_SOURCES_VALUE,
  614. 0, &dwType, (LPBYTE) data, &datalen);
  615. if (((status == ERROR_SUCCESS) || (status == ERROR_MORE_DATA)) &&
  616. (dwType == REG_MULTI_SZ))
  617. {
  618. if (status == ERROR_MORE_DATA)
  619. {
  620. delete [] data;
  621. data = new wchar_t[datalen];
  622. status = RegQueryValueEx(hkResult, EVTLOG_REG_SOURCES_VALUE,
  623. 0, &dwType, (LPBYTE) data, &datalen);
  624. }
  625. if (status == ERROR_SUCCESS)
  626. {
  627. wchar_t* tmp = data;
  628. int x = 0;
  629. while (*tmp != L'\0')
  630. {
  631. CStringW* tmpstr = new CStringW(tmp);
  632. m_sources.SetAtGrow(x++, tmpstr);
  633. tmp += wcslen(tmp) + 1;
  634. }
  635. }
  636. else
  637. {
  638. DebugOut(
  639. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  640. _T(__FILE__),__LINE__,
  641. L"CEventlogFileAttributes::ReadRegistry:Failed to read sources. Error %lx\r\n",
  642. status
  643. ) ;
  644. )
  645. }
  646. }
  647. else
  648. {
  649. DebugOut(
  650. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  651. _T(__FILE__),__LINE__,
  652. L"CEventlogFileAttributes::ReadRegistry:Failed to read sources. Error %lx\r\n",
  653. status
  654. ) ;
  655. )
  656. }
  657. delete [] data;
  658. }
  659. RegCloseKey(hkResult);
  660. }
  661. return retVal;
  662. }
  663. CEventLogFile::CEventLogFile(const WCHAR* logname, BOOL bVerify) : m_hEvtLog(NULL), m_BuffLen (0)
  664. {
  665. m_Reason = ERROR_SUCCESS;
  666. m_EvtLogName = logname;
  667. m_bValid = FALSE;
  668. m_bBuffer = FALSE;
  669. m_hEvtLog = NULL;
  670. m_Buffer = NULL;
  671. if (bVerify)
  672. {
  673. if (logname != NULL)
  674. {
  675. DWORD cchBase = wcslen(EVENTLOG_BASE);
  676. DWORD cchSize = cchBase + 1 + wcslen(logname) + 1;
  677. wchar_t* buff = new wchar_t[ cchSize ];
  678. StringCchCopyW ( buff, cchBase + 1, EVENTLOG_BASE );
  679. StringCchCatW ( buff, cchSize, L"\\" );
  680. StringCchCatW ( buff, cchSize, logname);
  681. HKEY hkResult = NULL;
  682. m_Reason = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  683. buff, 0,
  684. KEY_READ,
  685. &hkResult);
  686. if (m_Reason == ERROR_SUCCESS)
  687. {
  688. if (hkResult != NULL)
  689. {
  690. RegCloseKey(hkResult);
  691. hkResult = NULL;
  692. }
  693. else
  694. {
  695. m_Reason = ERROR_FILE_NOT_FOUND;
  696. }
  697. }
  698. delete [] buff;
  699. buff = NULL;
  700. }
  701. else
  702. {
  703. m_Reason = ERROR_FILE_NOT_FOUND;
  704. }
  705. }
  706. if (m_Reason == ERROR_SUCCESS)
  707. {
  708. m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
  709. if (m_hEvtLog == NULL)
  710. {
  711. if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  712. {
  713. SetSecurityLogPrivilege();
  714. m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
  715. }
  716. }
  717. m_bValid = (NULL != m_hEvtLog);
  718. if (!m_bValid)
  719. {
  720. m_Reason = GetLastError();
  721. }
  722. }
  723. }
  724. CEventLogFile::~CEventLogFile()
  725. {
  726. if (0 != m_BuffLen)
  727. {
  728. delete [] m_Buffer;
  729. }
  730. if (NULL != m_hEvtLog)
  731. {
  732. CloseEventLog(m_hEvtLog);
  733. }
  734. }
  735. BOOL CEventLogFile::QueryRegForFileName(HKEY hk_Log, const wchar_t* valname, wchar_t** res, DWORD* dwType)
  736. {
  737. BOOL retVal = FALSE;
  738. *res = new wchar_t[MAX_PATH + 1];
  739. DWORD datalen = (MAX_PATH + 1) * sizeof(wchar_t);
  740. LONG status = RegQueryValueEx(hk_Log, valname,
  741. 0, dwType, (LPBYTE)(*res), &datalen);
  742. if (status != ERROR_SUCCESS)
  743. {
  744. if (status == ERROR_MORE_DATA)
  745. {
  746. delete [] *res;
  747. *res = new wchar_t[datalen];
  748. status = RegQueryValueEx(hk_Log, valname,
  749. 0, dwType, (LPBYTE)(*res), &datalen);
  750. }
  751. else
  752. {
  753. DebugOut(
  754. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  755. _T(__FILE__),__LINE__,
  756. L"CEventLogFile::QueryRegForFileName:Failed to get %s value\r\n",
  757. valname
  758. ) ;
  759. )
  760. }
  761. }
  762. if ((status == ERROR_SUCCESS) && ((*dwType == REG_EXPAND_SZ) || (*dwType == REG_SZ)))
  763. {
  764. retVal = TRUE;
  765. }
  766. else
  767. {
  768. delete [] *res;
  769. *res = NULL;
  770. DebugOut(
  771. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  772. _T(__FILE__),__LINE__,
  773. L"CEventLogFile::QueryRegForFileName:Failed\r\n"
  774. ) ;
  775. )
  776. }
  777. return retVal;
  778. }
  779. CStringW CEventLogFile :: ExpandFileName ( const wchar_t* filepath )
  780. {
  781. CStringW retVal ;
  782. DWORD cbExpand = ExpandEnvironmentStrings(filepath, NULL, 0);
  783. DWORD datalen = cbExpand ;
  784. wchar_t *fullpath = new wchar_t[datalen];
  785. cbExpand = ExpandEnvironmentStrings(filepath, fullpath, datalen);
  786. if (cbExpand == 0)
  787. {
  788. delete [] fullpath;
  789. }
  790. else
  791. {
  792. if ( cbExpand == datalen )
  793. {
  794. retVal = fullpath;
  795. delete [] fullpath;
  796. }
  797. else
  798. {
  799. delete [] fullpath;
  800. }
  801. }
  802. return retVal ;
  803. }
  804. DWORD CEventLogFile::GetFileNames(HKEY hk_Log, CStringW** names, const wchar_t* valname)
  805. {
  806. DWORD retVal = 0;
  807. wchar_t* path = NULL;
  808. DWORD dwType;
  809. if (QueryRegForFileName(hk_Log, valname, &path, &dwType) && (path != NULL))
  810. {
  811. //got the comma or semi-colon separated list
  812. //need to separate it into
  813. retVal = 1;
  814. wchar_t* tmp = wcspbrk(path, L",;");
  815. while (tmp != NULL)
  816. {
  817. //don't count chars at start of string!
  818. if (tmp != path)
  819. {
  820. retVal++;
  821. }
  822. while ((*tmp == L',') || (*tmp == L';'))
  823. {
  824. *tmp = L'\0';
  825. tmp++;
  826. }
  827. tmp = wcspbrk(tmp, L",;");
  828. }
  829. *names = new CStringW[retVal];
  830. tmp = path;
  831. for (int x = 0; x < retVal; x++)
  832. {
  833. while (*tmp == L'\0')
  834. {
  835. tmp++;
  836. }
  837. (*names)[x] = ExpandFileName(tmp);
  838. tmp += wcslen(tmp);
  839. }
  840. delete [] path;
  841. }
  842. return retVal;
  843. }
  844. CStringW CEventLogFile::GetFileName(HKEY hk_Log, const wchar_t* valname)
  845. {
  846. CStringW retVal;
  847. wchar_t* path = NULL;
  848. DWORD dwType;
  849. if (QueryRegForFileName(hk_Log, valname, &path, &dwType) && (path != NULL))
  850. {
  851. if (dwType == REG_EXPAND_SZ)
  852. {
  853. retVal = ExpandFileName( path );
  854. }
  855. else
  856. {
  857. retVal = path;
  858. }
  859. delete [] path;
  860. }
  861. return retVal;
  862. }
  863. BOOL CEventLogFile::SetSecurityLogPrivilege(BOOL bProcess, LPCWSTR privName)
  864. {
  865. BOOL bResult = TRUE;
  866. //only need the security mutex if not NT5
  867. DWORD dwVersion = GetVersion();
  868. if ( 5 > (DWORD)(LOBYTE(LOWORD(dwVersion))) )
  869. {
  870. bResult = ObtainedSerialAccess(CNTEventProvider::g_secMutex);
  871. }
  872. if (bResult)
  873. {
  874. HANDLE hToken = NULL;
  875. if (bProcess)
  876. {
  877. bResult = OpenProcessToken(GetCurrentProcess(),
  878. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  879. &hToken);
  880. if ( ! bResult )
  881. {
  882. DWORD t_LastError = GetLastError () ;
  883. DebugOut(
  884. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  885. _T(__FILE__),__LINE__,
  886. L"CEventLogFile::SetSecurityLogPrivilege:Failed to open process token: Error %lx\r\n",
  887. t_LastError
  888. ) ;
  889. )
  890. }
  891. HANDLE hThreadToken = 0 ;
  892. bResult = OpenThreadToken(GetCurrentThread(),
  893. TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE |TOKEN_QUERY,
  894. TRUE, &hToken);
  895. if ( bResult)
  896. {
  897. DebugOut(
  898. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  899. _T(__FILE__),__LINE__,
  900. L"CEventLogFile::SetSecurityLogPrivilege:Thread Token Present\r\n"
  901. ) ;
  902. )
  903. }
  904. else
  905. {
  906. DebugOut(
  907. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  908. _T(__FILE__),__LINE__,
  909. L"CEventLogFile::SetSecurityLogPrivilege:Thread Token Missing\r\n"
  910. ) ;
  911. )
  912. }
  913. CloseHandle ( hThreadToken ) ;
  914. }
  915. else
  916. {
  917. bResult = OpenThreadToken(GetCurrentThread(),
  918. TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE |TOKEN_QUERY,
  919. TRUE, &hToken);
  920. }
  921. if (bResult)
  922. {
  923. // Enable Security Privilege...
  924. LUID Luid;
  925. bResult = LookupPrivilegeValue(NULL, privName, &Luid);
  926. if (bResult)
  927. {
  928. TOKEN_PRIVILEGES newPriv;
  929. newPriv.PrivilegeCount = 1;
  930. newPriv.Privileges[0].Luid = Luid;
  931. newPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  932. bResult = AdjustTokenPrivileges(hToken, // TokenHandle
  933. FALSE, // DisableAllPrivileges
  934. &newPriv, // NewState (OPTIONAL)
  935. NULL, // BufferLength
  936. NULL, // PreviousState
  937. NULL); // ReturnLength
  938. DWORD dwErr = GetLastError();
  939. if (dwErr != ERROR_SUCCESS)
  940. {
  941. bResult = FALSE;
  942. }
  943. }
  944. if (hToken != NULL)
  945. {
  946. CloseHandle( hToken );
  947. }
  948. }
  949. if ( 5 > (DWORD)(LOBYTE(LOWORD(dwVersion))) )
  950. {
  951. ReleaseSerialAccess(CNTEventProvider::g_secMutex);
  952. }
  953. }
  954. return bResult;
  955. }
  956. CStringW CEventLogFile::GetLogName(const WCHAR* file_name)
  957. {
  958. // open registry for log names
  959. CStringW retVal;
  960. if (file_name == NULL)
  961. {
  962. return retVal;
  963. }
  964. HKEY hkResult;
  965. LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  966. EVENTLOG_BASE, 0,
  967. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  968. &hkResult);
  969. if (status != ERROR_SUCCESS)
  970. {
  971. DebugOut(
  972. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  973. _T(__FILE__),__LINE__,
  974. L"CEventLogFile::GetLogName:Failed to open registry: Error %lx\r\n",
  975. status
  976. ) ;
  977. )
  978. return retVal;
  979. }
  980. DWORD iValue = 0;
  981. WCHAR t_logname[MAX_PATH+1];
  982. DWORD t_lognameSize = MAX_PATH;
  983. // read all entries under this key to find all logfiles...
  984. while ((status = RegEnumKey(hkResult, iValue, t_logname, t_lognameSize)) != ERROR_NO_MORE_ITEMS)
  985. {
  986. // if error during read
  987. if (status != ERROR_SUCCESS)
  988. {
  989. DebugOut(
  990. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  991. _T(__FILE__),__LINE__,
  992. L"CEventLogFile::GetLogName:Failed while enumerating registry: Error %lx\r\n",
  993. status
  994. ) ;
  995. )
  996. // indicate error
  997. break;
  998. }
  999. //open logfile key
  1000. HKEY hkLog;
  1001. if (ERROR_SUCCESS == RegOpenKeyEx(hkResult, t_logname, 0, KEY_QUERY_VALUE, &hkLog))
  1002. {
  1003. CStringW fname = GetFileName(hkLog);
  1004. RegCloseKey(hkLog);
  1005. if (!fname.IsEmpty() && (0 == _wcsicmp(fname, file_name)))
  1006. {
  1007. retVal = t_logname;
  1008. break;
  1009. }
  1010. }
  1011. // read next parameter
  1012. iValue++;
  1013. } // end while
  1014. RegCloseKey(hkResult);
  1015. return retVal;
  1016. }
  1017. void CEventLogFile::RefreshHandle()
  1018. {
  1019. m_LogLock.Lock();
  1020. if (NULL != m_hEvtLog)
  1021. {
  1022. CloseEventLog(m_hEvtLog);
  1023. }
  1024. m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
  1025. if (m_hEvtLog == NULL)
  1026. {
  1027. if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  1028. {
  1029. SetSecurityLogPrivilege();
  1030. m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
  1031. }
  1032. }
  1033. m_LogLock.Unlock();
  1034. if (NULL != m_hEvtLog)
  1035. {
  1036. m_bValid = TRUE;
  1037. m_Reason = 0;
  1038. }
  1039. else
  1040. {
  1041. DebugOut(
  1042. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1043. _T(__FILE__),__LINE__,
  1044. L"CEventLogFile::RefreshHandle:Invalid log\r\n"
  1045. ) ;
  1046. )
  1047. m_bValid = FALSE;
  1048. m_Reason = GetLastError();
  1049. }
  1050. }
  1051. DWORD CEventLogFile::FindOldEvent(DWORD evtID, const wchar_t* source, DWORD* recID, time_t offset)
  1052. {
  1053. DWORD dwRet = 0;
  1054. time_t timeVal;
  1055. if (offset > 0)
  1056. {
  1057. time(&timeVal);
  1058. timeVal -= offset;
  1059. }
  1060. DWORD dwEventSize = 0;
  1061. DWORD lastErr = ReadRecord(0, &dwEventSize, TRUE);
  1062. if (0 != lastErr)
  1063. {
  1064. if (lastErr != ERROR_HANDLE_EOF)
  1065. {
  1066. DebugOut(
  1067. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1068. _T(__FILE__),__LINE__,
  1069. L"CEventLogFile::FindOldEvent:Log no longer valid\r\n"
  1070. ) ;
  1071. )
  1072. m_bValid = FALSE;
  1073. }
  1074. }
  1075. else
  1076. {
  1077. while (TRUE)
  1078. {
  1079. if (lastErr != 0)
  1080. {
  1081. if (lastErr != ERROR_HANDLE_EOF)
  1082. {
  1083. m_bValid = FALSE;
  1084. DebugOut(
  1085. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1086. _T(__FILE__),__LINE__,
  1087. L"CEventLogFile::FindOldEvent:Log no longer valid\r\n"
  1088. ) ;
  1089. )
  1090. }
  1091. break;
  1092. }
  1093. else
  1094. {
  1095. PEVENTLOGRECORD EventBuffer = (PEVENTLOGRECORD)m_Buffer;
  1096. BOOL bDone = FALSE;
  1097. while (dwEventSize != 0)
  1098. {
  1099. //eventid and sourcename identify event
  1100. if ((source != NULL) && (evtID == EventBuffer->EventID) &&
  1101. (0 == _wcsicmp(source,
  1102. (const wchar_t*)((UCHAR*)EventBuffer + sizeof(EVENTLOGRECORD))
  1103. )
  1104. )
  1105. )
  1106. {
  1107. if (offset > 0)
  1108. {
  1109. if (EventBuffer->TimeWritten < timeVal)
  1110. {
  1111. bDone = TRUE;
  1112. break;
  1113. }
  1114. }
  1115. dwRet = EventBuffer->TimeWritten;
  1116. if (recID != NULL)
  1117. {
  1118. *recID = EventBuffer->RecordNumber;
  1119. }
  1120. bDone = TRUE;
  1121. break;
  1122. }
  1123. else
  1124. {
  1125. if (offset > 0)
  1126. {
  1127. if (EventBuffer->TimeWritten < timeVal)
  1128. {
  1129. bDone = TRUE;
  1130. break;
  1131. }
  1132. else
  1133. {
  1134. if (recID != NULL)
  1135. {
  1136. *recID = EventBuffer->RecordNumber;
  1137. }
  1138. }
  1139. }
  1140. }
  1141. // drop by length of this record and point to next record
  1142. dwEventSize -= EventBuffer->Length;
  1143. EventBuffer = (PEVENTLOGRECORD) ((UCHAR*) EventBuffer + EventBuffer->Length);
  1144. }
  1145. if (bDone)
  1146. {
  1147. break;
  1148. }
  1149. else
  1150. {
  1151. lastErr = ReadRecord(0, &dwEventSize, TRUE);
  1152. }
  1153. }
  1154. }
  1155. }
  1156. return dwRet;
  1157. }
  1158. BOOL CEventLogFile::GetLastRecordID(DWORD& rec, DWORD& numrecs)
  1159. {
  1160. rec = 0;
  1161. numrecs = 0;
  1162. m_LogLock.Lock();
  1163. if (!GetNumberOfEventLogRecords(m_hEvtLog, &numrecs))
  1164. {
  1165. m_LogLock.Unlock();
  1166. return FALSE;
  1167. }
  1168. if (numrecs != 0)
  1169. {
  1170. DWORD last_rec = 0;
  1171. if (!GetOldestEventLogRecord(m_hEvtLog, &last_rec))
  1172. {
  1173. m_LogLock.Unlock();
  1174. return FALSE;
  1175. }
  1176. if (0xFFFFFFFF - last_rec >= numrecs)
  1177. {
  1178. rec = numrecs + last_rec - 1;
  1179. }
  1180. else
  1181. {
  1182. //we have to guard the overflow...
  1183. rec = numrecs - (0xFFFFFFFF - last_rec) - 1;
  1184. }
  1185. }
  1186. m_LogLock.Unlock();
  1187. return TRUE;
  1188. }
  1189. DWORD CEventLogFile::ReadRecord(DWORD recID, DWORD* dwBytesRead, BOOL b_Back)
  1190. {
  1191. if (NULL != dwBytesRead)
  1192. {
  1193. *dwBytesRead = 0;
  1194. }
  1195. DWORD dwFlags;
  1196. if (recID == 0)
  1197. {
  1198. dwFlags = EVENTLOG_SEQUENTIAL_READ;
  1199. }
  1200. else
  1201. {
  1202. dwFlags = EVENTLOG_SEEK_READ;
  1203. }
  1204. if (b_Back)
  1205. {
  1206. dwFlags = dwFlags | EVENTLOG_BACKWARDS_READ;
  1207. }
  1208. else
  1209. {
  1210. dwFlags = dwFlags | EVENTLOG_FORWARDS_READ;
  1211. }
  1212. m_bBuffer = TRUE;
  1213. if (0 == m_BuffLen)
  1214. {
  1215. m_BuffLen = 2048;
  1216. m_Buffer = new BYTE[m_BuffLen];
  1217. }
  1218. DWORD dwRead = 0;
  1219. DWORD dwNext = 0;
  1220. m_LogLock.Lock();
  1221. if ( !ReadEventLog(m_hEvtLog,
  1222. dwFlags,
  1223. recID,
  1224. m_Buffer,
  1225. m_BuffLen,
  1226. &dwRead,
  1227. &dwNext))
  1228. {
  1229. DWORD err = GetLastError();
  1230. if (ERROR_INSUFFICIENT_BUFFER == err)
  1231. {
  1232. delete [] m_Buffer;
  1233. m_Buffer = NULL;
  1234. m_BuffLen = 5*dwNext;
  1235. m_Buffer = new BYTE[m_BuffLen];
  1236. if ( !ReadEventLog(m_hEvtLog,
  1237. dwFlags,
  1238. recID,
  1239. m_Buffer,
  1240. m_BuffLen,
  1241. &dwRead,
  1242. &dwNext))
  1243. {
  1244. m_LogLock.Unlock();
  1245. return GetLastError();
  1246. }
  1247. }
  1248. else
  1249. {
  1250. m_LogLock.Unlock();
  1251. return err;
  1252. }
  1253. }
  1254. if (NULL != dwBytesRead)
  1255. {
  1256. *dwBytesRead = dwRead;
  1257. }
  1258. m_bBuffer = TRUE;
  1259. m_LogLock.Unlock();
  1260. return 0;
  1261. }
  1262. DWORD CEventLogFile::ReadFirstRecord()
  1263. {
  1264. DWORD last_rec = 0;
  1265. DWORD dwRead = 0;
  1266. m_bValid = FALSE;
  1267. m_LogLock.Lock();
  1268. BOOL bTest = GetOldestEventLogRecord(m_hEvtLog, &last_rec);
  1269. m_LogLock.Unlock();
  1270. if (bTest)
  1271. {
  1272. DWORD lastErr = ReadRecord(last_rec, &dwRead);
  1273. if (0 != lastErr)
  1274. {
  1275. if (lastErr == ERROR_HANDLE_EOF)
  1276. {
  1277. m_bValid = TRUE;
  1278. }
  1279. }
  1280. else
  1281. {
  1282. m_bValid = TRUE;
  1283. }
  1284. }
  1285. else
  1286. {
  1287. DebugOut(
  1288. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1289. _T(__FILE__),__LINE__,
  1290. L"CEventLogFile::ReadFirstRecord:Failed to get oldest record\r\n"
  1291. ) ;
  1292. )
  1293. }
  1294. return dwRead;
  1295. }
  1296. void CEventLogFile::ReadLastRecord()
  1297. {
  1298. DWORD recID = 0;
  1299. DWORD numRecs = 0;
  1300. m_bValid = FALSE;
  1301. if (GetLastRecordID(recID, numRecs))
  1302. {
  1303. DWORD lastErr = ReadRecord(recID);
  1304. if (0 != lastErr)
  1305. {
  1306. if (lastErr == ERROR_HANDLE_EOF)
  1307. {
  1308. m_bValid = TRUE;
  1309. }
  1310. else
  1311. {
  1312. DebugOut(
  1313. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1314. _T(__FILE__),__LINE__,
  1315. L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
  1316. ) ;
  1317. )
  1318. }
  1319. }
  1320. else
  1321. {
  1322. while (0 == (lastErr = ReadRecord(0)));
  1323. if (lastErr == ERROR_HANDLE_EOF)
  1324. {
  1325. m_bValid = TRUE;
  1326. }
  1327. else
  1328. {
  1329. DebugOut(
  1330. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1331. _T(__FILE__),__LINE__,
  1332. L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
  1333. ) ;
  1334. )
  1335. }
  1336. }
  1337. }
  1338. else
  1339. {
  1340. DebugOut(
  1341. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1342. _T(__FILE__),__LINE__,
  1343. L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
  1344. ) ;
  1345. )
  1346. }
  1347. }
  1348. HANDLE CEventLogFile::OpenLocalEventLog(LPCWSTR a_log, DWORD *a_Reason)
  1349. {
  1350. HANDLE retVal = NULL;
  1351. if (a_Reason)
  1352. {
  1353. *a_Reason = 0;
  1354. }
  1355. HKEY hkLog;
  1356. CStringW log(EVENTLOG_BASE);
  1357. log += L"\\";
  1358. log += a_log;
  1359. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, log, 0, KEY_READ, &hkLog))
  1360. {
  1361. *a_Reason = ERROR_FILE_NOT_FOUND;
  1362. }
  1363. else
  1364. {
  1365. RegCloseKey(hkLog);
  1366. retVal = OpenEventLog(NULL, a_log);
  1367. DWORD t_dwErr = GetLastError();
  1368. if (retVal == NULL)
  1369. {
  1370. if (t_dwErr == ERROR_PRIVILEGE_NOT_HELD)
  1371. {
  1372. SetSecurityLogPrivilege();
  1373. retVal = OpenEventLog(NULL, a_log);
  1374. t_dwErr = GetLastError();
  1375. }
  1376. else if (a_Reason)
  1377. {
  1378. *a_Reason = t_dwErr;
  1379. }
  1380. }
  1381. if ((NULL == retVal) && a_Reason && (*a_Reason == 0))
  1382. {
  1383. *a_Reason = t_dwErr;
  1384. }
  1385. }
  1386. return retVal;
  1387. }
  1388. CMonitoredEventLogFile::CMonitoredEventLogFile(CEventProviderManager* parent, const WCHAR* logname)
  1389. : ProvTaskObject(), CEventLogFile(logname, FALSE), m_Class (NULL)
  1390. {
  1391. InterlockedIncrement(&(CNTEventProviderClassFactory::objectsInProgress));
  1392. VariantInit(&m_VpsdSelfRel);
  1393. m_RecID = 0;
  1394. if (parent != NULL)
  1395. {
  1396. m_parent = parent;
  1397. }
  1398. else
  1399. {
  1400. m_bValid = FALSE;
  1401. }
  1402. if (IsValid())
  1403. {
  1404. ReadLastRecord();
  1405. if (IsValid())
  1406. {
  1407. m_LogLock.Lock();
  1408. m_bValid = NotifyChangeEventLog(m_hEvtLog, GetHandle());
  1409. m_bValid = m_bValid && SetEventDescriptor();
  1410. m_LogLock.Unlock();
  1411. }
  1412. }
  1413. if (!m_bValid)
  1414. {
  1415. DebugOut(
  1416. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1417. _T(__FILE__),__LINE__,
  1418. L"CMonitoredEventLogFile::CMonitoredEventLogFile:Invalid log created\r\n"
  1419. ) ;
  1420. )
  1421. }
  1422. }
  1423. CMonitoredEventLogFile::~CMonitoredEventLogFile()
  1424. {
  1425. if (m_Class != NULL)
  1426. {
  1427. m_Class->Release();
  1428. }
  1429. VariantClear(&m_VpsdSelfRel);
  1430. InterlockedDecrement(&(CNTEventProviderClassFactory::objectsInProgress));
  1431. }
  1432. void CMonitoredEventLogFile::RefreshHandle()
  1433. {
  1434. CEventLogFile::RefreshHandle();
  1435. if (IsValid())
  1436. {
  1437. m_LogLock.Lock();
  1438. m_bValid = NotifyChangeEventLog(m_hEvtLog, GetHandle());
  1439. m_LogLock.Unlock();
  1440. }
  1441. if (!m_bValid)
  1442. {
  1443. DebugOut(
  1444. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1445. _T(__FILE__),__LINE__,
  1446. L"CMonitoredEventLogFile::RefreshHandle:Invalid log\r\n"
  1447. ) ;
  1448. )
  1449. }
  1450. }
  1451. BOOL CMonitoredEventLogFile::GenerateInstance(IWbemClassObject** ppEvtInst,
  1452. IWbemClassObject* pEmbedObj)
  1453. {
  1454. HRESULT hr;
  1455. if ((ppEvtInst == NULL) || (pEmbedObj == NULL))
  1456. {
  1457. DebugOut(
  1458. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1459. _T(__FILE__),__LINE__,
  1460. L"CMonitoredEventLogFile::GenerateInstance:Invalid parameter\r\n"
  1461. ) ;
  1462. )
  1463. return FALSE;
  1464. }
  1465. else
  1466. {
  1467. *ppEvtInst = NULL;
  1468. }
  1469. if (m_Class == NULL)
  1470. {
  1471. BSTR path = SysAllocString(EVENT_CLASS);
  1472. IWbemServices* ns = m_parent->GetNamespacePtr();
  1473. if (ns == NULL)
  1474. {
  1475. hr = WBEM_E_FAILED;
  1476. }
  1477. else
  1478. {
  1479. hr = ns->GetObject(path, 0, NULL, &m_Class, NULL);
  1480. SysFreeString(path);
  1481. ns->Release();
  1482. }
  1483. if (FAILED(hr))
  1484. {
  1485. m_Class = NULL;
  1486. DebugOut(
  1487. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1488. _T(__FILE__),__LINE__,
  1489. L"CMonitoredEventLogFile::GenerateInstance:Failed to get class object\r\n"
  1490. ) ;
  1491. )
  1492. return FALSE;
  1493. }
  1494. }
  1495. hr = m_Class->SpawnInstance(0, ppEvtInst);
  1496. if (FAILED(hr))
  1497. {
  1498. m_Class->Release();
  1499. m_Class = NULL;
  1500. DebugOut(
  1501. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1502. _T(__FILE__),__LINE__,
  1503. L"CMonitoredEventLogFile::GenerateInstance:Failed to spawn instance\r\n"
  1504. ) ;
  1505. )
  1506. return FALSE;
  1507. }
  1508. hr = (*ppEvtInst)->Put(SD_PROP, 0, &m_VpsdSelfRel, 0);
  1509. if (FAILED(hr))
  1510. {
  1511. (*ppEvtInst)->Release();
  1512. *ppEvtInst = NULL;
  1513. DebugOut(
  1514. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1515. _T(__FILE__),__LINE__,
  1516. L"CMonitoredEventLogFile::GenerateInstance:Failed to set security descriptor into event\r\n"
  1517. ) ;
  1518. )
  1519. return FALSE;
  1520. }
  1521. VARIANT v;
  1522. VariantInit(&v);
  1523. #ifdef STILL_DISPATCH
  1524. v.vt = VT_DISPATCH;
  1525. v.pdispVal = pEmbedObj;
  1526. #else
  1527. v.vt = VT_UNKNOWN;
  1528. v.punkVal = pEmbedObj;
  1529. #endif
  1530. pEmbedObj->AddRef();
  1531. hr = (*ppEvtInst)->Put(TARGET_PROP, 0, &v, 0);
  1532. VariantClear(&v); // will call release on value stored in variant
  1533. if (FAILED(hr))
  1534. {
  1535. (*ppEvtInst)->Release();
  1536. *ppEvtInst = NULL;
  1537. DebugOut(
  1538. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1539. _T(__FILE__),__LINE__,
  1540. L"CMonitoredEventLogFile::GenerateInstance:Failed to embed target instance into event\r\n"
  1541. ) ;
  1542. )
  1543. return FALSE;
  1544. }
  1545. return TRUE;
  1546. }
  1547. void CMonitoredEventLogFile::Process()
  1548. {
  1549. SetStructuredExceptionHandler seh;
  1550. try
  1551. {
  1552. //Read and process the eventlog
  1553. DWORD dwEventSize = 0;
  1554. DWORD err = ReadRecord(m_RecID, &dwEventSize);
  1555. m_RecID = 0;
  1556. while (TRUE)
  1557. {
  1558. if (err != 0)
  1559. {
  1560. if (err == ERROR_HANDLE_EOF)
  1561. {
  1562. break;
  1563. }
  1564. else
  1565. {
  1566. RefreshHandle();
  1567. if (!m_bValid)
  1568. {
  1569. //log cannot be monitored
  1570. Complete();
  1571. DebugOut(
  1572. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1573. _T(__FILE__),__LINE__,
  1574. L"CMonitoredEventLogFile::Process:log cannot be read\r\n"
  1575. ) ;
  1576. )
  1577. break;
  1578. }
  1579. if (err == ERROR_EVENTLOG_FILE_CHANGED)
  1580. {
  1581. err = 0;
  1582. continue;
  1583. }
  1584. else
  1585. {
  1586. ReadLastRecord();
  1587. if (!m_bValid)
  1588. {
  1589. //log cannot be monitored
  1590. DebugOut(
  1591. CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
  1592. _T(__FILE__),__LINE__,
  1593. L"CMonitoredEventLogFile::Process:log cannot be read\r\n"
  1594. ) ;
  1595. )
  1596. Complete();
  1597. break;
  1598. }
  1599. }
  1600. }
  1601. break;
  1602. }
  1603. else
  1604. {
  1605. PEVENTLOGRECORD EventBuffer = (PEVENTLOGRECORD)m_Buffer;
  1606. while (dwEventSize != 0)
  1607. {
  1608. //generate records...
  1609. IWbemServices* ns = m_parent->GetNamespacePtr();
  1610. if (ns == NULL)
  1611. {
  1612. //no control objects!
  1613. return;
  1614. }
  1615. CEventlogRecord evtrec(m_EvtLogName, EventBuffer, ns);
  1616. ns->Release();
  1617. IWbemClassObject* pEmbedInst = NULL;
  1618. if (evtrec.GenerateInstance(&pEmbedInst))
  1619. {
  1620. IWbemClassObject* pEvtInst;
  1621. if (GenerateInstance(&pEvtInst, pEmbedInst))
  1622. {
  1623. m_parent->SendEvent(pEvtInst);
  1624. pEvtInst->Release();
  1625. }
  1626. pEmbedInst->Release();
  1627. }
  1628. // drop by length of this record and point to next record
  1629. dwEventSize -= EventBuffer->Length;
  1630. EventBuffer = (PEVENTLOGRECORD) ((UCHAR*) EventBuffer + EventBuffer->Length);
  1631. }
  1632. }
  1633. dwEventSize = 0;
  1634. err = ReadRecord(0, &dwEventSize);
  1635. }
  1636. }
  1637. catch(Structured_Exception e_SE)
  1638. {
  1639. try
  1640. {
  1641. Complete();
  1642. }
  1643. catch(...)
  1644. {
  1645. return;
  1646. }
  1647. }
  1648. catch(Heap_Exception e_HE)
  1649. {
  1650. try
  1651. {
  1652. Complete();
  1653. }
  1654. catch(...)
  1655. {
  1656. return;
  1657. }
  1658. }
  1659. catch(...)
  1660. {
  1661. try
  1662. {
  1663. Complete();
  1664. }
  1665. catch(...)
  1666. {
  1667. return;
  1668. }
  1669. }
  1670. }
  1671. static GENERIC_MAPPING LogFileObjectMapping = {
  1672. STANDARD_RIGHTS_READ | // Generic read
  1673. ELF_LOGFILE_READ |
  1674. WBEM_RIGHT_SUBSCRIBE,
  1675. STANDARD_RIGHTS_WRITE | // Generic write
  1676. ELF_LOGFILE_WRITE |
  1677. WBEM_RIGHT_SUBSCRIBE,
  1678. STANDARD_RIGHTS_EXECUTE | // Generic execute
  1679. ELF_LOGFILE_START |
  1680. ELF_LOGFILE_STOP |
  1681. ELF_LOGFILE_CONFIGURE |
  1682. WBEM_RIGHT_SUBSCRIBE,
  1683. ELF_LOGFILE_ALL_ACCESS | // Generic all
  1684. WBEM_RIGHT_SUBSCRIBE
  1685. };
  1686. BOOL CMonitoredEventLogFile::SetEventDescriptor()
  1687. {
  1688. BOOL retVal = FALSE;
  1689. DWORD NumberOfAcesToUse = 0;
  1690. //
  1691. // Logfile object specific access type
  1692. //
  1693. RTL_ACE_DATA AceData[ELF_LOGFILE_OBJECT_ACES] = {
  1694. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  1695. ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AnonymousLogonSid},
  1696. {ACCESS_DENIED_ACE_TYPE, 0, 0,
  1697. ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasGuestsSid},
  1698. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1699. ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_LocalSystemSid},
  1700. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1701. ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasAdminsSid},
  1702. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1703. ELF_LOGFILE_BACKUP, &CNTEventProvider::s_AliasBackupOpsSid},
  1704. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1705. ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasSystemOpsSid},
  1706. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1707. ELF_LOGFILE_READ | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_WorldSid},
  1708. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1709. ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasAdminsSid},
  1710. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1711. ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_LocalServiceSid},
  1712. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1713. ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_NetworkServiceSid},
  1714. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1715. ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasSystemOpsSid},
  1716. {ACCESS_ALLOWED_ACE_TYPE, 0, 0,
  1717. ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_WorldSid}
  1718. };
  1719. PRTL_ACE_DATA pAceData = NULL;
  1720. //
  1721. // NON_SECURE logfiles let anyone read/write to them, secure ones
  1722. // only let admins/local system do this. so for secure files we just
  1723. // don't use the last ACE
  1724. //
  1725. // Adjust the ACL start based on the passed GuestAccessRestriction flag.
  1726. // The first two aces deny all log access to guests and/or anonymous
  1727. // logons. The flag, GuestAccessRestriction, indicates that these two
  1728. // deny access aces should be applied. Note that the deny aces and the
  1729. // GuestAccessRestriction flag are not applicable to the security log,
  1730. // since users and anonymous logons, by default, do not have access.
  1731. //
  1732. DWORD cchBase = wcslen(EVENTLOG_BASE);
  1733. DWORD cchSize = cchBase + 1 + m_EvtLogName.GetLength() + 1;
  1734. wchar_t* buff = new wchar_t[ cchSize ];
  1735. StringCchCopyW ( buff, cchBase + 1, EVENTLOG_BASE );
  1736. StringCchCatW ( buff, cchSize, L"\\" );
  1737. StringCchCatW ( buff, cchSize, m_EvtLogName );
  1738. HKEY hkResult = NULL;
  1739. BOOL GuestAccessRestriction = TRUE;
  1740. DWORD dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1741. buff, 0,
  1742. KEY_READ,
  1743. &hkResult);
  1744. if (dwErr == ERROR_SUCCESS)
  1745. {
  1746. DWORD datalen = sizeof(DWORD);
  1747. DWORD dwType = 0;
  1748. DWORD dwVal = 0;
  1749. dwErr = RegQueryValueEx(hkResult, GUEST_ACCESS,
  1750. 0, &dwType, (LPBYTE) &dwVal, &datalen);
  1751. if ((dwErr == ERROR_SUCCESS) && (dwType == REG_DWORD))
  1752. {
  1753. if (dwVal == 0)
  1754. {
  1755. GuestAccessRestriction = FALSE;
  1756. }
  1757. }
  1758. RegCloseKey(hkResult);
  1759. }
  1760. DWORD Type = 0;
  1761. if (m_EvtLogName.CompareNoCase(SYSTEM_LOG) == 0)
  1762. {
  1763. Type = 1;
  1764. }
  1765. else if (m_EvtLogName.CompareNoCase(SECURITY_LOG) == 0)
  1766. {
  1767. Type = 2;
  1768. }
  1769. switch (Type)
  1770. {
  1771. case 2:
  1772. {
  1773. pAceData = AceData + 2; // Deny ACEs *not* applicable
  1774. NumberOfAcesToUse = 3;
  1775. }
  1776. break;
  1777. case 1:
  1778. {
  1779. if (GuestAccessRestriction)
  1780. {
  1781. pAceData = AceData; // Deny ACEs *applicable*
  1782. NumberOfAcesToUse = 10;
  1783. }
  1784. else
  1785. {
  1786. pAceData = AceData + 2; // Deny ACEs *not* applicable
  1787. NumberOfAcesToUse = 8;
  1788. }
  1789. }
  1790. break;
  1791. case 0:
  1792. default:
  1793. {
  1794. if (GuestAccessRestriction)
  1795. {
  1796. pAceData = AceData; // Deny ACEs *applicable*
  1797. NumberOfAcesToUse = 12;
  1798. }
  1799. else
  1800. {
  1801. pAceData = AceData + 2; // Deny ACEs *not* applicable
  1802. NumberOfAcesToUse = 10;
  1803. }
  1804. }
  1805. break;
  1806. }
  1807. PSECURITY_DESCRIPTOR psdSelfRel = NULL;
  1808. NTSTATUS Status = RtlCreateUserSecurityObject(
  1809. pAceData,
  1810. NumberOfAcesToUse,
  1811. CNTEventProvider::s_LocalSystemSid, // Owner
  1812. CNTEventProvider::s_LocalSystemSid, // Group
  1813. TRUE, // IsDirectoryObject
  1814. &LogFileObjectMapping,
  1815. &psdSelfRel);
  1816. if (NT_SUCCESS(Status) && psdSelfRel)
  1817. {
  1818. try
  1819. {
  1820. DWORD sdlen = GetSecurityDescriptorLength(psdSelfRel);
  1821. if (sdlen > 0)
  1822. {
  1823. SAFEARRAYBOUND rgsabound[1];
  1824. SAFEARRAY* psa = NULL;
  1825. UCHAR* pdata = NULL;
  1826. rgsabound[0].lLbound = 0;
  1827. rgsabound[0].cElements = sdlen;
  1828. psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
  1829. if (NULL != psa)
  1830. {
  1831. try
  1832. {
  1833. if (SUCCEEDED(SafeArrayAccessData(psa, (void **)&pdata)))
  1834. {
  1835. memcpy((void *)pdata, (void *)psdSelfRel, sdlen);
  1836. SafeArrayUnaccessData(psa);
  1837. m_VpsdSelfRel.vt = VT_ARRAY|VT_UI1;
  1838. m_VpsdSelfRel.parray = psa;
  1839. retVal = TRUE;
  1840. }
  1841. else
  1842. {
  1843. SafeArrayDestroy(psa);
  1844. psa = NULL;
  1845. }
  1846. }
  1847. catch(...)
  1848. {
  1849. SafeArrayDestroy(psa);
  1850. psa = NULL;
  1851. throw;
  1852. }
  1853. }
  1854. }
  1855. }
  1856. catch(...)
  1857. {
  1858. RtlDeleteSecurityObject(&psdSelfRel);
  1859. psdSelfRel = NULL;
  1860. }
  1861. RtlDeleteSecurityObject(&psdSelfRel);
  1862. psdSelfRel = NULL;
  1863. }
  1864. return retVal;
  1865. }