mirror of https://github.com/tongzx/nt5src
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.
1576 lines
35 KiB
1576 lines
35 KiB
/*++
|
|
|
|
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;
|
|
|
|
}
|
|
|