4.2 Write Events to an Event Log

In this example, the client application wants to write events to an event log. This involves the following:

  1. To establish a connection to the server, the client application calls ElfrRegisterEventSourceW with the following values for the parameters.

              NTSTATUS = {to be filled in by server}
                 ElfrRegisterEventSourceW(
                   [in] EVENTLOG_HANDLE_W 
                      UNCServerName = "servername",
                   [in] PRPC_UNICODE_STRING ModuleName = {"MySource"},
                   [in] PRPC_UNICODE_STRING RegModuleName = {""},
                   [in] unsigned long MajorVersion = 0x00000001,
                   [in] unsigned long MinorVersion = 0x00000001,
                   [out] IELF_HANDLE * LogHandle = 
                      {to be filled in by server}
                   );
      
    

     The server verifies that the client application has write access to the application log. For example, assume that MySource is registered under the application log. If the server has a CustomSD specified in the registry (as specified in section 3.1.1.2) like the following security descriptor that was written using the Security Descriptor Definition Language (SDDL) (specified in [MS-DTYP]):  "O:BAG:SYD:(A;;0x7;;;SY)(A;;0x7;;;BA)(A;;0x1;;;S-1-5-32-573)". It means that the local system and administrators have the right to write, read or clear the application log, but event log users are only able to read the application log. Using this security descriptor, the server can check if a client has write access to the application log.

    If the check is successful, the server returns a handle to the client application. The server maintains an association between the handle and a particular event log. The handle is returned as IELF_HANDLE, and its value will be:

     typedef [context_handle] struct _ELF_HANDLE {
         ULONG    Signature;   =  0x654c6648
         ULONG    Flags;       = 0
         unsigned __int64 LastRecordRead; = 0
         ULONG    MajorVersion;  = 1
         ULONG    MinorVersion;  = 0
         void*    LogPublisher;  = {pointer to the MySource}
         ULONG    NameLength;    = 0x0000000b
         [size_is(NameLength)] WCHAR Name[] = "Application"
     } *IELF_HANDLE;
    

    As shown in the example, the application log is recorded in the Name field of the IELF_HANDLE, that is how the server maintains the association between the handle and a particular event log.

  2. The client application writes the events by using the ElfrReportEventW method. The client application specifies the context handle (LogHandle) obtained in the preceding step. The parameters to the ElfrReportEventW method are as follows.

            NTSTATUS = {to be filled in by server}
            ElfrReportEventW(
               [in] IELF_HANDLE LogHandle =
               {handle obtained from ElfrRegisterEventSourceW},
               [in] unsigned long Time =
               {number of seconds since Jan 1, 1970},
               [in] unsigned short EventType = 0x0004,
               [in] unsigned short EventCategory = 0x0001,
               [in] unsigned long EventID = 0x00000017,
               [in, range(0, 0x100)]
               unsigned short NumStrings = 0x0002,
               [in, range(0, 0x3FFFF)]
               unsigned long DataSize = 0x00000010,
               [in] PRPC_UNICODE_STRING
               ComputerName = {"Computer"},
               [in, unique] PRPC_SID UserSID = NULL,
               [in, size_is(NumStrings), unique]
               PRPC_UNICODE_STRING Strings[*] = {"First" "Second"},
               [in, size_is(DataSize), unique]
               unsigned char * Data = {some binary data whose length is 16 bytes},
               [in] unsigned short Flags = 0x0000,
               [in, out, unique] unsigned long * RecordNumber = NULL,
               [in, out, unique] unsigned long * TimeWritten = NULL
               );
      
    

    If the client specifies the UserSID parameter, it needs to generate a PSID data type first. The function ConvertStringSidToSid (as described in [MSDN-ConvertStringSidToSid]) can convert the string SID to the PSID. Assume the SID the client wants to pass is: S-X-X-X. The function ConvertStringSidToSid can be used to get the PSID type value and pass it in as the UserSID parameter.

    The server writes a record to the event log that is associated with the handle and returns success.

    The newly written event record looks like the following:

     +0x000 Length           : 0xa8
     +0x004 Reserved         : 0x654c664c
     +0x008 RecordNumber     : 0x00000100
     +0x00c TimeGenerated    : 0x4cb3bb01
     +0x010 TimeWritten      : 0x4cb3bb19
     +0x014 EventID          : 0x00000017
     +0x018 EventType        : 4
     +0x01a NumStrings       : 2
     +0x01c EventCategory    : 1
     +0x01e ReservedFlags    : 0
     +0x020 ClosingRecordNumber : 0
     +0x024 StringOffset     : 0x76
     +0x028 UserSidLength    : 0xc
     +0x02c UserSidOffset    : 0x6a
     +0x030 DataLength       : 0x10
     +0x034 DataOffset       : 0x90
    

    The following table shows how the source, computer name, SID, strings and binary data are packed together in the file.

    Data

    Description

    G.e.n.e.r.a.t.e.E.v.e.n.t.

    Source Name.

    C.O.M.P.U.T.E.R

    Computer Name.

    (00000100 00460000)

    User SID (including 4 bytes of padding).

    F.i.r.s.t.

    The first string.

    S.e.c.o.n.d

    The second string.

    (760b5486 423ebe9e ff64b096 01532b77)

    The binary data.

    The client application can continue invoking this method to write additional events.

  3. When the client application is finished writing events, it releases the handle by calling ElfrDeregisterEventSource with the following parameter.

                 NTSTATUS = {to be filled in by server}
                 ElfrDeregisterEventSource(
                   [in, out] IELF_HANDLE * LogHandle = 
                    {handle obtained from ElfrRegisterEventSourceW}
                 );
      
    

    The server removes its state for the handle and returns success.