mirror of https://github.com/lianthony/NT4.0
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.
471 lines
12 KiB
471 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
CAIRO.C
|
|
|
|
Abstract:
|
|
|
|
This file contains Cairo alert extensions to the NT event log.
|
|
|
|
Author:
|
|
|
|
Mark Blanford (markbl) 02-Nov-1994 New routines:
|
|
|
|
GetSourceAlertValuesFromRegistry
|
|
RaiseCairoAlert
|
|
TestSeverityFilter
|
|
|
|
With this check-in, it is possible for an NT event written to the 'System'
|
|
log to be raised as a Cairo alert. Further, it is possible for any
|
|
'System' log source to have the NT events it writes be raised as Cairo
|
|
alerts (subject to a filter) by simply supplying two key values:
|
|
'AlertCategory' & 'SeverityFilter' with their source name key under the
|
|
...\EventLog\System portion of the registry.
|
|
|
|
The 'AlertCategory' key value specifies the alert category value used in
|
|
the alerts created from the source's NT events.
|
|
|
|
The 'SeverityFilter' key value is a bit mask specifying the severity of
|
|
NT events to be converted to Cairo alerts. Note: alert severity values are
|
|
a superset of the NT event types information, warning & error. For
|
|
example: assume the "Srv" source has specified alert category and severity
|
|
key values, and the severity value, a bit mask, is set to warning | error.
|
|
The NT events "Srv" subsequently writes to the 'System' log of NT event
|
|
type warning or error will be distributed as Cairo alerts. "Srv" NT events
|
|
with NT event types other than warning or error will not be raised as
|
|
Cairo alerts.
|
|
|
|
All Cairo alerts generated as a result of this conversion, are raised to
|
|
the local computer distributor.
|
|
|
|
[Environment:]
|
|
|
|
User Mode - Win32, except for NTSTATUS returned by some functions.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
//
|
|
// INCLUDES
|
|
//
|
|
|
|
#include <eventp.h>
|
|
#include <ole2.h>
|
|
#include <oleext.h>
|
|
#include <sysmgmt.h>
|
|
#include <alertapi.h>
|
|
|
|
GUID CLSID_CNTEventReport = {
|
|
0x43750e20,
|
|
0xfa68,
|
|
0x11cd,
|
|
{ 0x84, 0xb7, 0x00, 0xaa, 0x00, 0x4a, 0x56, 0xe1 }
|
|
};
|
|
|
|
static WCHAR wszAlertCategory[] = L"AlertCategory";
|
|
static WCHAR wszSeverityFilter[] = L"SeverityFilter";
|
|
|
|
BOOL IsValidSeverityFilter(SHORT sSeverity);
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fetch "...\EventLog\System\<SourceName>" 'AlertCategory' and
|
|
'SeverityFilter' registry values, if they exist.
|
|
|
|
Arguments:
|
|
|
|
hKeyLogFile - Registry handle to '...\EventLog\<LogName>' where
|
|
<LogName> is likely to be 'System'.
|
|
pswszSourceName - Source name registered to report events to the log
|
|
indicated above.
|
|
psAlertCategory - Returned category value.
|
|
psSeverityFilter - Returned severity value.
|
|
|
|
Return Value:
|
|
|
|
BOOL - TRUE if the category,severity filter was successfully read;
|
|
FALSE otherwise.
|
|
|
|
Note:
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
GetSourceAlertFilterFromRegistry(
|
|
HANDLE hKeyLogFile,
|
|
UNICODE_STRING * pswszSourceName,
|
|
SHORT * psAlertCategory,
|
|
SHORT * psSeverityFilter)
|
|
{
|
|
#define KEY_VALUE_FULL_INFO_SIZE 1024 // BUGBUG : need proper size
|
|
|
|
BOOL fRet = FALSE;
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING SubKeyName;
|
|
HANDLE hKeySource;
|
|
BYTE Buffer[KEY_VALUE_FULL_INFO_SIZE];
|
|
PKEY_VALUE_FULL_INFORMATION KeyValue = (PKEY_VALUE_FULL_INFORMATION)Buffer;
|
|
ULONG Index = 0;
|
|
ULONG ActualSize;
|
|
SHORT sAlertCategory, sSeverityFilter;
|
|
|
|
ASSERT(pswszSourceName != NULL);
|
|
ASSERT(psAlertCategory != NULL);
|
|
ASSERT(psSeverityFilter != NULL);
|
|
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
pswszSourceName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKeyLogFile,
|
|
NULL);
|
|
|
|
//
|
|
// Read category,severity filter values, if they exist, for this source.
|
|
//
|
|
|
|
Status = NtOpenKey(&hKeySource, KEY_READ, &ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
//
|
|
// Fetch alert category value, if it exists.
|
|
//
|
|
|
|
RtlInitUnicodeString(&SubKeyName, wszAlertCategory);
|
|
|
|
Status = NtQueryValueKey(hKeySource,
|
|
&SubKeyName,
|
|
KeyValueFullInformation,
|
|
KeyValue,
|
|
KEY_VALUE_FULL_INFO_SIZE,
|
|
&ActualSize);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
sAlertCategory = *((PSHORT)(Buffer + KeyValue->DataOffset));
|
|
|
|
//
|
|
// Fetch severity filter value, if it exists.
|
|
//
|
|
|
|
RtlInitUnicodeString(&SubKeyName, wszSeverityFilter);
|
|
|
|
Status = NtQueryValueKey(hKeySource,
|
|
&SubKeyName,
|
|
KeyValueFullInformation,
|
|
KeyValue,
|
|
KEY_VALUE_FULL_INFO_SIZE,
|
|
&ActualSize);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
sSeverityFilter = *((PSHORT)(Buffer + KeyValue->DataOffset));
|
|
|
|
//
|
|
// Is the severity valid?
|
|
//
|
|
|
|
if (!IsValidSeverityFilter(sSeverityFilter))
|
|
{
|
|
ElfDbgPrintNC((
|
|
"[ELF] Invalid severity filter (%02x) for " \
|
|
"source \"%ws\"\n",
|
|
sSeverityFilter,
|
|
pswszSourceName->Buffer));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
*psAlertCategory = sAlertCategory;
|
|
*psSeverityFilter = sSeverityFilter;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
Status = NtClose(hKeySource);
|
|
ASSERT(NT_SUCCESS(Status));
|
|
}
|
|
else
|
|
{
|
|
ElfDbgPrintNC((
|
|
"[ELF] Unable to open source key %ws to fetch alert " \
|
|
"filter (%x)\n",
|
|
pswszSourceName->Buffer,
|
|
Status));
|
|
}
|
|
|
|
return(fRet);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Bit-wise compare the passed NT event type & alert severity.
|
|
|
|
Arguments:
|
|
|
|
NTEventType - NT event type.
|
|
sSeverityFilter - Alert severity.
|
|
|
|
Return Value:
|
|
|
|
BOOL - TRUE if NTEventType has a bit in common with sSeverityFilter;
|
|
FALSE otherwise.
|
|
|
|
Note:
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
TestFilter(WORD NTEventType, SHORT sSeverityFilter)
|
|
{
|
|
//
|
|
// Mask off all bits but the alert severities.
|
|
//
|
|
|
|
if (((ALERTSEVERITY_FATAL_ERROR |
|
|
ALERTSEVERITY_SEVERE_ERROR |
|
|
ALERTSEVERITY_ERROR |
|
|
ALERTSEVERITY_WARNING |
|
|
ALERTSEVERITY_INFORMATION) & sSeverityFilter) & NTEventType)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Test the severity passed for validity. No bits other than the severity
|
|
mask must be set and the severity must be non-zero.
|
|
|
|
Arguments:
|
|
|
|
sSeverity - Tested severity.
|
|
|
|
Return Value:
|
|
|
|
BOOL - TRUE if the test succeeds;
|
|
FALSE otherwise.
|
|
|
|
Note:
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
IsValidSeverityFilter(SHORT sSeverity)
|
|
{
|
|
//
|
|
// Insure the only bits set are the severity mask.
|
|
//
|
|
|
|
if (!(sSeverity & ~(ALERTSEVERITY_FATAL_ERROR |
|
|
ALERTSEVERITY_SEVERE_ERROR |
|
|
ALERTSEVERITY_ERROR |
|
|
ALERTSEVERITY_WARNING |
|
|
ALERTSEVERITY_INFORMATION)))
|
|
{
|
|
//
|
|
// Is a severity specified at all?
|
|
//
|
|
|
|
return(sSeverity ? TRUE : FALSE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert & raise the NT event passed as a Cairo alert to the local
|
|
computer distributor.
|
|
|
|
Arguments:
|
|
|
|
pLogModule - Specific log module. This structure supplies the alert
|
|
category value & the log module name.
|
|
pEventLogRecord - The NT event to be converted & raised as an alert.
|
|
|
|
Return Value:
|
|
|
|
HRESULT -
|
|
|
|
Note:
|
|
|
|
--*/
|
|
|
|
HRESULT
|
|
RaiseCairoAlert(PLOGMODULE pLogModule, EVENTLOGRECORD * pEventLogRecord)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrLogName = NULL;
|
|
WCHAR * pwszTmp;
|
|
int i;
|
|
ALERTREPORTRECORD alertreport;
|
|
VARIANT avar[2];
|
|
DISPID aid[2];
|
|
WCHAR ** apwszInserts = NULL;
|
|
HINSTANCE hInstance;
|
|
|
|
|
|
do
|
|
{
|
|
//
|
|
// ALERTSYS.DLL & the ReportAlert entry point is linked to by hand
|
|
// in the eventlog initialization code (eventlog.c). If this global
|
|
// handle is NULL, the link attempt failed.
|
|
//
|
|
|
|
if (ghAlertSysDll == NULL)
|
|
{
|
|
//
|
|
// BUGBUG : Log an error?
|
|
//
|
|
|
|
return(E_FAIL);
|
|
}
|
|
|
|
//
|
|
// Initialize mandatory properties.
|
|
//
|
|
|
|
INITIALIZE_ALERTREPORTRECORD(alertreport,
|
|
pLogModule->AlertCategory, // Alert category
|
|
pEventLogRecord->EventType, // Alert severity
|
|
-1, // No title message no.
|
|
pEventLogRecord->EventID, // Description message no.
|
|
NULL, // No component ID
|
|
(WCHAR *)((BYTE *)pEventLogRecord + // Source name
|
|
sizeof(EVENTLOGRECORD)));
|
|
|
|
//
|
|
// Alert report class
|
|
//
|
|
|
|
alertreport.ReportClassID = &CLSID_CNTEventReport;
|
|
|
|
//
|
|
// Properties specific to NT event reports...
|
|
//
|
|
// Event category
|
|
//
|
|
|
|
aid[0] = DISPID_NTEventReport_EventCategory;
|
|
VariantInit(&avar[0]);
|
|
avar[0].vt = VT_I2;
|
|
avar[0].iVal = pEventLogRecord->EventCategory;
|
|
|
|
//
|
|
// Log module name
|
|
//
|
|
|
|
bstrLogName = SysAllocString(pLogModule->LogFile->
|
|
LogModuleName->Buffer);
|
|
|
|
if (bstrLogName == NULL)
|
|
{
|
|
ElfDbgPrintNC((
|
|
"[ELF RaiseCairoAlert] failed to allocate log name bstr\n"));
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
aid[1] = DISPID_NTEventReport_LogFile;
|
|
VariantInit(&avar[1]);
|
|
avar[1].vt = VT_BSTR;
|
|
avar[1].bstrVal = bstrLogName;
|
|
|
|
//
|
|
// Description inserts; optional.
|
|
//
|
|
|
|
if (pEventLogRecord->NumStrings > 0)
|
|
{
|
|
apwszInserts = (WCHAR **)ElfpAllocateBuffer(sizeof(WCHAR *) *
|
|
pEventLogRecord->NumStrings);
|
|
|
|
if (apwszInserts == NULL)
|
|
{
|
|
ElfDbgPrintNC((
|
|
"[ELF RaiseCairoAlert] failed to allocate insert " \
|
|
"string\n"));
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
for (i = 0, pwszTmp = (WCHAR *)((BYTE *)pEventLogRecord +
|
|
pEventLogRecord->StringOffset);
|
|
(pwszTmp != NULL) && (i < pEventLogRecord->NumStrings); i++)
|
|
{
|
|
apwszInserts[i] = pwszTmp;
|
|
pwszTmp += wcslen(pwszTmp) + 1;
|
|
}
|
|
|
|
alertreport.cDescrMessageInserts = i;
|
|
alertreport.DescrMessageInserts = apwszInserts;
|
|
}
|
|
|
|
alertreport.cAdditionalArguments = 2;
|
|
alertreport.AdditionalArgumentNames = aid;
|
|
alertreport.AdditionalArguments = avar;
|
|
|
|
//
|
|
// Alert data; optional, as well.
|
|
//
|
|
|
|
if (pEventLogRecord->DataLength > 0)
|
|
{
|
|
alertreport.cBytesAlertData = pEventLogRecord->DataLength;
|
|
alertreport.AlertData = (BYTE *)pEventLogRecord +
|
|
pEventLogRecord->DataOffset;
|
|
}
|
|
|
|
//
|
|
// Finally, raise the alert.
|
|
//
|
|
|
|
hr = gpfReportAlert(&alertreport, RA_REPORT);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
ElfDbgPrintNC((
|
|
"[ELF RaiseCairoAlert] ReportAlert failed HRESULT(%x)\n",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
} while (0);
|
|
|
|
// Cleanup
|
|
|
|
if (bstrLogName != NULL)
|
|
{
|
|
SysFreeString(bstrLogName);
|
|
}
|
|
if (apwszInserts != NULL)
|
|
{
|
|
ElfpFreeBuffer(apwszInserts);
|
|
}
|
|
|
|
return(hr);
|
|
}
|