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
2219 lines
54 KiB
//***************************************************************************
|
|
|
|
//
|
|
|
|
// NTEVTLOGF.CPP
|
|
|
|
//
|
|
|
|
// Module: WBEM NT EVENT PROVIDER
|
|
|
|
//
|
|
|
|
// Purpose: Contains the Eventlog classes
|
|
|
|
//
|
|
|
|
// Copyright (c) 1996-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
//***************************************************************************
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <time.h>
|
|
#include <io.h>
|
|
#include <wbemtime.h>
|
|
|
|
CEventlogFileAttributes::CEventlogFileAttributes(const wchar_t* log):
|
|
m_logname(log),
|
|
m_retention (0),
|
|
m_fileSz (15000*1024)
|
|
{
|
|
m_sources.SetSize(0, 10);
|
|
}
|
|
|
|
|
|
CEventlogFileAttributes::~CEventlogFileAttributes()
|
|
{
|
|
LONG count = m_sources.GetSize();
|
|
|
|
if (count > 0)
|
|
{
|
|
for (LONG x = 0; x < count; x++)
|
|
{
|
|
delete m_sources[x];
|
|
}
|
|
|
|
m_sources.RemoveAll();
|
|
}
|
|
}
|
|
|
|
DWORD CEventlogFileAttributes::EventLogOperation (const wchar_t* archive, BOOL bClear,
|
|
WbemProvErrorObject &a_ErrorObject, BOOL &bSuccess)
|
|
{
|
|
DWORD retVal = ERROR_SUCCESS;
|
|
HANDLE hEventLog = OpenEventLog(NULL, m_logname);
|
|
|
|
if (hEventLog == NULL)
|
|
{
|
|
if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
CEventLogFile::SetSecurityLogPrivilege();
|
|
hEventLog = OpenEventLog(NULL, m_logname);
|
|
}
|
|
}
|
|
|
|
if (hEventLog == NULL)
|
|
{
|
|
retVal = GetLastError();
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::EventLogOperation:Failed to OpenEventLog %s with error %lx.\r\n",
|
|
m_logname, retVal
|
|
) ;
|
|
)
|
|
if (retVal == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
retVal = 0;
|
|
bSuccess = FALSE;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_ACCESS_DENIED ) ;
|
|
a_ErrorObject.SetMessage ( L"Failed to open the logfile" ) ;
|
|
a_ErrorObject.SetPrivilegeFailed();
|
|
a_ErrorObject.SetSecurityPrivRequired();
|
|
a_ErrorObject.SetSecurityPrivFailed();
|
|
|
|
if (!bClear)
|
|
{
|
|
a_ErrorObject.SetBackupPrivRequired();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bClear)
|
|
{
|
|
if (!ClearEventLog(hEventLog, archive))
|
|
{
|
|
retVal = GetLastError();
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::EventLogOperation:Failed to ClearEventLog %s with error %lx.\r\n",
|
|
m_logname, retVal
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (archive == NULL)
|
|
{
|
|
retVal = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else if (!BackupEventLog(hEventLog, archive))
|
|
{
|
|
retVal = GetLastError();
|
|
|
|
if (retVal == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
retVal = 0;
|
|
CEventLogFile::SetSecurityLogPrivilege(FALSE, SE_BACKUP_NAME);
|
|
|
|
if (!BackupEventLog(hEventLog, archive))
|
|
{
|
|
retVal = GetLastError();
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::EventLogOperation:Failed even after privilege set to BackupEventLog %s with error %lx.\r\n",
|
|
m_logname, retVal
|
|
) ;
|
|
)
|
|
if (retVal == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
retVal = 0;
|
|
bSuccess = FALSE;
|
|
a_ErrorObject.SetWbemStatus ( WBEM_E_ACCESS_DENIED ) ;
|
|
a_ErrorObject.SetMessage ( L"Opened the logfile but failed to back it up, privilege error" ) ;
|
|
a_ErrorObject.SetPrivilegeFailed();
|
|
a_ErrorObject.SetBackupPrivRequired();
|
|
a_ErrorObject.SetBackupPrivFailed();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::EventLogOperation:After privilege set, BackupEventLog %s succeeded.\r\n",
|
|
m_logname
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::EventLogOperation:Failed to BackupEventLog %s with error %lx.\r\n",
|
|
m_logname, retVal
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
|
|
CloseEventLog(hEventLog);
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
BOOL CEventlogFileAttributes::GenerateInstance(IWbemClassObject* pClassObj, IWbemClassObject* pAClassObj, IWbemClassObject** ppInst)
|
|
{
|
|
if (pClassObj == NULL)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::GenerateInstance:Invalid parameter - Return FALSE\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
|
|
if (ReadRegistry() != ERROR_SUCCESS)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::GenerateInstance:Failed to read registry values - Return FALSE\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT hr = pClassObj->SpawnInstance(0, ppInst);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::GenerateInstance:Failed to spawn instance - Return FALSE\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
|
|
//set the key properties, they are all in the super class
|
|
if (!SetSuperClassProperties(*ppInst))
|
|
{
|
|
//can't set the key, just return
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::GenerateInstance:Failed to set key values - Return FALSE\r\n"
|
|
) ;
|
|
)
|
|
|
|
(*ppInst)->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
//set the evtlog properties...
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = m_logname.AllocSysString();
|
|
hr = (*ppInst)->Put(PROP_LOGNAME, 0, &v, 0);
|
|
VariantClear(&v); // will call free v.bstrVal
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_I4;
|
|
v.lVal = m_fileSz;
|
|
hr = (*ppInst)->Put(PROP_MAXSZ, 0, &v, 0);
|
|
VariantClear(&v);
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_I4;
|
|
|
|
if ((m_retention > 0) && (m_retention < EVT_NEVER_AGE))
|
|
{
|
|
//turn into days
|
|
v.lVal = m_retention/EVT_UNITS_FROM_DAYS;
|
|
|
|
if (v.lVal > MAX_EVT_AGE)
|
|
{
|
|
v.lVal = MAX_EVT_AGE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
v.lVal = m_retention;
|
|
}
|
|
|
|
hr = (*ppInst)->Put(PROP_RETENTION, 0, &v, 0);
|
|
|
|
if (pAClassObj)
|
|
{
|
|
SetRetentionStr(pAClassObj, *ppInst, (DWORD)v.lVal);
|
|
}
|
|
|
|
VariantClear(&v);
|
|
|
|
HANDLE hEventLog = OpenEventLog(NULL, m_logname);
|
|
|
|
if (hEventLog == NULL)
|
|
{
|
|
if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
CEventLogFile::SetSecurityLogPrivilege();
|
|
hEventLog = OpenEventLog(NULL, m_logname);
|
|
}
|
|
}
|
|
|
|
if (hEventLog != NULL)
|
|
{
|
|
DWORD num_recs = 0;
|
|
|
|
if (GetNumberOfEventLogRecords(hEventLog, &num_recs))
|
|
{
|
|
VariantInit(&v);
|
|
v.vt = VT_I4;
|
|
v.lVal = num_recs;
|
|
hr = (*ppInst)->Put(PROP_NUMRECS, 0, &v, 0);
|
|
VariantClear(&v);
|
|
}
|
|
|
|
CloseEventLog(hEventLog);
|
|
}
|
|
|
|
LONG count = m_sources.GetSize();
|
|
|
|
if (count > 0)
|
|
{
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
SAFEARRAY* psa = NULL;
|
|
BSTR* pBstr = NULL;
|
|
rgsabound[0].lLbound = 0;
|
|
VariantInit(&v);
|
|
rgsabound[0].cElements = count;
|
|
psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
|
|
|
|
if (NULL != psa)
|
|
{
|
|
if (SUCCEEDED(SafeArrayAccessData(psa, (void **)&pBstr)))
|
|
{
|
|
for (LONG x = 0; x < count; x++)
|
|
{
|
|
pBstr[x] = m_sources[x]->AllocSysString();
|
|
delete m_sources[x];
|
|
m_sources[x] = NULL;
|
|
}
|
|
|
|
m_sources.RemoveAll();
|
|
SafeArrayUnaccessData(psa);
|
|
v.vt = VT_ARRAY|VT_BSTR;
|
|
v.parray = psa;
|
|
hr = (*ppInst)->Put(PROP_SOURCES, 0, &v, 0);
|
|
}
|
|
}
|
|
|
|
VariantClear(&v);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULONG CEventlogFileAttributes::GetIndex(wchar_t* indexStr, BOOL* bError)
|
|
{
|
|
#if 0
|
|
__int64 val = _wtoi64(indexStr);
|
|
#else
|
|
int val = _wtoi(indexStr);
|
|
#endif
|
|
*bError = FALSE;
|
|
ULONG index = 0;
|
|
|
|
switch (val)
|
|
{
|
|
case 0: //Always overwrite
|
|
{
|
|
index = 0;
|
|
break;
|
|
}
|
|
case 1: //1-365
|
|
{
|
|
index = 1;
|
|
break;
|
|
}
|
|
case EVT_NEVER_AGE: //0xffffffff
|
|
{
|
|
index = 2;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
*bError = TRUE;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
void CEventlogFileAttributes::SetRetentionStr(IWbemClassObject* pClassObj, IWbemClassObject* pInstObj, DWORD dwVal)
|
|
{
|
|
CStringW strRetentionArray[RETENTION_ARRAY_LEN];
|
|
|
|
if (CEventlogRecord::SetEnumArray(pClassObj, PROP_RETENTION_STR,(CStringW*) strRetentionArray,
|
|
RETENTION_ARRAY_LEN, (GetIndexFunc)GetIndex))
|
|
{
|
|
BSTR retStr = NULL;
|
|
|
|
if (dwVal == 0)
|
|
{
|
|
retStr = strRetentionArray[0].AllocSysString();
|
|
}
|
|
else if (dwVal == EVT_NEVER_AGE)
|
|
{
|
|
retStr = strRetentionArray[2].AllocSysString();
|
|
}
|
|
else
|
|
{
|
|
retStr = strRetentionArray[1].AllocSysString();
|
|
}
|
|
|
|
if (retStr != NULL)
|
|
{
|
|
VARIANT v;
|
|
VariantInit (&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = retStr;
|
|
HRESULT hr = pInstObj->Put(PROP_RETENTION_STR, 0, &v, 0);
|
|
VariantClear(&v);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CEventlogFileAttributes::SetSuperClassProperties(IWbemClassObject* pInst)
|
|
{
|
|
//failure to set any key property
|
|
//is an error, return FALSE!!
|
|
|
|
VARIANT v;
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = m_logpath.AllocSysString();
|
|
HRESULT hr = pInst->Put(PROP_NAME, 0, &v, 0);
|
|
VariantClear(&v);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = SysAllocString(VAL_FS_CRE_CLASS);
|
|
hr = pInst->Put(PROP_FS_CRE_CLASS, 0, &v, 0);
|
|
VariantClear(&v);
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = SysAllocString(NTEVTLOG_CLASS);
|
|
hr = pInst->Put(PROP_CRE_CLASS, 0, &v, 0);
|
|
VariantClear(&v);
|
|
|
|
VariantInit(&v);
|
|
v.vt = VT_BSTR;
|
|
v.bstrVal = SysAllocString(COMP_CLASS);
|
|
hr = pInst->Put(PROP_CS_CRE_CLASS, 0, &v, 0);
|
|
VariantClear(&v);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD CEventlogFileAttributes::UpdateRegistry(IWbemClassObject* pInst)
|
|
{
|
|
if (NULL == pInst)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//get the data to be written
|
|
VARIANT v;
|
|
HRESULT hr = pInst->Get(PROP_RETENTION, 0, &v,NULL, NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_retention = (DWORD)v.lVal;
|
|
VariantClear(&v);
|
|
|
|
if ((m_retention > MAX_EVT_AGE) && (m_retention < EVT_NEVER_AGE))
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Retention Data not in range\r\n"
|
|
) ;
|
|
)
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
if ((m_retention > 0) && (m_retention < EVT_NEVER_AGE))
|
|
{
|
|
m_retention = m_retention * EVT_UNITS_FROM_DAYS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Failed to get retention value from instance\r\n"
|
|
) ;
|
|
)
|
|
|
|
return (DWORD)hr;
|
|
}
|
|
|
|
hr = pInst->Get(PROP_MAXSZ, 0, &v,NULL, NULL);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fileSz = (DWORD)v.lVal;
|
|
VariantClear(&v);
|
|
|
|
if (m_fileSz < FILE_CHUNK_SZ)
|
|
{
|
|
m_fileSz = FILE_CHUNK_SZ;
|
|
}
|
|
else if (m_fileSz > MAX_EVT_LOG_SZ)
|
|
{
|
|
m_fileSz = MAX_EVT_LOG_SZ;
|
|
}
|
|
else
|
|
{
|
|
DWORD rem = m_fileSz % FILE_CHUNK_SZ;
|
|
|
|
if (rem != 0)
|
|
{
|
|
//need to round up to nearest file chunk size
|
|
DWORD x = m_fileSz / FILE_CHUNK_SZ;
|
|
m_fileSz = (++x) * FILE_CHUNK_SZ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Failed to get MaxFileSize value from instance\r\n"
|
|
) ;
|
|
)
|
|
return (DWORD)hr;
|
|
}
|
|
|
|
DWORD retVal;
|
|
CStringW strKey(EVENTLOG_BASE);
|
|
strKey += CStringW(L'\\');
|
|
strKey += m_logname;
|
|
|
|
HKEY hkResult;
|
|
//open the logfile's key for setting values
|
|
LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
strKey, 0,
|
|
KEY_SET_VALUE,
|
|
&hkResult);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
// indicate error
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Open registry to set new values. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
return status;
|
|
}
|
|
|
|
//set the values we read in...
|
|
status = RegSetValueEx(hkResult,
|
|
EVTLOG_REG_MAXSZ_VALUE, 0, REG_DWORD,
|
|
(CONST BYTE *) &m_fileSz, sizeof(DWORD));
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
// indicate error
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Failed to set new size. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
retVal = status;
|
|
}
|
|
else
|
|
{
|
|
retVal =(DWORD) RegSetValueEx(hkResult,
|
|
EVTLOG_REG_RETENTION_VALUE, 0, REG_DWORD,
|
|
(CONST BYTE *) &m_retention, sizeof(DWORD));
|
|
|
|
if (retVal != ERROR_SUCCESS)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::UpdateRegistry:Failed to set new retention policy. Error %lx\r\n",
|
|
retVal
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkResult);
|
|
return retVal;
|
|
}
|
|
|
|
|
|
DWORD CEventlogFileAttributes::ReadRegistry()
|
|
{
|
|
DWORD retVal;
|
|
CStringW strKey(EVENTLOG_BASE);
|
|
strKey += CStringW(L'\\');
|
|
strKey += m_logname;
|
|
HKEY hkResult;
|
|
|
|
//open the logfile's key for read
|
|
LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
strKey, 0,
|
|
KEY_QUERY_VALUE,
|
|
&hkResult);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
// indicate error
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to open registry. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
|
|
retVal = status;
|
|
}
|
|
else
|
|
{
|
|
//first get the file value
|
|
m_logpath = CEventLogFile::GetFileName(hkResult);
|
|
DWORD datalen;
|
|
DWORD dwType;
|
|
wchar_t* data;
|
|
|
|
if (m_logpath.IsEmpty())
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to resolve log file name\r\n"
|
|
) ;
|
|
)
|
|
retVal = ERROR_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
datalen = sizeof(m_fileSz);
|
|
status = RegQueryValueEx(hkResult, EVTLOG_REG_MAXSZ_VALUE,
|
|
0, &dwType, (LPBYTE) &m_fileSz, &datalen);
|
|
|
|
if ( ERROR_SUCCESS == status )
|
|
{
|
|
retVal = 0;
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == status )
|
|
{
|
|
//
|
|
// we assume 512KB (same story with nt event viewer)
|
|
// was set in constructor
|
|
//
|
|
|
|
retVal = 0;
|
|
}
|
|
else if( REG_DWORD != dwType )
|
|
{
|
|
retVal = ERROR_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to read size. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
retVal = status;
|
|
}
|
|
|
|
if ( 0 == retVal )
|
|
{
|
|
datalen = sizeof(m_retention);
|
|
status = RegQueryValueEx(hkResult, EVTLOG_REG_RETENTION_VALUE,
|
|
0, &dwType, (LPBYTE) &m_retention, &datalen);
|
|
|
|
if ( ERROR_SUCCESS == status )
|
|
{
|
|
retVal = 0;
|
|
}
|
|
else if ( ERROR_FILE_NOT_FOUND == status )
|
|
{
|
|
//
|
|
// we assume 7 dyas (same story with nt event viewer)
|
|
// was set in constructor
|
|
//
|
|
|
|
retVal = 0;
|
|
}
|
|
else if( REG_DWORD != dwType )
|
|
{
|
|
retVal = ERROR_INVALID_DATA;
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to read retention. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
retVal = status;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (retVal == 0)
|
|
{
|
|
data = new wchar_t[MAX_PATH + 1];
|
|
datalen = (MAX_PATH + 1) * sizeof(wchar_t);
|
|
status = RegQueryValueEx(hkResult, EVTLOG_REG_SOURCES_VALUE,
|
|
0, &dwType, (LPBYTE) data, &datalen);
|
|
|
|
if (((status == ERROR_SUCCESS) || (status == ERROR_MORE_DATA)) &&
|
|
(dwType == REG_MULTI_SZ))
|
|
{
|
|
if (status == ERROR_MORE_DATA)
|
|
{
|
|
delete [] data;
|
|
data = new wchar_t[datalen];
|
|
status = RegQueryValueEx(hkResult, EVTLOG_REG_SOURCES_VALUE,
|
|
0, &dwType, (LPBYTE) data, &datalen);
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
wchar_t* tmp = data;
|
|
int x = 0;
|
|
|
|
while (*tmp != L'\0')
|
|
{
|
|
CStringW* tmpstr = new CStringW(tmp);
|
|
m_sources.SetAtGrow(x++, tmpstr);
|
|
tmp += wcslen(tmp) + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to read sources. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventlogFileAttributes::ReadRegistry:Failed to read sources. Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
|
|
}
|
|
|
|
delete [] data;
|
|
}
|
|
|
|
RegCloseKey(hkResult);
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
CEventLogFile::CEventLogFile(const WCHAR* logname, BOOL bVerify) : m_hEvtLog(NULL), m_BuffLen (0)
|
|
{
|
|
m_Reason = ERROR_SUCCESS;
|
|
m_EvtLogName = logname;
|
|
m_bValid = FALSE;
|
|
m_bBuffer = FALSE;
|
|
m_hEvtLog = NULL;
|
|
m_Buffer = NULL;
|
|
|
|
if (bVerify)
|
|
{
|
|
if (logname != NULL)
|
|
{
|
|
DWORD cchBase = wcslen(EVENTLOG_BASE);
|
|
DWORD cchSize = cchBase + 1 + wcslen(logname) + 1;
|
|
wchar_t* buff = new wchar_t[ cchSize ];
|
|
StringCchCopyW ( buff, cchBase + 1, EVENTLOG_BASE );
|
|
StringCchCatW ( buff, cchSize, L"\\" );
|
|
StringCchCatW ( buff, cchSize, logname);
|
|
|
|
HKEY hkResult = NULL;
|
|
m_Reason = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
buff, 0,
|
|
KEY_READ,
|
|
&hkResult);
|
|
|
|
if (m_Reason == ERROR_SUCCESS)
|
|
{
|
|
if (hkResult != NULL)
|
|
{
|
|
RegCloseKey(hkResult);
|
|
hkResult = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_Reason = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
delete [] buff;
|
|
buff = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_Reason = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
if (m_Reason == ERROR_SUCCESS)
|
|
{
|
|
m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
|
|
|
|
if (m_hEvtLog == NULL)
|
|
{
|
|
if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
SetSecurityLogPrivilege();
|
|
m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
|
|
}
|
|
}
|
|
|
|
m_bValid = (NULL != m_hEvtLog);
|
|
|
|
if (!m_bValid)
|
|
{
|
|
m_Reason = GetLastError();
|
|
}
|
|
}
|
|
}
|
|
|
|
CEventLogFile::~CEventLogFile()
|
|
{
|
|
if (0 != m_BuffLen)
|
|
{
|
|
delete [] m_Buffer;
|
|
}
|
|
|
|
if (NULL != m_hEvtLog)
|
|
{
|
|
CloseEventLog(m_hEvtLog);
|
|
}
|
|
}
|
|
|
|
BOOL CEventLogFile::QueryRegForFileName(HKEY hk_Log, const wchar_t* valname, wchar_t** res, DWORD* dwType)
|
|
{
|
|
BOOL retVal = FALSE;
|
|
*res = new wchar_t[MAX_PATH + 1];
|
|
DWORD datalen = (MAX_PATH + 1) * sizeof(wchar_t);
|
|
LONG status = RegQueryValueEx(hk_Log, valname,
|
|
0, dwType, (LPBYTE)(*res), &datalen);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
if (status == ERROR_MORE_DATA)
|
|
{
|
|
delete [] *res;
|
|
*res = new wchar_t[datalen];
|
|
status = RegQueryValueEx(hk_Log, valname,
|
|
0, dwType, (LPBYTE)(*res), &datalen);
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::QueryRegForFileName:Failed to get %s value\r\n",
|
|
valname
|
|
) ;
|
|
)
|
|
}
|
|
}
|
|
|
|
if ((status == ERROR_SUCCESS) && ((*dwType == REG_EXPAND_SZ) || (*dwType == REG_SZ)))
|
|
{
|
|
retVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
delete [] *res;
|
|
*res = NULL;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::QueryRegForFileName:Failed\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
CStringW CEventLogFile :: ExpandFileName ( const wchar_t* filepath )
|
|
{
|
|
CStringW retVal ;
|
|
DWORD cbExpand = ExpandEnvironmentStrings(filepath, NULL, 0);
|
|
DWORD datalen = cbExpand ;
|
|
wchar_t *fullpath = new wchar_t[datalen];
|
|
cbExpand = ExpandEnvironmentStrings(filepath, fullpath, datalen);
|
|
if (cbExpand == 0)
|
|
{
|
|
delete [] fullpath;
|
|
}
|
|
else
|
|
{
|
|
if ( cbExpand == datalen )
|
|
{
|
|
retVal = fullpath;
|
|
delete [] fullpath;
|
|
}
|
|
else
|
|
{
|
|
delete [] fullpath;
|
|
}
|
|
}
|
|
|
|
return retVal ;
|
|
}
|
|
|
|
DWORD CEventLogFile::GetFileNames(HKEY hk_Log, CStringW** names, const wchar_t* valname)
|
|
{
|
|
DWORD retVal = 0;
|
|
wchar_t* path = NULL;
|
|
DWORD dwType;
|
|
|
|
if (QueryRegForFileName(hk_Log, valname, &path, &dwType) && (path != NULL))
|
|
{
|
|
//got the comma or semi-colon separated list
|
|
//need to separate it into
|
|
retVal = 1;
|
|
wchar_t* tmp = wcspbrk(path, L",;");
|
|
|
|
while (tmp != NULL)
|
|
{
|
|
//don't count chars at start of string!
|
|
if (tmp != path)
|
|
{
|
|
retVal++;
|
|
}
|
|
|
|
while ((*tmp == L',') || (*tmp == L';'))
|
|
{
|
|
*tmp = L'\0';
|
|
tmp++;
|
|
}
|
|
|
|
tmp = wcspbrk(tmp, L",;");
|
|
}
|
|
|
|
*names = new CStringW[retVal];
|
|
tmp = path;
|
|
|
|
for (int x = 0; x < retVal; x++)
|
|
{
|
|
while (*tmp == L'\0')
|
|
{
|
|
tmp++;
|
|
}
|
|
|
|
(*names)[x] = ExpandFileName(tmp);
|
|
tmp += wcslen(tmp);
|
|
}
|
|
|
|
delete [] path;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
CStringW CEventLogFile::GetFileName(HKEY hk_Log, const wchar_t* valname)
|
|
{
|
|
CStringW retVal;
|
|
wchar_t* path = NULL;
|
|
DWORD dwType;
|
|
|
|
if (QueryRegForFileName(hk_Log, valname, &path, &dwType) && (path != NULL))
|
|
{
|
|
if (dwType == REG_EXPAND_SZ)
|
|
{
|
|
retVal = ExpandFileName( path );
|
|
}
|
|
else
|
|
{
|
|
retVal = path;
|
|
}
|
|
|
|
delete [] path;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
BOOL CEventLogFile::SetSecurityLogPrivilege(BOOL bProcess, LPCWSTR privName)
|
|
{
|
|
BOOL bResult = TRUE;
|
|
|
|
//only need the security mutex if not NT5
|
|
DWORD dwVersion = GetVersion();
|
|
|
|
if ( 5 > (DWORD)(LOBYTE(LOWORD(dwVersion))) )
|
|
{
|
|
bResult = ObtainedSerialAccess(CNTEventProvider::g_secMutex);
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
HANDLE hToken = NULL;
|
|
|
|
if (bProcess)
|
|
{
|
|
bResult = OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
|
&hToken);
|
|
|
|
if ( ! bResult )
|
|
{
|
|
DWORD t_LastError = GetLastError () ;
|
|
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::SetSecurityLogPrivilege:Failed to open process token: Error %lx\r\n",
|
|
t_LastError
|
|
) ;
|
|
)
|
|
}
|
|
|
|
HANDLE hThreadToken = 0 ;
|
|
bResult = OpenThreadToken(GetCurrentThread(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE |TOKEN_QUERY,
|
|
TRUE, &hToken);
|
|
|
|
|
|
if ( bResult)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::SetSecurityLogPrivilege:Thread Token Present\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::SetSecurityLogPrivilege:Thread Token Missing\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
|
|
CloseHandle ( hThreadToken ) ;
|
|
}
|
|
else
|
|
{
|
|
bResult = OpenThreadToken(GetCurrentThread(),
|
|
TOKEN_ADJUST_PRIVILEGES | TOKEN_IMPERSONATE |TOKEN_QUERY,
|
|
TRUE, &hToken);
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
// Enable Security Privilege...
|
|
LUID Luid;
|
|
bResult = LookupPrivilegeValue(NULL, privName, &Luid);
|
|
|
|
if (bResult)
|
|
{
|
|
TOKEN_PRIVILEGES newPriv;
|
|
newPriv.PrivilegeCount = 1;
|
|
newPriv.Privileges[0].Luid = Luid;
|
|
newPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
bResult = AdjustTokenPrivileges(hToken, // TokenHandle
|
|
FALSE, // DisableAllPrivileges
|
|
&newPriv, // NewState (OPTIONAL)
|
|
NULL, // BufferLength
|
|
NULL, // PreviousState
|
|
NULL); // ReturnLength
|
|
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
bResult = FALSE;
|
|
}
|
|
}
|
|
|
|
if (hToken != NULL)
|
|
{
|
|
CloseHandle( hToken );
|
|
}
|
|
}
|
|
|
|
if ( 5 > (DWORD)(LOBYTE(LOWORD(dwVersion))) )
|
|
{
|
|
ReleaseSerialAccess(CNTEventProvider::g_secMutex);
|
|
}
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
CStringW CEventLogFile::GetLogName(const WCHAR* file_name)
|
|
{
|
|
// open registry for log names
|
|
CStringW retVal;
|
|
|
|
if (file_name == NULL)
|
|
{
|
|
return retVal;
|
|
}
|
|
|
|
HKEY hkResult;
|
|
LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
EVENTLOG_BASE, 0,
|
|
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
|
|
&hkResult);
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::GetLogName:Failed to open registry: Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
return retVal;
|
|
}
|
|
|
|
DWORD iValue = 0;
|
|
WCHAR t_logname[MAX_PATH+1];
|
|
DWORD t_lognameSize = MAX_PATH;
|
|
|
|
// read all entries under this key to find all logfiles...
|
|
while ((status = RegEnumKey(hkResult, iValue, t_logname, t_lognameSize)) != ERROR_NO_MORE_ITEMS)
|
|
{
|
|
// if error during read
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::GetLogName:Failed while enumerating registry: Error %lx\r\n",
|
|
status
|
|
) ;
|
|
)
|
|
// indicate error
|
|
break;
|
|
}
|
|
|
|
//open logfile key
|
|
HKEY hkLog;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(hkResult, t_logname, 0, KEY_QUERY_VALUE, &hkLog))
|
|
{
|
|
CStringW fname = GetFileName(hkLog);
|
|
RegCloseKey(hkLog);
|
|
|
|
if (!fname.IsEmpty() && (0 == _wcsicmp(fname, file_name)))
|
|
{
|
|
retVal = t_logname;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// read next parameter
|
|
iValue++;
|
|
|
|
} // end while
|
|
|
|
RegCloseKey(hkResult);
|
|
return retVal;
|
|
}
|
|
|
|
void CEventLogFile::RefreshHandle()
|
|
{
|
|
m_LogLock.Lock();
|
|
|
|
if (NULL != m_hEvtLog)
|
|
{
|
|
CloseEventLog(m_hEvtLog);
|
|
}
|
|
|
|
m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
|
|
|
|
if (m_hEvtLog == NULL)
|
|
{
|
|
if (GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
SetSecurityLogPrivilege();
|
|
m_hEvtLog = OpenEventLog(NULL, m_EvtLogName);
|
|
}
|
|
}
|
|
|
|
m_LogLock.Unlock();
|
|
|
|
if (NULL != m_hEvtLog)
|
|
{
|
|
m_bValid = TRUE;
|
|
m_Reason = 0;
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::RefreshHandle:Invalid log\r\n"
|
|
) ;
|
|
)
|
|
m_bValid = FALSE;
|
|
m_Reason = GetLastError();
|
|
}
|
|
}
|
|
|
|
DWORD CEventLogFile::FindOldEvent(DWORD evtID, const wchar_t* source, DWORD* recID, time_t offset)
|
|
{
|
|
DWORD dwRet = 0;
|
|
time_t timeVal;
|
|
|
|
if (offset > 0)
|
|
{
|
|
time(&timeVal);
|
|
timeVal -= offset;
|
|
}
|
|
|
|
DWORD dwEventSize = 0;
|
|
DWORD lastErr = ReadRecord(0, &dwEventSize, TRUE);
|
|
|
|
if (0 != lastErr)
|
|
{
|
|
if (lastErr != ERROR_HANDLE_EOF)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::FindOldEvent:Log no longer valid\r\n"
|
|
) ;
|
|
)
|
|
|
|
m_bValid = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (TRUE)
|
|
{
|
|
if (lastErr != 0)
|
|
{
|
|
if (lastErr != ERROR_HANDLE_EOF)
|
|
{
|
|
m_bValid = FALSE;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::FindOldEvent:Log no longer valid\r\n"
|
|
) ;
|
|
)
|
|
}
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
PEVENTLOGRECORD EventBuffer = (PEVENTLOGRECORD)m_Buffer;
|
|
BOOL bDone = FALSE;
|
|
|
|
while (dwEventSize != 0)
|
|
{
|
|
//eventid and sourcename identify event
|
|
if ((source != NULL) && (evtID == EventBuffer->EventID) &&
|
|
(0 == _wcsicmp(source,
|
|
(const wchar_t*)((UCHAR*)EventBuffer + sizeof(EVENTLOGRECORD))
|
|
)
|
|
)
|
|
)
|
|
{
|
|
if (offset > 0)
|
|
{
|
|
if (EventBuffer->TimeWritten < timeVal)
|
|
{
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
dwRet = EventBuffer->TimeWritten;
|
|
|
|
if (recID != NULL)
|
|
{
|
|
*recID = EventBuffer->RecordNumber;
|
|
}
|
|
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (offset > 0)
|
|
{
|
|
if (EventBuffer->TimeWritten < timeVal)
|
|
{
|
|
bDone = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (recID != NULL)
|
|
{
|
|
*recID = EventBuffer->RecordNumber;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// drop by length of this record and point to next record
|
|
dwEventSize -= EventBuffer->Length;
|
|
EventBuffer = (PEVENTLOGRECORD) ((UCHAR*) EventBuffer + EventBuffer->Length);
|
|
}
|
|
|
|
if (bDone)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
lastErr = ReadRecord(0, &dwEventSize, TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
BOOL CEventLogFile::GetLastRecordID(DWORD& rec, DWORD& numrecs)
|
|
{
|
|
rec = 0;
|
|
numrecs = 0;
|
|
m_LogLock.Lock();
|
|
|
|
if (!GetNumberOfEventLogRecords(m_hEvtLog, &numrecs))
|
|
{
|
|
m_LogLock.Unlock();
|
|
return FALSE;
|
|
}
|
|
|
|
if (numrecs != 0)
|
|
{
|
|
DWORD last_rec = 0;
|
|
|
|
if (!GetOldestEventLogRecord(m_hEvtLog, &last_rec))
|
|
{
|
|
m_LogLock.Unlock();
|
|
return FALSE;
|
|
}
|
|
|
|
if (0xFFFFFFFF - last_rec >= numrecs)
|
|
{
|
|
rec = numrecs + last_rec - 1;
|
|
}
|
|
else
|
|
{
|
|
//we have to guard the overflow...
|
|
rec = numrecs - (0xFFFFFFFF - last_rec) - 1;
|
|
}
|
|
}
|
|
|
|
m_LogLock.Unlock();
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD CEventLogFile::ReadRecord(DWORD recID, DWORD* dwBytesRead, BOOL b_Back)
|
|
{
|
|
if (NULL != dwBytesRead)
|
|
{
|
|
*dwBytesRead = 0;
|
|
}
|
|
|
|
DWORD dwFlags;
|
|
|
|
if (recID == 0)
|
|
{
|
|
dwFlags = EVENTLOG_SEQUENTIAL_READ;
|
|
}
|
|
else
|
|
{
|
|
dwFlags = EVENTLOG_SEEK_READ;
|
|
}
|
|
|
|
if (b_Back)
|
|
{
|
|
dwFlags = dwFlags | EVENTLOG_BACKWARDS_READ;
|
|
}
|
|
else
|
|
{
|
|
dwFlags = dwFlags | EVENTLOG_FORWARDS_READ;
|
|
}
|
|
|
|
m_bBuffer = TRUE;
|
|
|
|
if (0 == m_BuffLen)
|
|
{
|
|
m_BuffLen = 2048;
|
|
m_Buffer = new BYTE[m_BuffLen];
|
|
}
|
|
|
|
DWORD dwRead = 0;
|
|
DWORD dwNext = 0;
|
|
m_LogLock.Lock();
|
|
|
|
if ( !ReadEventLog(m_hEvtLog,
|
|
dwFlags,
|
|
recID,
|
|
m_Buffer,
|
|
m_BuffLen,
|
|
&dwRead,
|
|
&dwNext))
|
|
{
|
|
DWORD err = GetLastError();
|
|
|
|
if (ERROR_INSUFFICIENT_BUFFER == err)
|
|
{
|
|
delete [] m_Buffer;
|
|
m_Buffer = NULL;
|
|
m_BuffLen = 5*dwNext;
|
|
m_Buffer = new BYTE[m_BuffLen];
|
|
|
|
if ( !ReadEventLog(m_hEvtLog,
|
|
dwFlags,
|
|
recID,
|
|
m_Buffer,
|
|
m_BuffLen,
|
|
&dwRead,
|
|
&dwNext))
|
|
{
|
|
m_LogLock.Unlock();
|
|
return GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_LogLock.Unlock();
|
|
return err;
|
|
}
|
|
}
|
|
|
|
if (NULL != dwBytesRead)
|
|
{
|
|
*dwBytesRead = dwRead;
|
|
}
|
|
|
|
m_bBuffer = TRUE;
|
|
m_LogLock.Unlock();
|
|
return 0;
|
|
}
|
|
|
|
DWORD CEventLogFile::ReadFirstRecord()
|
|
{
|
|
DWORD last_rec = 0;
|
|
DWORD dwRead = 0;
|
|
m_bValid = FALSE;
|
|
m_LogLock.Lock();
|
|
BOOL bTest = GetOldestEventLogRecord(m_hEvtLog, &last_rec);
|
|
m_LogLock.Unlock();
|
|
|
|
if (bTest)
|
|
{
|
|
DWORD lastErr = ReadRecord(last_rec, &dwRead);
|
|
|
|
if (0 != lastErr)
|
|
{
|
|
if (lastErr == ERROR_HANDLE_EOF)
|
|
{
|
|
m_bValid = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_bValid = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::ReadFirstRecord:Failed to get oldest record\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
|
|
return dwRead;
|
|
}
|
|
|
|
void CEventLogFile::ReadLastRecord()
|
|
{
|
|
DWORD recID = 0;
|
|
DWORD numRecs = 0;
|
|
m_bValid = FALSE;
|
|
|
|
|
|
if (GetLastRecordID(recID, numRecs))
|
|
{
|
|
DWORD lastErr = ReadRecord(recID);
|
|
|
|
if (0 != lastErr)
|
|
{
|
|
if (lastErr == ERROR_HANDLE_EOF)
|
|
{
|
|
m_bValid = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (0 == (lastErr = ReadRecord(0)));
|
|
|
|
if (lastErr == ERROR_HANDLE_EOF)
|
|
{
|
|
m_bValid = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CEventLogFile::ReadLastRecord:Failed to read last record\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
}
|
|
|
|
|
|
HANDLE CEventLogFile::OpenLocalEventLog(LPCWSTR a_log, DWORD *a_Reason)
|
|
{
|
|
HANDLE retVal = NULL;
|
|
|
|
if (a_Reason)
|
|
{
|
|
*a_Reason = 0;
|
|
}
|
|
|
|
HKEY hkLog;
|
|
CStringW log(EVENTLOG_BASE);
|
|
log += L"\\";
|
|
log += a_log;
|
|
|
|
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, log, 0, KEY_READ, &hkLog))
|
|
{
|
|
*a_Reason = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
RegCloseKey(hkLog);
|
|
retVal = OpenEventLog(NULL, a_log);
|
|
DWORD t_dwErr = GetLastError();
|
|
|
|
if (retVal == NULL)
|
|
{
|
|
if (t_dwErr == ERROR_PRIVILEGE_NOT_HELD)
|
|
{
|
|
SetSecurityLogPrivilege();
|
|
retVal = OpenEventLog(NULL, a_log);
|
|
t_dwErr = GetLastError();
|
|
}
|
|
else if (a_Reason)
|
|
{
|
|
*a_Reason = t_dwErr;
|
|
}
|
|
}
|
|
|
|
if ((NULL == retVal) && a_Reason && (*a_Reason == 0))
|
|
{
|
|
*a_Reason = t_dwErr;
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
CMonitoredEventLogFile::CMonitoredEventLogFile(CEventProviderManager* parent, const WCHAR* logname)
|
|
: ProvTaskObject(), CEventLogFile(logname, FALSE), m_Class (NULL)
|
|
{
|
|
InterlockedIncrement(&(CNTEventProviderClassFactory::objectsInProgress));
|
|
VariantInit(&m_VpsdSelfRel);
|
|
m_RecID = 0;
|
|
|
|
if (parent != NULL)
|
|
{
|
|
m_parent = parent;
|
|
}
|
|
else
|
|
{
|
|
m_bValid = FALSE;
|
|
}
|
|
|
|
if (IsValid())
|
|
{
|
|
ReadLastRecord();
|
|
|
|
if (IsValid())
|
|
{
|
|
m_LogLock.Lock();
|
|
m_bValid = NotifyChangeEventLog(m_hEvtLog, GetHandle());
|
|
m_bValid = m_bValid && SetEventDescriptor();
|
|
m_LogLock.Unlock();
|
|
}
|
|
}
|
|
|
|
if (!m_bValid)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::CMonitoredEventLogFile:Invalid log created\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
}
|
|
|
|
CMonitoredEventLogFile::~CMonitoredEventLogFile()
|
|
{
|
|
if (m_Class != NULL)
|
|
{
|
|
m_Class->Release();
|
|
}
|
|
|
|
VariantClear(&m_VpsdSelfRel);
|
|
|
|
InterlockedDecrement(&(CNTEventProviderClassFactory::objectsInProgress));
|
|
}
|
|
|
|
void CMonitoredEventLogFile::RefreshHandle()
|
|
{
|
|
CEventLogFile::RefreshHandle();
|
|
|
|
if (IsValid())
|
|
{
|
|
m_LogLock.Lock();
|
|
m_bValid = NotifyChangeEventLog(m_hEvtLog, GetHandle());
|
|
m_LogLock.Unlock();
|
|
}
|
|
|
|
if (!m_bValid)
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::RefreshHandle:Invalid log\r\n"
|
|
) ;
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOL CMonitoredEventLogFile::GenerateInstance(IWbemClassObject** ppEvtInst,
|
|
IWbemClassObject* pEmbedObj)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ((ppEvtInst == NULL) || (pEmbedObj == NULL))
|
|
{
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::GenerateInstance:Invalid parameter\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
*ppEvtInst = NULL;
|
|
}
|
|
|
|
if (m_Class == NULL)
|
|
{
|
|
BSTR path = SysAllocString(EVENT_CLASS);
|
|
IWbemServices* ns = m_parent->GetNamespacePtr();
|
|
|
|
if (ns == NULL)
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
else
|
|
{
|
|
hr = ns->GetObject(path, 0, NULL, &m_Class, NULL);
|
|
SysFreeString(path);
|
|
ns->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
m_Class = NULL;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::GenerateInstance:Failed to get class object\r\n"
|
|
) ;
|
|
)
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
hr = m_Class->SpawnInstance(0, ppEvtInst);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
m_Class->Release();
|
|
m_Class = NULL;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::GenerateInstance:Failed to spawn instance\r\n"
|
|
) ;
|
|
)
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
hr = (*ppEvtInst)->Put(SD_PROP, 0, &m_VpsdSelfRel, 0);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
(*ppEvtInst)->Release();
|
|
*ppEvtInst = NULL;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::GenerateInstance:Failed to set security descriptor into event\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
|
|
VARIANT v;
|
|
VariantInit(&v);
|
|
#ifdef STILL_DISPATCH
|
|
v.vt = VT_DISPATCH;
|
|
v.pdispVal = pEmbedObj;
|
|
#else
|
|
v.vt = VT_UNKNOWN;
|
|
v.punkVal = pEmbedObj;
|
|
#endif
|
|
pEmbedObj->AddRef();
|
|
hr = (*ppEvtInst)->Put(TARGET_PROP, 0, &v, 0);
|
|
VariantClear(&v); // will call release on value stored in variant
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
(*ppEvtInst)->Release();
|
|
*ppEvtInst = NULL;
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::GenerateInstance:Failed to embed target instance into event\r\n"
|
|
) ;
|
|
)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CMonitoredEventLogFile::Process()
|
|
{
|
|
SetStructuredExceptionHandler seh;
|
|
|
|
try
|
|
{
|
|
//Read and process the eventlog
|
|
DWORD dwEventSize = 0;
|
|
DWORD err = ReadRecord(m_RecID, &dwEventSize);
|
|
m_RecID = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
if (err != 0)
|
|
{
|
|
if (err == ERROR_HANDLE_EOF)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
RefreshHandle();
|
|
|
|
if (!m_bValid)
|
|
{
|
|
//log cannot be monitored
|
|
Complete();
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::Process:log cannot be read\r\n"
|
|
) ;
|
|
)
|
|
|
|
break;
|
|
}
|
|
|
|
if (err == ERROR_EVENTLOG_FILE_CHANGED)
|
|
{
|
|
err = 0;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
ReadLastRecord();
|
|
|
|
if (!m_bValid)
|
|
{
|
|
//log cannot be monitored
|
|
DebugOut(
|
|
CNTEventProvider::g_NTEvtDebugLog->WriteFileAndLine (
|
|
|
|
_T(__FILE__),__LINE__,
|
|
L"CMonitoredEventLogFile::Process:log cannot be read\r\n"
|
|
) ;
|
|
)
|
|
Complete();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
else
|
|
{
|
|
PEVENTLOGRECORD EventBuffer = (PEVENTLOGRECORD)m_Buffer;
|
|
|
|
while (dwEventSize != 0)
|
|
{
|
|
//generate records...
|
|
IWbemServices* ns = m_parent->GetNamespacePtr();
|
|
|
|
if (ns == NULL)
|
|
{
|
|
//no control objects!
|
|
return;
|
|
}
|
|
|
|
CEventlogRecord evtrec(m_EvtLogName, EventBuffer, ns);
|
|
ns->Release();
|
|
IWbemClassObject* pEmbedInst = NULL;
|
|
|
|
if (evtrec.GenerateInstance(&pEmbedInst))
|
|
{
|
|
IWbemClassObject* pEvtInst;
|
|
|
|
if (GenerateInstance(&pEvtInst, pEmbedInst))
|
|
{
|
|
m_parent->SendEvent(pEvtInst);
|
|
pEvtInst->Release();
|
|
}
|
|
|
|
pEmbedInst->Release();
|
|
}
|
|
|
|
// drop by length of this record and point to next record
|
|
dwEventSize -= EventBuffer->Length;
|
|
EventBuffer = (PEVENTLOGRECORD) ((UCHAR*) EventBuffer + EventBuffer->Length);
|
|
}
|
|
}
|
|
|
|
dwEventSize = 0;
|
|
err = ReadRecord(0, &dwEventSize);
|
|
}
|
|
}
|
|
catch(Structured_Exception e_SE)
|
|
{
|
|
try
|
|
{
|
|
Complete();
|
|
}
|
|
catch(...)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
catch(Heap_Exception e_HE)
|
|
{
|
|
try
|
|
{
|
|
Complete();
|
|
}
|
|
catch(...)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
try
|
|
{
|
|
Complete();
|
|
}
|
|
catch(...)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static GENERIC_MAPPING LogFileObjectMapping = {
|
|
|
|
STANDARD_RIGHTS_READ | // Generic read
|
|
ELF_LOGFILE_READ |
|
|
WBEM_RIGHT_SUBSCRIBE,
|
|
|
|
STANDARD_RIGHTS_WRITE | // Generic write
|
|
ELF_LOGFILE_WRITE |
|
|
WBEM_RIGHT_SUBSCRIBE,
|
|
|
|
STANDARD_RIGHTS_EXECUTE | // Generic execute
|
|
ELF_LOGFILE_START |
|
|
ELF_LOGFILE_STOP |
|
|
ELF_LOGFILE_CONFIGURE |
|
|
WBEM_RIGHT_SUBSCRIBE,
|
|
|
|
ELF_LOGFILE_ALL_ACCESS | // Generic all
|
|
WBEM_RIGHT_SUBSCRIBE
|
|
};
|
|
|
|
BOOL CMonitoredEventLogFile::SetEventDescriptor()
|
|
{
|
|
BOOL retVal = FALSE;
|
|
DWORD NumberOfAcesToUse = 0;
|
|
//
|
|
// Logfile object specific access type
|
|
//
|
|
RTL_ACE_DATA AceData[ELF_LOGFILE_OBJECT_ACES] = {
|
|
|
|
{ACCESS_DENIED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AnonymousLogonSid},
|
|
|
|
{ACCESS_DENIED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasGuestsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_ALL_ACCESS | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_LocalSystemSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasAdminsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_BACKUP, &CNTEventProvider::s_AliasBackupOpsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_READ | ELF_LOGFILE_CLEAR | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasSystemOpsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_READ | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_WorldSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasAdminsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_LocalServiceSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_NetworkServiceSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_AliasSystemOpsSid},
|
|
|
|
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
|
|
ELF_LOGFILE_WRITE | WBEM_RIGHT_SUBSCRIBE, &CNTEventProvider::s_WorldSid}
|
|
};
|
|
|
|
PRTL_ACE_DATA pAceData = NULL;
|
|
|
|
//
|
|
// NON_SECURE logfiles let anyone read/write to them, secure ones
|
|
// only let admins/local system do this. so for secure files we just
|
|
// don't use the last ACE
|
|
//
|
|
// Adjust the ACL start based on the passed GuestAccessRestriction flag.
|
|
// The first two aces deny all log access to guests and/or anonymous
|
|
// logons. The flag, GuestAccessRestriction, indicates that these two
|
|
// deny access aces should be applied. Note that the deny aces and the
|
|
// GuestAccessRestriction flag are not applicable to the security log,
|
|
// since users and anonymous logons, by default, do not have access.
|
|
//
|
|
|
|
DWORD cchBase = wcslen(EVENTLOG_BASE);
|
|
DWORD cchSize = cchBase + 1 + m_EvtLogName.GetLength() + 1;
|
|
wchar_t* buff = new wchar_t[ cchSize ];
|
|
StringCchCopyW ( buff, cchBase + 1, EVENTLOG_BASE );
|
|
StringCchCatW ( buff, cchSize, L"\\" );
|
|
StringCchCatW ( buff, cchSize, m_EvtLogName );
|
|
|
|
HKEY hkResult = NULL;
|
|
BOOL GuestAccessRestriction = TRUE;
|
|
|
|
DWORD dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
buff, 0,
|
|
KEY_READ,
|
|
&hkResult);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
DWORD datalen = sizeof(DWORD);
|
|
DWORD dwType = 0;
|
|
DWORD dwVal = 0;
|
|
|
|
dwErr = RegQueryValueEx(hkResult, GUEST_ACCESS,
|
|
0, &dwType, (LPBYTE) &dwVal, &datalen);
|
|
|
|
if ((dwErr == ERROR_SUCCESS) && (dwType == REG_DWORD))
|
|
{
|
|
if (dwVal == 0)
|
|
{
|
|
GuestAccessRestriction = FALSE;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkResult);
|
|
}
|
|
|
|
DWORD Type = 0;
|
|
|
|
if (m_EvtLogName.CompareNoCase(SYSTEM_LOG) == 0)
|
|
{
|
|
Type = 1;
|
|
}
|
|
else if (m_EvtLogName.CompareNoCase(SECURITY_LOG) == 0)
|
|
{
|
|
Type = 2;
|
|
}
|
|
|
|
switch (Type)
|
|
{
|
|
case 2:
|
|
{
|
|
pAceData = AceData + 2; // Deny ACEs *not* applicable
|
|
NumberOfAcesToUse = 3;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
if (GuestAccessRestriction)
|
|
{
|
|
pAceData = AceData; // Deny ACEs *applicable*
|
|
NumberOfAcesToUse = 10;
|
|
}
|
|
else
|
|
{
|
|
pAceData = AceData + 2; // Deny ACEs *not* applicable
|
|
NumberOfAcesToUse = 8;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0:
|
|
default:
|
|
{
|
|
if (GuestAccessRestriction)
|
|
{
|
|
pAceData = AceData; // Deny ACEs *applicable*
|
|
NumberOfAcesToUse = 12;
|
|
}
|
|
else
|
|
{
|
|
pAceData = AceData + 2; // Deny ACEs *not* applicable
|
|
NumberOfAcesToUse = 10;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
PSECURITY_DESCRIPTOR psdSelfRel = NULL;
|
|
NTSTATUS Status = RtlCreateUserSecurityObject(
|
|
pAceData,
|
|
NumberOfAcesToUse,
|
|
CNTEventProvider::s_LocalSystemSid, // Owner
|
|
CNTEventProvider::s_LocalSystemSid, // Group
|
|
TRUE, // IsDirectoryObject
|
|
&LogFileObjectMapping,
|
|
&psdSelfRel);
|
|
|
|
if (NT_SUCCESS(Status) && psdSelfRel)
|
|
{
|
|
try
|
|
{
|
|
DWORD sdlen = GetSecurityDescriptorLength(psdSelfRel);
|
|
|
|
if (sdlen > 0)
|
|
{
|
|
SAFEARRAYBOUND rgsabound[1];
|
|
SAFEARRAY* psa = NULL;
|
|
UCHAR* pdata = NULL;
|
|
rgsabound[0].lLbound = 0;
|
|
rgsabound[0].cElements = sdlen;
|
|
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
|
|
|
|
if (NULL != psa)
|
|
{
|
|
try
|
|
{
|
|
if (SUCCEEDED(SafeArrayAccessData(psa, (void **)&pdata)))
|
|
{
|
|
memcpy((void *)pdata, (void *)psdSelfRel, sdlen);
|
|
SafeArrayUnaccessData(psa);
|
|
m_VpsdSelfRel.vt = VT_ARRAY|VT_UI1;
|
|
m_VpsdSelfRel.parray = psa;
|
|
retVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
SafeArrayDestroy(psa);
|
|
psa = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
SafeArrayDestroy(psa);
|
|
psa = NULL;
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
RtlDeleteSecurityObject(&psdSelfRel);
|
|
psdSelfRel = NULL;
|
|
}
|
|
|
|
RtlDeleteSecurityObject(&psdSelfRel);
|
|
psdSelfRel = NULL;
|
|
}
|
|
|
|
return retVal;
|
|
}
|