1577 lines
35 KiB
C
1577 lines
35 KiB
C
/*++
|
||
|
||
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;
|
||
|
||
}
|
||
|