4.6 Push Subscription Example

In this example, the client asks to get all future events from the "Application" and "Microsoft-Windows-Backup/Operational" channel through push mode. This involves the following steps:

  1. The client registers with RPC to obtain an RPC binding handle to the service based on the endpoint information specified in section 2.1. For information on how to get the RPC binding handle, see [MSDN-BNDHNDLS].

  2. The client calls the EvtRpcRegisterRemoteSubscription method (section 3.1.4.8) to establish a subscription connection and to obtain a subscription context and operation control handles.

     error_status_t EvtRpcRegisterRemoteSubscription(
       [in] RPC_BINDING_HANDLE binding = {binding handle from step 1.},
       [in, unique, range(0, MAX_RPC_CHANNEL_NAME_LENGTH), string] LPCWSTR channelPath = NULL,
       [in, range(1, MAX_RPC_QUERY_LENGTH), string] 
         LPCWSTR query = {pointer to a structure query which describes the two channels.},
       [in, unique, range(0, MAX_RPC_BOOKMARK_NG,] LPCWSTR bookmarkXml = NULL,
       [in] DWORD flags = 0x00000001,
       [out, context_handle] PCONTEXT_HANDLE_REMOTE_SUBSCRIPTION* handle,
       [out, context_handle] PCONTEXT_HANDLE_OPERATION_CONTROL* control,
       [out] DWORD* queryChannelInfoSize,
       [out, size_is(, *queryChannelInfoSize), range(0, MAX_RPC_QUERY_CHANNEL_SIZE)] 
         EvtRpcQueryChannelInfo** queryChannelInfo,
       [out] RpcInfo*error
     );
      
    

    The structure query content for parameter query in this example would be as follows:

     <?xml version="1.0" encoding="UTF-8"?>
     <QueryList>
     <Query Id="1" Path="Application">
     <Select Path="Application">*</Select>
     </Query>
     <Query Id="2" Path="Microsoft-Windows-Backup/Operational">
     <Select Path="Microsoft-Windows-Backup/Operational">*</Select>
     </Query>
     </QueryList>
      
    
  3. The server handles the registration request from the client and the server creates a subscription object and a control object and casts them to remote subscription context handle and operation control context handle. As described in section 3.1.4.8, the subscription object contains the list of client subscribed channels. In this example, the subscription object contains "Application" and "Microsoft-Windows-Backup/Operational". Because these two channels are registered with the server already, the server finds and opens both of them to read how many events there are for each channel. Suppose the Application channel contains 200 existing events and the other one contains 100 existing events. The subscription object then has two longlong type of numeric cursor values for each channel, one is 201 and the other is 101. Because the client asks to get the future events, the subscription object sets the two cursors to the end of the channel to indicate that only future events will be delivered to the client. Then the subscription object sees that the flag does not specify the pull mode, and it sets the push mode flag to be true. For information on the operation control handle value, see section 4.1.

    After the server has completed these steps, it passes the subscription handle and control handle to the client.

  4. Once the client gets the subscription handle, it calls the EvtRpcRemoteSubscriptionNextAsync method (section 3.1.4.9) to fetch its subscribed events in the asynchronized way.

     error_status_t EvtRpcRemoteSubscriptionNextAsync(
       [in, context_handle] PCONTEXT_HANDLE_REMOTE_SUBSCRIPTION handle = {handle from step 2},
       [in] DWORD numRequestedRecords = 5,
       [in] DWORD flags = 0,
       [out] DWORD* numActualRecords,
       [out, size_is(,*numActualRecords), range(0, MAX_RPC_RECORD_COUNT)] 
         DWORD** eventDataIndices,
       [out, size_is(,*numActualRecords), range(0, MAX_RPC_RECORD_COUNT)] 
         DWORD** eventDataSizes,
       [out] DWORD* resultBufferSize,
       [out, size_is(, *resultBufferSize), range(0, MAX_RPC_BATCH_SIZE)] 
         BYTE** resultBuffer
     );
      
    
  5. On the server, it first checks if there are any new events in either of the channels. If there are no new events, the server returns the call immediately but does not complete the call. In this way the client does not need to wait when there are no new events coming into either of the channels. But the server keeps monitoring the channel. The server implements that by either checking the latest event in the channel periodically or registering a callback function from a system component that accepts the events from a provider. Note that for applicable Windows Server releases, the server registers its callback to the system component so that it can receive notification when a provider generates events. Later, if a provider generates a new event into the Application channel, with that information the server fills the event data in the resultBuffer and notifies the client that the events are coming now.

  6. The client then gets notified by RPC that the result is ready in its supplies buffer, as described in step 4. The client can then access the event data in its buffer. For more information on how the client interprets the data in the result buffer, see section 4.1.

This example shows the benefits of the push subscription. The client is not blocked by the server if there are no events that match the criteria of the client's subscriber requirement. Instead, the client can perform its own tasks while the server is waiting for the new events, and get notified when the server has new events ready.