1950 lines
46 KiB
C
1950 lines
46 KiB
C
|
||
/*++
|
||
|
||
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;
|
||
|
||
|
||
|
||
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;
|
||
|
||
//
|
||
// If this fails, we're leaking
|
||
//
|
||
ASSERT(pGlobalComputerNameU == NULL && pGlobalComputerNameA == NULL);
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
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);
|
||
|
||
}
|