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.
2023 lines
49 KiB
2023 lines
49 KiB
|
|
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
APISTUB.C
|
|
|
|
Abstract:
|
|
|
|
This module contains the client ends of the Elf APIs.
|
|
|
|
|
|
Author:
|
|
|
|
Rajen Shah (rajens) 29-Jul-1991
|
|
|
|
|
|
Revision History:
|
|
|
|
29-Jul-1991 RajenS
|
|
Created
|
|
|
|
13-Jan-1997 Added extensions for clustering to support replicated
|
|
eventlogs
|
|
--*/
|
|
/****
|
|
@doc EXTERNAL INTERFACES EVTLOG
|
|
****/
|
|
|
|
#include <elfclntp.h>
|
|
#include <lmerr.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
//
|
|
// Global data
|
|
//
|
|
PUNICODE_STRING pGlobalComputerNameU;
|
|
PANSI_STRING pGlobalComputerNameA;
|
|
|
|
long glInitNameCount = 0;
|
|
|
|
VOID
|
|
w_GetComputerName ( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the name of the computer. It checks the global
|
|
variable to see if the computer name has already been determined.
|
|
If not, it updates that variable with the name.
|
|
It does this for the UNICODE and the ANSI versions.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
|
|
--*/
|
|
{
|
|
PUNICODE_STRING pNameU;
|
|
PANSI_STRING pNameA;
|
|
LPSTR szName;
|
|
LPWSTR wszName;
|
|
DWORD dwStatus;
|
|
|
|
long lTemp;
|
|
|
|
// Grab the lock.
|
|
|
|
lTemp = InterlockedExchange(&glInitNameCount, 1);
|
|
if(lTemp != 0)
|
|
{
|
|
// someone else got the lock, spin till they are done and then return.
|
|
while(lTemp == 1)
|
|
{
|
|
Sleep(100);
|
|
lTemp = InterlockedExchange(&glInitNameCount, 1);
|
|
}
|
|
if(pGlobalComputerNameU)
|
|
{
|
|
glInitNameCount = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// now that we own the lock, do one last check to make sure someone else didnt do the allocation
|
|
//
|
|
if(pGlobalComputerNameU)
|
|
{
|
|
glInitNameCount = 0;
|
|
return;
|
|
}
|
|
|
|
pNameU = MIDL_user_allocate (sizeof (UNICODE_STRING));
|
|
pNameA = MIDL_user_allocate (sizeof (ANSI_STRING));
|
|
|
|
if ((pNameU != NULL) && (pNameA != NULL)) {
|
|
|
|
dwStatus = ElfpGetComputerName(&szName, &wszName);
|
|
|
|
if (dwStatus == NO_ERROR) {
|
|
|
|
//
|
|
// ElfpComputerName has allocated a buffer to contain the
|
|
// ASCII name of the computer. We use that for the ANSI
|
|
// string structure.
|
|
//
|
|
RtlInitAnsiString ( pNameA, szName );
|
|
RtlInitUnicodeString ( pNameU, wszName );
|
|
|
|
} else {
|
|
|
|
//
|
|
// We could not get the computer name for some reason. Set up
|
|
// the golbal pointer to point to the NULL string.
|
|
//
|
|
RtlInitAnsiString ( pNameA, "\0");
|
|
RtlInitUnicodeString ( pNameU, L"\0");
|
|
}
|
|
|
|
pGlobalComputerNameU = pNameU;
|
|
pGlobalComputerNameA = pNameA;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// In case one of the two was allocated.
|
|
//
|
|
MIDL_user_free (pNameU);
|
|
MIDL_user_free (pNameA);
|
|
}
|
|
glInitNameCount = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
PUNICODE_STRING
|
|
TmpGetComputerNameW ( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the UNICODE name of the computer. It checks the global
|
|
variable to see if the computer name has already been determined.
|
|
If not, it calls the worker routine to do that.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
Returns a pointer to the computer name, or a NULL.
|
|
|
|
|
|
--*/
|
|
{
|
|
if (pGlobalComputerNameU == NULL) {
|
|
w_GetComputerName();
|
|
}
|
|
return (pGlobalComputerNameU);
|
|
}
|
|
|
|
|
|
|
|
PANSI_STRING
|
|
TmpGetComputerNameA ( )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the ANSI name of the computer. It checks the global
|
|
variable to see if the computer name has already been determined.
|
|
If not, it calls the worker routine to do that.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
Returns a pointer to the computer name, or a NULL.
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
if (pGlobalComputerNameA == NULL) {
|
|
w_GetComputerName();
|
|
}
|
|
return (pGlobalComputerNameA);
|
|
}
|
|
|
|
//
|
|
// These APIs only have one interface, since they don't take or return strings
|
|
//
|
|
|
|
NTSTATUS
|
|
ElfNumberOfRecords(
|
|
IN HANDLE LogHandle,
|
|
OUT PULONG NumberOfRecords
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Make sure the output pointer is valid
|
|
//
|
|
|
|
if (!NumberOfRecords) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrNumberOfRecords (
|
|
(IELF_HANDLE) LogHandle,
|
|
NumberOfRecords
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ElfOldestRecord(
|
|
IN HANDLE LogHandle,
|
|
OUT PULONG OldestRecordNumber
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
//
|
|
// Make sure the output pointer is valid
|
|
//
|
|
|
|
if (!OldestRecordNumber) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrOldestRecord (
|
|
(IELF_HANDLE) LogHandle,
|
|
OldestRecordNumber
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfChangeNotify(
|
|
IN HANDLE LogHandle,
|
|
IN HANDLE Event
|
|
)
|
|
{
|
|
|
|
NTSTATUS status;
|
|
RPC_CLIENT_ID RpcClientId;
|
|
CLIENT_ID ClientId;
|
|
|
|
//
|
|
// Map the handles to something that RPC can understand
|
|
//
|
|
|
|
ClientId = NtCurrentTeb()->ClientId;
|
|
RpcClientId.UniqueProcess = (ULONG)((ULONG_PTR)ClientId.UniqueProcess);
|
|
RpcClientId.UniqueThread = (ULONG)((ULONG_PTR)ClientId.UniqueThread);
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrChangeNotify (
|
|
(IELF_HANDLE)((ULONG_PTR)LogHandle),
|
|
RpcClientId,
|
|
(DWORD)(ULONG_PTR)Event
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfGetLogInformation(
|
|
IN HANDLE LogHandle,
|
|
IN ULONG InfoLevel,
|
|
OUT PVOID lpBuffer,
|
|
IN ULONG cbBufSize,
|
|
OUT PULONG pcbBytesNeeded
|
|
)
|
|
{
|
|
NTSTATUS ntStatus;
|
|
|
|
//
|
|
// Make sure the Infolevel is valid
|
|
//
|
|
|
|
switch (InfoLevel) {
|
|
|
|
case EVENTLOG_FULL_INFO:
|
|
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
ntStatus = ElfrGetLogInformation(
|
|
(IELF_HANDLE) LogHandle,
|
|
InfoLevel,
|
|
lpBuffer,
|
|
cbBufSize,
|
|
pcbBytesNeeded);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
ntStatus = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ntStatus = STATUS_INVALID_LEVEL;
|
|
break;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
//
|
|
// UNICODE APIs
|
|
//
|
|
|
|
NTSTATUS
|
|
ElfOpenEventLogW (
|
|
IN PUNICODE_STRING UNCServerName,
|
|
IN PUNICODE_STRING LogName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfOpenEventLog 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.
|
|
|
|
LogName - Supplies the name of the module for the logfile
|
|
to associate with this handle.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
NTSTATUS ApiStatus;
|
|
UNICODE_STRING RegModuleName;
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
BOOLEAN fWasEnabled = FALSE;
|
|
BOOL fIsSecurityLog;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !LogName || LogName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &RegModuleName, UNICODE_NULL);
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
fIsSecurityLog = (_wcsicmp(ELF_SECURITY_MODULE_NAME, LogName->Buffer) == 0);
|
|
|
|
if (fIsSecurityLog) {
|
|
|
|
//
|
|
// Tacitly attempt to enable the SE_SECURITY_PRIVILEGE so we can
|
|
// can check it on the server side. We ignore the return value
|
|
// because it's possible for this call to fail here but for the
|
|
// user to have this privilege if the log is on a remote server.
|
|
//
|
|
// Note that we make this call on behalf of the client to avoid
|
|
// a regression when we check for the privilege on the server
|
|
// side -- without this call, 3rd party apps that successfully
|
|
// called this API before would fail. Under normal circumstances,
|
|
// this is not an encouraged practice.
|
|
//
|
|
|
|
//
|
|
// -- This should really be done via ImpersonateSelf()
|
|
// and adjusting the thread token
|
|
//
|
|
ApiStatus = RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
status = ElfrOpenELW(
|
|
ServerNameString,
|
|
(PRPC_UNICODE_STRING) LogName,
|
|
(PRPC_UNICODE_STRING) &RegModuleName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
|
|
if (fIsSecurityLog && NT_SUCCESS(ApiStatus)) {
|
|
|
|
//
|
|
// Restore the state
|
|
//
|
|
|
|
RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
|
|
fWasEnabled,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfRegisterEventSourceW (
|
|
IN PUNICODE_STRING UNCServerName,
|
|
IN PUNICODE_STRING ModuleName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfRegisterEventSource 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.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UNICODE_STRING RegModuleName;
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !ModuleName || ModuleName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &RegModuleName, UNICODE_NULL);
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
status = ElfrRegisterEventSourceW(
|
|
ServerNameString,
|
|
(PRPC_UNICODE_STRING)ModuleName,
|
|
(PRPC_UNICODE_STRING)&RegModuleName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfOpenBackupEventLogW (
|
|
IN PUNICODE_STRING UNCServerName,
|
|
IN PUNICODE_STRING BackupFileName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfOpenBackupEventLog 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.
|
|
|
|
BackupFileName - Supplies the filename of the module to associate with
|
|
this handle.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !BackupFileName || BackupFileName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
|
|
status = ElfrOpenBELW(
|
|
ServerNameString,
|
|
(PRPC_UNICODE_STRING)BackupFileName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfClearEventLogFileW (
|
|
IN HANDLE LogHandle,
|
|
IN PUNICODE_STRING BackupFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfClearEventLogFile 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:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrClearELFW (
|
|
(IELF_HANDLE) LogHandle,
|
|
(PRPC_UNICODE_STRING)BackupFileName
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfBackupEventLogFileW (
|
|
IN HANDLE LogHandle,
|
|
IN PUNICODE_STRING BackupFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfBackupEventLogFile 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:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS ApiStatus;
|
|
BOOLEAN fWasEnabled;
|
|
|
|
//
|
|
// Make sure input pointers are valid
|
|
//
|
|
|
|
if (!BackupFileName || BackupFileName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Tacitly attempt to enable the SE_BACKUP_PRIVILEGE so we can
|
|
// can check it on the server side
|
|
//
|
|
// Note that we make this call on behalf of the client to avoid
|
|
// a regression when we check for the privilege on the server
|
|
// side -- without this call, 3rd party apps that successfully
|
|
// called this API before would fail. Under normal circumstances,
|
|
// this is not an encouraged practice.
|
|
//
|
|
|
|
//
|
|
// -- This should really be done via ImpersonateSelf()
|
|
// and adjusting the thread token
|
|
//
|
|
ApiStatus = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrBackupELFW (
|
|
(IELF_HANDLE) LogHandle,
|
|
(PRPC_UNICODE_STRING)BackupFileName);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
//
|
|
// Restore the client's privilege state to what it was before
|
|
//
|
|
|
|
if (NT_SUCCESS(ApiStatus)) {
|
|
|
|
RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
|
|
fWasEnabled,
|
|
TRUE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfCloseEventLog (
|
|
IN HANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfCloseEventLog API.
|
|
It closes the RPC binding, and frees any memory allocated for the
|
|
handle.
|
|
|
|
|
|
Arguments:
|
|
|
|
LogHandle - Handle returned from a previous "Open" call.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call server
|
|
|
|
status = ElfrCloseEL (
|
|
(PIELF_HANDLE) &LogHandle
|
|
);
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfDeregisterEventSource (
|
|
IN HANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfDeregisterEventSource API.
|
|
It closes the RPC binding, and frees any memory allocated for the
|
|
handle.
|
|
|
|
|
|
Arguments:
|
|
|
|
LogHandle - Handle returned from a previous "Open" call.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call server
|
|
|
|
status = ElfrDeregisterEventSource (
|
|
(PIELF_HANDLE) &LogHandle
|
|
);
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfReadEventLogW (
|
|
IN HANDLE LogHandle,
|
|
IN ULONG ReadFlags,
|
|
IN ULONG RecordNumber,
|
|
OUT PVOID Buffer,
|
|
IN ULONG NumberOfBytesToRead,
|
|
OUT PULONG NumberOfBytesRead,
|
|
OUT PULONG MinNumberOfBytesNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfReadEventLog API.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
ULONG FlagBits;
|
|
|
|
//
|
|
// Make sure the output pointers are valid
|
|
//
|
|
|
|
if (!Buffer || !NumberOfBytesRead || !MinNumberOfBytesNeeded) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Ensure that the ReadFlags we got are valid.
|
|
// Make sure that one of each type of bit is set.
|
|
//
|
|
FlagBits = ReadFlags & (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ);
|
|
|
|
if ((FlagBits > 2) || (FlagBits == 0)) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
FlagBits = ReadFlags & (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ);
|
|
|
|
if ((FlagBits > 8) || (FlagBits == 0)) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrReadELW (
|
|
(IELF_HANDLE) LogHandle,
|
|
ReadFlags,
|
|
RecordNumber,
|
|
NumberOfBytesToRead,
|
|
Buffer,
|
|
NumberOfBytesRead,
|
|
MinNumberOfBytesNeeded
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
// Return status and bytes read/required.
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfReportEventW (
|
|
IN HANDLE LogHandle,
|
|
IN USHORT EventType,
|
|
IN USHORT EventCategory OPTIONAL,
|
|
IN ULONG EventID,
|
|
IN PSID UserSid,
|
|
IN USHORT NumStrings,
|
|
IN ULONG DataSize,
|
|
IN PUNICODE_STRING *Strings,
|
|
IN PVOID Data,
|
|
IN USHORT Flags,
|
|
IN OUT PULONG RecordNumber OPTIONAL,
|
|
IN OUT PULONG TimeWritten OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfReportEvent API.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
Note:
|
|
|
|
The last three parameters (Flags, RecordNumber and TimeWritten) are
|
|
designed to be used by Security Auditing for the implementation of
|
|
paired events (associating a file open event with the subsequent file
|
|
close). This will not be implemented in Product 1, but the API is
|
|
defined to allow easier support of this in a later release.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PUNICODE_STRING pComputerNameU;
|
|
LARGE_INTEGER Time;
|
|
ULONG EventTime;
|
|
|
|
//
|
|
// Generate the time of the event. This is done on the client side
|
|
// since that is where the event occurred.
|
|
//
|
|
NtQuerySystemTime(&Time);
|
|
RtlTimeToSecondsSince1970(&Time,
|
|
&EventTime
|
|
);
|
|
|
|
//
|
|
// Generate the ComputerName of the client.
|
|
// We have to do this in the client side since this call may be
|
|
// remoted to another server and we would not necessarily have
|
|
// the computer name there.
|
|
//
|
|
pComputerNameU = TmpGetComputerNameW();
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrReportEventW (
|
|
(IELF_HANDLE) LogHandle,
|
|
EventTime,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
NumStrings,
|
|
DataSize,
|
|
(PRPC_UNICODE_STRING)pComputerNameU,
|
|
UserSid,
|
|
(PRPC_UNICODE_STRING *)Strings,
|
|
Data,
|
|
Flags,
|
|
RecordNumber,
|
|
TimeWritten
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// ANSI APIs
|
|
//
|
|
|
|
NTSTATUS
|
|
ElfOpenEventLogA (
|
|
IN PANSI_STRING UNCServerName,
|
|
IN PANSI_STRING LogName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfOpenEventLog 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.
|
|
|
|
LogName - Supplies the name of the module for the logfile to
|
|
associate with this handle.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
NTSTATUS ApiStatus;
|
|
ANSI_STRING RegModuleName;
|
|
EVENTLOG_HANDLE_A ServerNameString;
|
|
BOOLEAN fWasEnabled = FALSE;
|
|
BOOL fIsSecurityLog;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !LogName || LogName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
RtlInitAnsiString( &RegModuleName, ELF_APPLICATION_MODULE_NAME_ASCII );
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
fIsSecurityLog = (_stricmp(ELF_SECURITY_MODULE_NAME_ASCII, LogName->Buffer) == 0);
|
|
|
|
if (fIsSecurityLog) {
|
|
|
|
//
|
|
// Tacitly attempt to enable the SE_SECURITY_PRIVILEGE so we can
|
|
// can check it on the server side. We ignore the return value
|
|
// because it's possible for this call to fail here but for the
|
|
// user to have this privilege if the log is on a remote server
|
|
//
|
|
// Note that we make this call on behalf of the client to avoid
|
|
// a regression when we check for the privilege on the server
|
|
// side -- without this call, 3rd party apps that successfully
|
|
// called this API before would fail. Under normal circumstances,
|
|
// this is not an encouraged practice.
|
|
//
|
|
|
|
//
|
|
// -- This should really be done via ImpersonateSelf()
|
|
// and adjusting the thread token
|
|
//
|
|
ApiStatus = RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
status = ElfrOpenELA (
|
|
ServerNameString,
|
|
(PRPC_STRING) LogName,
|
|
(PRPC_STRING) &RegModuleName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
if (fIsSecurityLog && NT_SUCCESS(ApiStatus)) {
|
|
|
|
//
|
|
// Restore the state
|
|
//
|
|
|
|
RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
|
|
fWasEnabled,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfRegisterEventSourceA (
|
|
IN PANSI_STRING UNCServerName,
|
|
IN PANSI_STRING ModuleName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfOpenEventLog 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.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ANSI_STRING RegModuleName;
|
|
EVENTLOG_HANDLE_A ServerNameString;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !ModuleName || ModuleName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
RtlInitAnsiString( &RegModuleName, ELF_APPLICATION_MODULE_NAME_ASCII );
|
|
|
|
if ( NT_SUCCESS (status) ) {
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
status = ElfrRegisterEventSourceA (
|
|
ServerNameString,
|
|
(PRPC_STRING)ModuleName,
|
|
(PRPC_STRING)&RegModuleName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfOpenBackupEventLogA (
|
|
IN PANSI_STRING UNCServerName,
|
|
IN PANSI_STRING FileName,
|
|
OUT PHANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfOpenBackupEventLog 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.
|
|
|
|
LogHandle - Location where log handle is to be returned.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code and, if no error, a handle that can be used
|
|
for subsequent Elf API calls.
|
|
|
|
|
|
--*/
|
|
{
|
|
EVENTLOG_HANDLE_A ServerNameString;
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Make sure input & output pointers are valid
|
|
//
|
|
|
|
if (!LogHandle || !FileName || FileName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
|
|
ServerNameString = UNCServerName->Buffer;
|
|
} else {
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
// Call service via RPC. Pass in major and minor version numbers.
|
|
|
|
*LogHandle = NULL; // Must be NULL so RPC fills it in
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
|
|
RpcTryExcept {
|
|
|
|
status = ElfrOpenBELA (
|
|
ServerNameString,
|
|
(PRPC_STRING)FileName,
|
|
ELF_VERSION_MAJOR,
|
|
ELF_VERSION_MINOR,
|
|
(PIELF_HANDLE) LogHandle
|
|
);
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfClearEventLogFileA (
|
|
IN HANDLE LogHandle,
|
|
IN PANSI_STRING BackupFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfClearEventLogFile 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:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrClearELFA (
|
|
(IELF_HANDLE) LogHandle,
|
|
(PRPC_STRING)BackupFileName
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ElfBackupEventLogFileA (
|
|
IN HANDLE LogHandle,
|
|
IN PANSI_STRING BackupFileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfBackupEventLogFile 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:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS ApiStatus;
|
|
BOOLEAN fWasEnabled;
|
|
|
|
//
|
|
// Make sure input pointers are valid
|
|
//
|
|
|
|
if (!BackupFileName || BackupFileName->Length == 0) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Tacitly attempt to enable the SE_BACKUP_PRIVILEGE so we can
|
|
// can check it on the server side
|
|
//
|
|
// Note that we make this call on behalf of the client to avoid
|
|
// a regression when we check for the privilege on the server
|
|
// side -- without this call, 3rd party apps that successfully
|
|
// called this API before would fail. Under normal circumstances,
|
|
// this is not an encouraged practice.
|
|
//
|
|
|
|
//
|
|
// -- This should really be done via ImpersonateSelf()
|
|
// and adjusting the thread token
|
|
//
|
|
ApiStatus = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
|
|
TRUE,
|
|
FALSE,
|
|
&fWasEnabled);
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service entry point
|
|
|
|
status = ElfrBackupELFA (
|
|
(IELF_HANDLE) LogHandle,
|
|
(PRPC_STRING)BackupFileName
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
//
|
|
// Restore the client's privilege state to what it was before
|
|
//
|
|
|
|
if (NT_SUCCESS(ApiStatus)) {
|
|
|
|
RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
|
|
fWasEnabled,
|
|
TRUE,
|
|
&fWasEnabled);
|
|
}
|
|
|
|
return (status);
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfReadEventLogA (
|
|
IN HANDLE LogHandle,
|
|
IN ULONG ReadFlags,
|
|
IN ULONG RecordNumber,
|
|
OUT PVOID Buffer,
|
|
IN ULONG NumberOfBytesToRead,
|
|
OUT PULONG NumberOfBytesRead,
|
|
OUT PULONG MinNumberOfBytesNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfReadEventLog API.
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
ULONG FlagBits;
|
|
|
|
//
|
|
// Make sure the output pointers are valid
|
|
//
|
|
|
|
if (!Buffer || !NumberOfBytesRead || !MinNumberOfBytesNeeded) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Ensure that the ReadFlags we got are valid.
|
|
// Make sure that one of each type of bit is set.
|
|
//
|
|
FlagBits = ReadFlags & (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ);
|
|
|
|
if ( (FlagBits == (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ))
|
|
|| (FlagBits == 0)) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
FlagBits = ReadFlags & (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ);
|
|
|
|
if ( (FlagBits == (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ))
|
|
|| (FlagBits == 0)) {
|
|
return(STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrReadELA (
|
|
(IELF_HANDLE) LogHandle,
|
|
ReadFlags,
|
|
RecordNumber,
|
|
NumberOfBytesToRead,
|
|
Buffer,
|
|
NumberOfBytesRead,
|
|
MinNumberOfBytesNeeded
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
// Return status and bytes read/required.
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
ElfReportEventA (
|
|
IN HANDLE LogHandle,
|
|
IN USHORT EventType,
|
|
IN USHORT EventCategory OPTIONAL,
|
|
IN ULONG EventID,
|
|
IN PSID UserSid,
|
|
IN USHORT NumStrings,
|
|
IN ULONG DataSize,
|
|
IN PANSI_STRING *Strings,
|
|
IN PVOID Data,
|
|
IN USHORT Flags,
|
|
IN OUT PULONG RecordNumber OPTIONAL,
|
|
IN OUT PULONG TimeWritten OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfReportEvent API.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
Note:
|
|
|
|
The last three parameters (Flags, RecordNumber and TimeWritten) are
|
|
designed to be used by Security Auditing for the implementation of
|
|
paired events (associating a file open event with the subsequent file
|
|
close). This will not be implemented in Product 1, but the API is
|
|
defined to allow easier support of this in a later release.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PANSI_STRING pComputerNameA;
|
|
LARGE_INTEGER Time;
|
|
ULONG EventTime;
|
|
|
|
//
|
|
// Generate the time of the event. This is done on the client side
|
|
// since that is where the event occurred.
|
|
//
|
|
NtQuerySystemTime(&Time);
|
|
RtlTimeToSecondsSince1970(&Time,
|
|
&EventTime
|
|
);
|
|
|
|
//
|
|
// Generate the ComputerName of the client.
|
|
// We have to do this in the client side since this call may be
|
|
// remoted to another server and we would not necessarily have
|
|
// the computer name there.
|
|
//
|
|
pComputerNameA = TmpGetComputerNameA();
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrReportEventA (
|
|
(IELF_HANDLE) LogHandle,
|
|
EventTime,
|
|
EventType,
|
|
EventCategory,
|
|
EventID,
|
|
NumStrings,
|
|
DataSize,
|
|
(PRPC_STRING)pComputerNameA,
|
|
UserSid,
|
|
(PRPC_STRING*)Strings,
|
|
Data,
|
|
Flags,
|
|
RecordNumber,
|
|
TimeWritten
|
|
);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|
|
/****
|
|
@func NTSTATUS | ElfRegisterClusterSvc| The cluster service registers
|
|
itself with the event log service at initialization by calling this api.
|
|
|
|
@parm IN PUNICODE_STRING | UNCServerName | Inidicates the server on which the
|
|
cluster service will register with the eventlog service. This must
|
|
be the local node.
|
|
|
|
@parm OUT PULONG | pulSize | A pointer to a long that returns the size of the
|
|
packed event information structure that is returned.
|
|
|
|
@parm OUT PPACKEDEVENTINFO | *ppPackedEventInfo| A pointer to the packed event information
|
|
structure for propagation is returned via this parameter.
|
|
|
|
@comm The elf client validates parameters and called the servier entry point.
|
|
|
|
@rdesc Returns a result code. ERROR_SUCCESS on success.
|
|
|
|
@xref <f ElfrRegisterClusterSvc>
|
|
****/
|
|
NTSTATUS
|
|
ElfRegisterClusterSvc (
|
|
IN PUNICODE_STRING UNCServerName,
|
|
OUT PULONG pulSize,
|
|
OUT PPACKEDEVENTINFO *ppPackedEventInfo
|
|
)
|
|
{
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
|
|
NTSTATUS status;
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
|
|
{
|
|
ServerNameString = UNCServerName->Buffer;
|
|
}
|
|
else
|
|
{
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrRegisterClusterSvc (ServerNameString, pulSize,
|
|
(PBYTE *)ppPackedEventInfo);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return(status);
|
|
}
|
|
|
|
/****
|
|
@func NTSTATUS | ElfDeregisterClusterSvc| Before stopping the cluster
|
|
service deregisters itself for propagation of events from the
|
|
eventlog service.
|
|
|
|
@parm IN PUNICODE_STRING | UNCServerName | Inidicates the server on which the
|
|
cluster service will register with the eventlog service. This must
|
|
be on the local node.
|
|
|
|
@comm The elf client forwards this to the appropriate eventlog server entry point.
|
|
|
|
@rdesc Returns a result code. ERROR_SUCCESS on success.
|
|
|
|
@xref <f ElfDeregisterClusterSvc> <f ElfrDeregisterClusterSvc>
|
|
****/
|
|
NTSTATUS
|
|
ElfDeregisterClusterSvc(
|
|
IN PUNICODE_STRING UNCServerName
|
|
)
|
|
{
|
|
|
|
NTSTATUS status;
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
|
|
{
|
|
ServerNameString = UNCServerName->Buffer;
|
|
}
|
|
else
|
|
{
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrDeregisterClusterSvc (ServerNameString);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
return(status);
|
|
|
|
}
|
|
|
|
|
|
/****
|
|
@func NTSTATUS | ElfWriteClusterEvents| The cluster service calls this
|
|
api to log events reported at other nodes of the cluster.
|
|
|
|
@parm IN EVENTLOG_HANDLE_W | UNCServerName | Not used.
|
|
|
|
@parm IN ULONG | ulSize | The size of the packed event information structure.
|
|
|
|
@parm IN PACKEDEVENTINFO | pPackedEventInfo| A pointer to the packed event information
|
|
structure for propagation.
|
|
|
|
@comm The elf client validates the parameters and forwards this to the appropriate
|
|
entry point in the eventlog server.
|
|
|
|
@rdesc Returns a result code. ERROR_SUCCESS on success.
|
|
|
|
@xref
|
|
****/
|
|
NTSTATUS
|
|
ElfWriteClusterEvents(
|
|
IN PUNICODE_STRING UNCServerName,
|
|
IN ULONG ulSize,
|
|
IN PPACKEDEVENTINFO pPackedEventInfo)
|
|
{
|
|
|
|
NTSTATUS status;
|
|
EVENTLOG_HANDLE_W ServerNameString;
|
|
|
|
//validate input parameters
|
|
if (!pPackedEventInfo || !ulSize || (pPackedEventInfo->ulSize != ulSize))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
|
|
if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
|
|
{
|
|
ServerNameString = UNCServerName->Buffer;
|
|
}
|
|
else
|
|
{
|
|
ServerNameString = NULL;
|
|
}
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call service
|
|
|
|
status = ElfrWriteClusterEvents (ServerNameString, ulSize,
|
|
(PBYTE)pPackedEventInfo);
|
|
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
return(status);
|
|
|
|
}
|
|
NTSTATUS
|
|
ElfFlushEventLog (
|
|
IN HANDLE LogHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the client DLL entry point for the ElfFlushEventLog API.
|
|
|
|
Arguments:
|
|
|
|
LogHandle - Handle returned from a previous "Open" call.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns an NTSTATUS code.
|
|
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
|
|
//
|
|
// Do the RPC call with an exception handler since RPC will raise an
|
|
// exception if anything fails. It is up to us to figure out what
|
|
// to do once the exception is raised.
|
|
//
|
|
RpcTryExcept {
|
|
|
|
// Call server
|
|
|
|
status = ElfrFlushEL (
|
|
(IELF_HANDLE) LogHandle
|
|
);
|
|
}
|
|
RpcExcept (1) {
|
|
|
|
status = I_RpcMapWin32Status(RpcExceptionCode());
|
|
}
|
|
RpcEndExcept
|
|
|
|
return (status);
|
|
|
|
}
|
|
|
|
|