3.1.4.7 ElfrReadELW (Opnum 10)

The ElfrReadELW (Opnum 10) method reads events from the event log; the server transmits these events to the client and advances the reader's position within the event log associated with the server context handle that is passed in the LogHandle parameter. The strings in the returned event MUST be in [UNICODE].

 NTSTATUS ElfrReadELW(
   [in] IELF_HANDLE LogHandle,
   [in] unsigned long ReadFlags,
   [in] unsigned long RecordOffset,
   [in] RULONG NumberOfBytesToRead,
   [out, size_is(NumberOfBytesToRead)] 
     unsigned char* Buffer,
   [out] unsigned long* NumberOfBytesRead,
   [out] unsigned long* MinNumberOfBytesNeeded
 );

LogHandle: Handle to an event log to read. This parameter is a server context handle, as specified in section 2.2.6.

ReadFlags: The caller MUST specify whether the read is to start at a specific record or is to proceed from the last record read. The value MUST include one and only one of the following flags.

Value

Meaning

EVENTLOG_SEQUENTIAL_READ

0x00000001

Read operation proceeds sequentially from the last call to the ElfrReadELW (section 3.1.4.7) method or the ElfrReadELA (section 3.1.4.8) method, using this handle. This flag MUST NOT be used with EVENTLOG_SEEK_READ.

EVENTLOG_SEEK_READ

0x00000002

Read operation proceeds from the record specified by the RecordOffset parameter. This flag MUST NOT be used with EVENTLOG_SEQUENTIAL_READ.

Because the method reads as many records as can fit in the buffer, the caller MUST also set one and only one of the following flags to indicate the direction for successive read operations.

Value

Meaning

EVENTLOG_FORWARDS_READ

0x00000004

Log is read in chronological order. This flag MUST NOT be used with EVENTLOG_BACKWARDS_READ.

EVENTLOG_BACKWARDS_READ

0x00000008

Log is read in reverse chronological order. This flag MUST NOT be used with EVENTLOG_FORWARDS_READ.

RecordOffset: Log entry record number from which the read operation starts (this is not a byte offset but a number). This parameter MUST be ignored unless the EVENTLOG_SEEK_READ bit is set in the ReadFlags parameter.

NumberOfBytesToRead: Size of the Buffer in bytes. This is the maximum amount of data that can be read.

Buffer: The buffer in which to place data read from the event log.

NumberOfBytesRead: Pointer to a variable that receives the number of bytes actually read by the method.

MinNumberOfBytesNeeded: If the method fails because the buffer is too small to fit even a single record, this MUST be set to the minimum number of bytes needed to fit the next record. Otherwise, this MUST NOT be set, and MUST be ignored by the caller.

Return Values: The method MUST return STATUS_SUCCESS (0x00000000) on success. If the method is successful, the read position MUST be adjusted by NumberOfBytesRead. The method MUST return STATUS_BUFFER_TOO_SMALL (0xC0000023) if the buffer is too small to fit even one record. Otherwise, it MUST return any other implementation-based, nonzero NTSTATUS value specified in [MS-ERREF].

In response to this request from the client, the server MUST first check that the handle is valid.<19> The server MUST fail the operation with the error STATUS_INVALID_HANDLE (0xC0000008) if the handle is invalid.

Then the server MUST determine what record to read next. The context handle LogHandle maps to a server side object (as specified in section 3.1.1.5) which contains the last reading record information. This mapping procedure is done through the RPC layer. For detailed information on how to use context handles and how RPC maintains the context handle mapping, refer to [MSDN-CH].

Note In the following procedure, "handle" refers to the server object which is mapped by the context handle LogHandle.

There are three cases:

  1. If the ReadFlags field includes the EVENTLOG_SEQUENTIAL_READ flag, and the log has never been read as suggested by the handle, the next record MUST be the oldest record in the file when the EVENTLOG_FORWARDS_READ flag is set; or it MUST be the newest record in the file if EVENTLOG_BACKWARDS_READ is set.

  2. If the ReadFlags field includes the EVENTLOG_SEQUENTIAL_READ flag, and the handle is indicating the last record which is previously used for reading, the next record MUST be determined by taking the last record read value from the handle state and either adding one to it (EVENTLOG_FORWARDS_READ is set) or subtracting one from it.

  3. If the ReadFlags field includes the EVENTLOG_SEEK_READ flag, the next record to read MUST be specified by the RecordOffset parameter.

If the next record to be read is out of range, the server MUST fail the operation. Examples include the caller trying to seek to a record that does not exist, or the caller requesting a sequential read when all the records have been read. The server can return STATUS_INVALID_PARAMETER (0xC000000D) for the first case, and STATUS_END_OF_FILE (0xC0000011) for the second one.

Once the next record is determined, the server MUST determine how large that record is. If the next record is too large to fit into the buffer, the server MUST fail the method, set the MinNumberOfBytesNeeded parameter to the number of bytes needed, and specifically return STATUS_BUFFER_TOO_SMALL (0xC0000023).

The server SHOULD check if the passing flag is valid or not and it SHOULD fail the method if the flags are in ambiguous or mutually exclusive combinations. For instance, if EVENTLOG_FORWARDS_READ and EVENTLOG_BACKWARDS_READ are both set. In such cases, the server can use the following behavior:

In the case where EVENTLOG_FORWARDS_READ and EVENTLOG_BACKWARDS_READ are both set, the flag EVENTLOG_BACKWARDS_READ is ignored. In other words, the server treats it as if only the EVENTLOG_FORWARDS_READ is set. If neither of the two flags are set, the server will treat it as if the EVENTLOG_BACKWARDS_READ flag is set. In the case where EVENTLOG_SEQUENTIAL_READ and EVENTLOG_SEEK_READ are both set, the flag EVENTLOG_SEEK_READ is ignored, and the server will treat it as if only EVENTLOG_SEQUENTIAL_READ is set. If neither of the two flags are set, the server will treat it as if EVENTLOG_SEQUENTIAL_READ is set. In all of the cases, the server does not return the error code for the wrong flags.

If the above checks all succeed, the server MUST attempt to copy as many records as it can into the buffer. The server MUST only copy full event records, and it MUST stop if there are no more events to be read. The server MUST update the handle state to save the record number of the last event copied into the buffer.

The server MUST return a value indicating success or failure for this operation.