windows-nt/Source/XPSP1/NT/mergedcomponents/advapi32/eventapi.c
2020-09-26 16:20:57 +08:00

1577 lines
35 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
EVENTAPI.C
Abstract:
This module contains the client ends of the EventLog APIs.
Author:
Rajen Shah (rajens) 24-Aug-1991
Revision History:
--*/
#include "advapi.h"
static WCHAR wszDosDevices[] = L"\\DosDevices\\";
ULONG
BaseSetLastNTError(
IN NTSTATUS Status
)
/*++
Routine Description:
This API sets the "last error value" and the "last error string"
based on the value of Status. For status codes that don't have
a corresponding error string, the string is set to null.
Arguments:
Status - Supplies the status value to store as the last error value.
Return Value:
The corresponding Win32 error code that was stored in the
"last error value" thread variable.
--*/
{
ULONG dwErrorCode;
dwErrorCode = RtlNtStatusToDosError( Status );
SetLastError( dwErrorCode );
return( dwErrorCode );
}
BOOL
InitAnsiString(
OUT PANSI_STRING DestinationString,
IN PCSZ SourceString OPTIONAL
)
/*++
Routine Description:
The RtlInitAnsiString function initializes an NT counted string.
The DestinationString is initialized to point to the SourceString
and the Length and MaximumLength fields of DestinationString are
initialized to the length of the SourceString, which is zero if
SourceString is not specified.
This is RtlInitAnsiString with a return status that rejects strings
that are greater than 64K bytes.
Arguments:
DestinationString - Pointer to the counted string to initialize
SourceString - Optional pointer to a null terminated string that
the counted string is to point to.
Return Value:
None.
--*/
{
ULONG Length = 0;
DestinationString->Length = 0;
DestinationString->Buffer = (PCHAR)SourceString;
if (ARGUMENT_PRESENT( SourceString )) {
while (*SourceString++) {
Length++;
}
//
// Make sure the length won't overflow a USHORT when converted to
// UNICODE characters
//
if (Length * sizeof(WCHAR) > 0xFFFF) {
return(FALSE);
}
DestinationString->Length = (USHORT) Length;
DestinationString->MaximumLength = (USHORT) (Length + 1);
}
else {
DestinationString->MaximumLength = 0;
DestinationString->Length = 0;
}
return(TRUE);
}
BOOL
InitUnicodeString(
OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString OPTIONAL
)
/*++
Routine Description:
The InitUnicodeString function initializes an NT counted
unicode string. The DestinationString is initialized to point to
the SourceString and the Length and MaximumLength fields of
DestinationString are initialized to the length of the SourceString,
which is zero if SourceString is not specified.
This is RtlInitUnicodeString with a return status that rejects strings
that are greater than 64K bytes.
Arguments:
DestinationString - Pointer to the counted string to initialize
SourceString - Optional pointer to a null terminated unicode string that
the counted string is to point to.
Return Value:
None.
--*/
{
ULONG Length = 0;
DestinationString->Length = 0;
DestinationString->Buffer = (PWSTR)SourceString;
if (ARGUMENT_PRESENT( SourceString )) {
while (*SourceString++) {
Length += sizeof(*SourceString);
}
//
// Make sure the length won't overflow a USHORT
//
if (Length > 0xFFFF) {
return(FALSE);
}
DestinationString->Length = (USHORT) Length;
DestinationString->MaximumLength =
(USHORT) Length + (USHORT) sizeof(UNICODE_NULL);
}
else {
DestinationString->MaximumLength = 0;
DestinationString->Length = 0;
}
return(TRUE);
}
//
// Single version API's (no strings)
//
BOOL
CloseEventLog (
HANDLE hEventLog
)
/*++
Routine Description:
This is the client DLL entry point for the WinCloseEventLog API.
It closes the RPC binding, and frees any memory allocated for the
handle.
NOTE that there is no equivalent call for ANSI.
Arguments:
LogHandle - Handle returned from a previous "Open" call.
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfCloseEventLog (hEventLog);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
DeregisterEventSource (
HANDLE hEventLog
)
/*++
Routine Description:
This is the client DLL entry point for the DeregisterEventSource API.
It closes the RPC binding, and frees any memory allocated for the
handle.
NOTE that there is no equivalent call for ANSI.
Arguments:
LogHandle - Handle returned from a previous "Open" call.
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfDeregisterEventSource (hEventLog);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
NotifyChangeEventLog(
HANDLE hEventLog,
HANDLE hEvent
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
NTSTATUS Status;
Status = ElfChangeNotify(hEventLog,hEvent);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
return(FALSE);
} else {
return(TRUE);
}
}
BOOL
GetNumberOfEventLogRecords (
HANDLE hEventLog,
PDWORD NumberOfRecords
)
/*++
Routine Description:
This is the client DLL entry point that returns the number of records in
the eventlog specified by hEventLog.
NOTE that there is no equivalent call for ANSI.
Arguments:
LogHandle - Handle returned from a previous "Open" call.
NumberOfRecords - Pointer to a DWORD to place the number of records.
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfNumberOfRecords (hEventLog, NumberOfRecords);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
GetOldestEventLogRecord (
HANDLE hEventLog,
PDWORD OldestRecord
)
/*++
Routine Description:
This is the client DLL entry point that returns the record number of the
oldest record in the eventlog specified by hEventLog.
NOTE that there is no equivalent call for ANSI.
Arguments:
LogHandle - Handle returned from a previous "Open" call.
OldestRecord - Pointer to a DWORD to place the record number of the
oldest record in the eventlog specified by hEventLog
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfOldestRecord (hEventLog, OldestRecord);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
GetEventLogInformation (
HANDLE hEventLog,
DWORD dwInfoLevel,
PVOID lpBuffer,
DWORD cbBufSize,
LPDWORD pcbBytesNeeded
)
/*++
Routine Description:
This is the client DLL entry point that returns information about
the eventlog specified by hEventLog.
Arguments:
LogHandle - Handle returned from a previous "Open" call.
dwInfoLevel - Which information to return
lpBuffer - Pointer to buffer to hold information
cbBufSize - Size of buffer, in bytes
pcbBytesNeeded - Number of bytes needed
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS ntStatus;
ntStatus = ElfGetLogInformation(hEventLog,
dwInfoLevel,
lpBuffer,
cbBufSize,
pcbBytesNeeded);
if (!NT_SUCCESS(ntStatus)) {
BaseSetLastNTError(ntStatus);
return FALSE;
}
return TRUE;
}
//
// UNICODE APIs
//
BOOL
ClearEventLogW (
HANDLE hEventLog,
LPCWSTR BackupFileName
)
/*++
Routine Description:
This is the client DLL entry point for the ClearEventLogFile API.
The call is passed to the eventlog service on the appropriate server
identified by LogHandle.
Arguments:
LogHandle - Handle returned from a previous "Open" call. This is
used to identify the module and the server.
BackupFileName - Name of the file to back up the current log file.
NULL implies not to back up the file.
Return Value:
TRUE if success, FALSE otherwise.
--*/
{
UNICODE_STRING Unicode;
UNICODE_STRING DLUnicode; // Downlevel NT filename.
NTSTATUS Status;
BOOL ReturnValue;
//
// Turn the Dos filename into an NT filename
//
if (BackupFileName) {
ReturnValue = RtlDosPathNameToNtPathName_U(BackupFileName, &Unicode, NULL, NULL);
if (!BackupFileName || !ReturnValue) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
}
else {
Unicode.Length = 0;
Unicode.MaximumLength = 0;
Unicode.Buffer = NULL;
}
Status = ElfClearEventLogFileW (hEventLog, &Unicode);
//
// With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
// in 3.51. This retry logic exists for 3.51 machines which don't
// recognize NT 4.0 filenames. The API should have passed Windows
// filenames vs NT.
//
if (Status == STATUS_OBJECT_PATH_NOT_FOUND && BackupFileName != NULL) {
DLUnicode.MaximumLength = (wcslen(BackupFileName) * sizeof(WCHAR)) +
sizeof(wszDosDevices);
DLUnicode.Buffer = RtlAllocateHeap(
RtlProcessHeap(), 0,
DLUnicode.MaximumLength);
if (DLUnicode.Buffer != NULL) {
wcscpy(DLUnicode.Buffer, wszDosDevices);
wcscat(DLUnicode.Buffer, BackupFileName);
DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
Status = ElfClearEventLogFileW (hEventLog, &DLUnicode);
RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
}
else {
Status = STATUS_NO_MEMORY;
}
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
if (Unicode.MaximumLength) {
RtlFreeHeap(RtlProcessHeap(), 0, Unicode.Buffer);
}
return ReturnValue;
}
BOOL
BackupEventLogW (
HANDLE hEventLog,
LPCWSTR BackupFileName
)
/*++
Routine Description:
This is the client DLL entry point for the BackupEventLogFile API.
The call is passed to the eventlog service on the appropriate server
identified by LogHandle.
Arguments:
LogHandle - Handle returned from a previous "Open" call. This is
used to identify the module and the server.
BackupFileName - Name of the file to back up the current log file.
Return Value:
TRUE if success, FALSE otherwise.
--*/
{
UNICODE_STRING Unicode;
UNICODE_STRING DLUnicode; // Downlevel NT filename.
NTSTATUS Status;
BOOL ReturnValue = TRUE;
//
// Turn the Dos filename into an NT filename
//
if (BackupFileName) {
ReturnValue = RtlDosPathNameToNtPathName_U(BackupFileName, &Unicode,
NULL, NULL);
}
if (!BackupFileName || !ReturnValue) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
Status = ElfBackupEventLogFileW (hEventLog, &Unicode);
//
// With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
// in 3.51. This retry logic exists for 3.51 machines which don't
// recognize NT 4.0 filenames. The API should have passed Windows
// filenames vs NT.
//
if (Status == STATUS_OBJECT_PATH_NOT_FOUND && BackupFileName != NULL) {
DLUnicode.MaximumLength = (wcslen(BackupFileName) * sizeof(WCHAR)) +
sizeof(wszDosDevices);
DLUnicode.Buffer = RtlAllocateHeap(
RtlProcessHeap(), 0,
DLUnicode.MaximumLength);
if (DLUnicode.Buffer != NULL) {
wcscpy(DLUnicode.Buffer, wszDosDevices);
wcscat(DLUnicode.Buffer, BackupFileName);
DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
Status = ElfBackupEventLogFileW (hEventLog, &DLUnicode);
RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
}
else {
Status = STATUS_NO_MEMORY;
}
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
if (Unicode.MaximumLength) {
RtlFreeHeap(RtlProcessHeap(), 0, Unicode.Buffer);
}
return ReturnValue;
}
HANDLE
OpenEventLogW (
LPCWSTR UNCServerName,
LPCWSTR ModuleName
)
/*++
Routine Description:
This is the client DLL entry point for the WinOpenEventLog API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
ModuleName - Supplies the name of the module to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
UNICODE_STRING Unicode;
UNICODE_STRING UnicodeModuleName;
HANDLE LogHandle;
NTSTATUS Status;
HANDLE ReturnHandle;
RtlInitUnicodeString(&UnicodeModuleName,ModuleName);
RtlInitUnicodeString(&Unicode, UNCServerName);
Status = ElfOpenEventLogW (
&Unicode,
&UnicodeModuleName,
&LogHandle
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnHandle = (HANDLE)NULL;
} else {
ReturnHandle = (HANDLE)LogHandle;
}
return ReturnHandle;
}
HANDLE
RegisterEventSourceW (
LPCWSTR UNCServerName,
LPCWSTR ModuleName
)
/*++
Routine Description:
This is the client DLL entry point for the RegisterEventSource API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
ModuleName - Supplies the name of the module to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
UNICODE_STRING Unicode;
UNICODE_STRING UnicodeModuleName;
HANDLE LogHandle;
NTSTATUS Status;
HANDLE ReturnHandle;
RtlInitUnicodeString(&UnicodeModuleName,ModuleName);
RtlInitUnicodeString(&Unicode, UNCServerName);
Status = ElfRegisterEventSourceW (
&Unicode,
&UnicodeModuleName,
&LogHandle
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnHandle = (HANDLE)NULL;
} else {
ReturnHandle = (HANDLE)LogHandle;
}
return ReturnHandle;
}
HANDLE
OpenBackupEventLogW (
LPCWSTR UNCServerName,
LPCWSTR FileName
)
/*++
Routine Description:
This is the client DLL entry point for the OpenBackupEventLog API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
FileName - Supplies the filename of the logfile to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
UNICODE_STRING Unicode;
UNICODE_STRING UnicodeFileName;
UNICODE_STRING DLUnicode; // Downlevel NT filename.
HANDLE LogHandle;
NTSTATUS Status = STATUS_SUCCESS;
HANDLE ReturnHandle;
RtlInitUnicodeString(&Unicode, UNCServerName);
RtlInitUnicodeString(&UnicodeFileName, NULL);
//
// Turn the Dos filename into an NT filename if it was given
//
if (FileName)
{
if (!RtlDosPathNameToNtPathName_U(FileName, &UnicodeFileName, NULL, NULL))
{
Status = STATUS_OBJECT_NAME_INVALID;
}
}
if (NT_SUCCESS(Status))
{
Status = ElfOpenBackupEventLogW (
&Unicode,
&UnicodeFileName,
&LogHandle
);
//
// With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
// in 3.51. This retry logic exists for 3.51 machines which don't
// recognize NT 4.0 filenames. The API should have passed Windows
// filenames vs NT.
//
if (Status == STATUS_OBJECT_PATH_NOT_FOUND && FileName != NULL)
{
DLUnicode.MaximumLength = (wcslen(FileName) * sizeof(WCHAR)) +
sizeof(wszDosDevices);
DLUnicode.Buffer = RtlAllocateHeap(
RtlProcessHeap(), 0,
DLUnicode.MaximumLength);
if (DLUnicode.Buffer != NULL)
{
wcscpy(DLUnicode.Buffer, wszDosDevices);
wcscat(DLUnicode.Buffer, FileName);
DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
Status = ElfOpenBackupEventLogW (
&Unicode,
&DLUnicode,
&LogHandle
);
RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
}
else
{
Status = STATUS_NO_MEMORY;
}
}
}
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
ReturnHandle = NULL;
}
else
{
ReturnHandle = LogHandle;
}
if (UnicodeFileName.MaximumLength)
{
RtlFreeHeap(RtlProcessHeap(), 0, UnicodeFileName.Buffer);
}
return ReturnHandle;
}
BOOL
ReadEventLogW (
HANDLE hEventLog,
DWORD dwReadFlags,
DWORD dwRecordOffset,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
DWORD *pnBytesRead,
DWORD *pnMinNumberOfBytesNeeded
)
/*++
Routine Description:
This is the client DLL entry point for the WinreadEventLog API.
Arguments:
Return Value:
Returns count of bytes read. Zero of none read.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfReadEventLogW (
hEventLog,
dwReadFlags,
dwRecordOffset,
lpBuffer,
nNumberOfBytesToRead,
pnBytesRead,
pnMinNumberOfBytesNeeded
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
ReportEventW (
HANDLE hEventLog,
WORD wType,
WORD wCategory OPTIONAL,
DWORD dwEventID,
PSID lpUserSid OPTIONAL,
WORD wNumStrings,
DWORD dwDataSize,
LPCWSTR *lpStrings OPTIONAL,
LPVOID lpRawData OPTIONAL
)
/*++
Routine Description:
This is the client DLL entry point for the ReportEvent API.
Arguments:
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
BOOL ReturnValue;
PUNICODE_STRING *pUStrings;
ULONG i;
ULONG AllocatedStrings;
//
// Convert the array of strings to an array of PUNICODE_STRINGs
// before calling ElfReportEventW.
//
pUStrings = RtlAllocateHeap(
RtlProcessHeap(), 0,
wNumStrings * sizeof(PUNICODE_STRING)
);
if (pUStrings) {
//
// Guard the memory allocation above while we peruse the user's
// buffer. If not, we'd leak it on an exception.
//
try {
//
// For each string passed in, allocate a UNICODE_STRING structure
// and set it to the matching string.
//
for (AllocatedStrings = 0; AllocatedStrings < wNumStrings;
AllocatedStrings++) {
pUStrings[AllocatedStrings] = RtlAllocateHeap(
RtlProcessHeap(), 0,
sizeof(UNICODE_STRING)
);
if (pUStrings[AllocatedStrings]) {
if (!InitUnicodeString(
pUStrings[AllocatedStrings],
lpStrings[AllocatedStrings]
)) {
//
// This string was invalid (> 64K bytes) give up
// and make sure we only free the ones we've already
// allocated (including this last one)
//
AllocatedStrings++;
Status = STATUS_INVALID_PARAMETER;
break;
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = STATUS_INVALID_PARAMETER;
}
if (Status == STATUS_SUCCESS) {
Status = ElfReportEventW (
hEventLog,
wType,
wCategory,
dwEventID,
lpUserSid,
wNumStrings,
dwDataSize,
pUStrings,
lpRawData,
0, // Flags - Paired event
NULL, // RecordNumber | support. Not
NULL // TimeWritten - in P1
);
}
//
// Free the space allocated for the UNICODE strings
// and then free the space for the array.
//
for (i = 0; i < AllocatedStrings; i++) {
if (pUStrings[i])
RtlFreeHeap (RtlProcessHeap(), 0, pUStrings[i]);
}
RtlFreeHeap (RtlProcessHeap(), 0, pUStrings);
} else {
Status = STATUS_NO_MEMORY;
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
//
// ANSI APIs
//
BOOL
ClearEventLogA (
HANDLE hEventLog,
LPCSTR BackupFileName
)
/*++
Routine Description:
This is the client DLL entry point for the ClearEventLogFile API.
The call is passed to the eventlog service on the appropriate server
identified by LogHandle.
Arguments:
LogHandle - Handle returned from a previous "Open" call. This is
used to identify the module and the server.
BackupFileName - Name of the file to back up the current log file.
NULL implies not to back up the file.
Return Value:
TRUE if success, FALSE otherwise.
--*/
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL ReturnValue;
//
// Turn the backup filename into UNICODE
//
if (BackupFileName) {
RtlInitAnsiString(&AnsiString, BackupFileName);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString,
TRUE);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
return(FALSE);
}
}
else {
RtlInitUnicodeString(&UnicodeString, NULL);
}
ReturnValue = ClearEventLogW (hEventLog, (LPCWSTR)UnicodeString.Buffer);
RtlFreeUnicodeString(&UnicodeString);
return(ReturnValue);
}
BOOL
BackupEventLogA (
HANDLE hEventLog,
LPCSTR BackupFileName
)
/*++
Routine Description:
This is the client DLL entry point for the BackupEventLogFile API.
The call is passed to the eventlog service on the appropriate server
identified by LogHandle.
Arguments:
LogHandle - Handle returned from a previous "Open" call. This is
used to identify the module and the server.
BackupFileName - Name of the file to back up the current log file.
Return Value:
TRUE if success, FALSE otherwise.
--*/
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
BOOL ReturnValue;
//
// Turn the backup filename into UNICODE
//
if (BackupFileName) {
RtlInitAnsiString(&AnsiString, BackupFileName);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString,
TRUE);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
return(FALSE);
}
}
else {
RtlInitUnicodeString(&UnicodeString, NULL);
}
ReturnValue = BackupEventLogW (hEventLog, (LPCWSTR)UnicodeString.Buffer);
RtlFreeUnicodeString(&UnicodeString);
return(ReturnValue);
}
HANDLE
OpenEventLogA (
LPCSTR UNCServerName,
LPCSTR ModuleName
)
/*++
Routine Description:
This is the client DLL entry point for the WinOpenEventLog API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
ModuleName - Supplies the name of the module to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
ANSI_STRING AnsiString;
ANSI_STRING AnsiModuleName;
NTSTATUS Status;
HANDLE LogHandle;
HANDLE ReturnHandle;
RtlInitAnsiString(&AnsiModuleName,ModuleName);
RtlInitAnsiString(&AnsiString, UNCServerName);
Status = ElfOpenEventLogA (
&AnsiString,
&AnsiModuleName,
&LogHandle
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnHandle = (HANDLE)NULL;
} else {
ReturnHandle = (HANDLE)LogHandle;
}
return ReturnHandle;
}
HANDLE
RegisterEventSourceA (
LPCSTR UNCServerName,
LPCSTR ModuleName
)
/*++
Routine Description:
This is the client DLL entry point for the RegisterEventSource API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
ModuleName - Supplies the name of the module to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
ANSI_STRING AnsiString;
ANSI_STRING AnsiModuleName;
NTSTATUS Status;
HANDLE LogHandle;
HANDLE ReturnHandle;
RtlInitAnsiString(&AnsiModuleName,ModuleName);
RtlInitAnsiString(&AnsiString, UNCServerName);
Status = ElfRegisterEventSourceA (
&AnsiString,
&AnsiModuleName,
&LogHandle
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnHandle = (HANDLE)NULL;
} else {
ReturnHandle = (HANDLE)LogHandle;
}
return ReturnHandle;
}
HANDLE
OpenBackupEventLogA (
LPCSTR UNCServerName,
LPCSTR FileName
)
/*++
Routine Description:
This is the client DLL entry point for the OpenBackupEventLog API.
It creates an RPC binding for the server specified, and stores that
and additional data away. It returns a handle to the caller that can
be used to later on access the handle-specific information.
Arguments:
UNCServerName - Server with which to bind for subsequent operations.
FileName - Supplies the filename of the logfile to associate with
this handle.
Return Value:
Returns a handle that can be used for subsequent Win API calls. If
the handle is NULL, then an error occurred.
--*/
{
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeServerName;
UNICODE_STRING UnicodeFileName;
NTSTATUS Status;
HANDLE ReturnHandle;
//
// Turn the servername into UNICODE
//
if (UNCServerName) {
RtlInitAnsiString(&AnsiString, UNCServerName);
Status = RtlAnsiStringToUnicodeString(&UnicodeServerName, &AnsiString,
TRUE);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
return(NULL);
}
}
else {
RtlInitUnicodeString(&UnicodeServerName, NULL);
}
//
// Turn the filename into UNICODE
//
if (FileName) {
RtlInitAnsiString(&AnsiString, FileName);
Status = RtlAnsiStringToUnicodeString(&UnicodeFileName, &AnsiString,
TRUE);
if ( !NT_SUCCESS(Status) ) {
RtlFreeUnicodeString(&UnicodeServerName);
BaseSetLastNTError(Status);
return(NULL);
}
}
else {
RtlInitUnicodeString(&UnicodeFileName, NULL);
}
ReturnHandle = OpenBackupEventLogW ((LPCWSTR)UnicodeServerName.Buffer,
(LPCWSTR)UnicodeFileName.Buffer);
RtlFreeUnicodeString(&UnicodeServerName);
RtlFreeUnicodeString(&UnicodeFileName);
return(ReturnHandle);
}
BOOL
ReadEventLogA (
HANDLE hEventLog,
DWORD dwReadFlags,
DWORD dwRecordOffset,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
DWORD *pnBytesRead,
DWORD *pnMinNumberOfBytesNeeded
)
/*++
Routine Description:
This is the client DLL entry point for the WinreadEventLog API.
Arguments:
Return Value:
Returns count of bytes read. Zero of none read.
--*/
{
NTSTATUS Status;
BOOL ReturnValue;
Status = ElfReadEventLogA (
hEventLog,
dwReadFlags,
dwRecordOffset,
lpBuffer,
nNumberOfBytesToRead,
pnBytesRead,
pnMinNumberOfBytesNeeded
);
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}
BOOL
ReportEventA (
HANDLE hEventLog,
WORD wType,
WORD wCategory OPTIONAL,
DWORD dwEventID,
PSID lpUserSid OPTIONAL,
WORD wNumStrings,
DWORD dwDataSize,
LPCSTR *lpStrings OPTIONAL,
LPVOID lpRawData OPTIONAL
)
/*++
Routine Description:
This is the client DLL entry point for the ReportEvent API.
Arguments:
Return Value:
Returns TRUE if success, FALSE otherwise.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
BOOL ReturnValue;
PANSI_STRING *pAStrings;
ULONG i;
ULONG AllocatedStrings;
//
// Convert the array of strings to an array of PANSI_STRINGs
// before calling ElfReportEventW.
//
pAStrings = RtlAllocateHeap(
RtlProcessHeap(), 0,
wNumStrings * sizeof(PANSI_STRING)
);
if (pAStrings) {
//
// Guard the memory allocation above while we peruse the user's
// buffer. If not, we'd leak it on an exception.
//
try {
//
// For each string passed in, allocate an ANSI_STRING structure
// and fill it in with the string.
//
for (AllocatedStrings = 0; AllocatedStrings < wNumStrings;
AllocatedStrings++) {
pAStrings[AllocatedStrings] = RtlAllocateHeap(
RtlProcessHeap(), 0,
sizeof(ANSI_STRING)
);
if (pAStrings[AllocatedStrings]) {
if (!InitAnsiString(
pAStrings[AllocatedStrings],
lpStrings[AllocatedStrings]
)) {
//
// This string was invalid (> 32K chars) give up
// and make sure we only free the ones we've already
// allocated (including this last one)
//
AllocatedStrings++;
Status = STATUS_INVALID_PARAMETER;
break;
}
}
}
}
except (EXCEPTION_EXECUTE_HANDLER) {
Status = STATUS_INVALID_PARAMETER;
}
if (Status == STATUS_SUCCESS) {
Status = ElfReportEventA (
hEventLog,
wType,
wCategory,
dwEventID,
lpUserSid,
wNumStrings,
dwDataSize,
pAStrings,
lpRawData,
0, // Flags - Paired event
NULL, // RecordNumber | support. Not
NULL // TimeWritten - in P1
);
}
//
// Free all the memory that was allocated
//
for (i = 0; i < AllocatedStrings; i++) {
if (pAStrings[i])
RtlFreeHeap (RtlProcessHeap(), 0, pAStrings[i]);
}
RtlFreeHeap (RtlProcessHeap(), 0, pAStrings);
} else {
Status = STATUS_NO_MEMORY;
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
ReturnValue = FALSE;
} else {
ReturnValue = TRUE;
}
return ReturnValue;
}