3.11.4.1.9 EnableNotification (Opnum 15)
The EnableNotification method is received by the server in an RPC_REQUEST packet. In response, the server starts event notification for asynchronously receiving or peeking messages.
-
HRESULT EnableNotification( [in] IMSMQEvent3* Event, [in, optional] VARIANT* Cursor, [in, optional] VARIANT* ReceiveTimeout );
Event: A pointer to an IMSMQEvent3 interface. If Event is NULL, the server MUST return an error E_INVALIDARG (0x80070057).
Cursor: A VARIANT pointer to a signed integer that corresponds to one of the MQMSGCURSOR ( section 2.2.2.8) enumeration values.
-
If this parameter is not specified by the client, the server MUST use the default value MQMSG_FIRST (0x00000000).
ReceiveTimeout: A pointer to a VARIANT that contains a long value (VT_I4) that specifies the time, in milliseconds, that the server MUST NOT exceed while waiting for a new message to arrive.
-
If this parameter is not specified by the client, the server MUST use the default value INFINITE (0xFFFFFFFF).
Return Values: The method MUST return S_OK (0x00000000) on success or an implementation-specific error HRESULT on failure.
When processing this call, the server MUST follow these guidelines:
If the Cursor input parameter is not equal to MQMSG_FIRST, MQMSG_CURRENT, or MQMSG_NEXT:
Return E_INVALIDARG (0x80070057), and take no further action.
If the IsInitialized instance variable equals False:
Return an error OLE_E_BLANK (0x80040007), and take no further action.
If the IsClosed instance variable equals True:
Return an error MQ_ERROR_INVALID_HANDLE (0xC00E0007), and take no further action.
If the Event input parameter is NULL:
Return E_INVALIDARG (0x80070057), and take no further action.
If refQueue.AccessType is not equal to PeekAccess or PeekAdminAccess:
Return an error MQ_ERROR_ACCESS_DENIED (0xC00E0025), and take no further action.
If the Cursor input parameter equals MQMSG_NEXT:
Advance the cursor represented by the Cursor instance variable.
Return S_OK (0x00000000), and take no further action.
Asynchronously:
If the Cursor input parameter equals MQMSG_NEXT or MQMSG_CURRENT:
Define suitable message as a Message, identified by the cursor represented by the Cursor instance variable, in the MessagePositionList of the referenced queue for which the MessagePosition.State attribute does not equal Locked or Message.AllowPeekWhenLocked equals True.
Starting from the Message identified by the cursor represented by the Cursor instance variable, continually advance the cursor, seeking a suitable message. If the cursor reaches EndQueue state, wait for more messages to arrive. The cursor is advanced seeking a suitable message by doing the following:
While a suitable message is not found:
The Peek Next Message event MUST be generated with the following arguments:
iQueueDesc: MUST be set to a reference to the OpenQueueDescriptor object that specifies the referenced queue.
iTimeout: MUST be set to ReceiveTimeout.
iCursor: MUST be set to a reference to the Cursor instance variable.
If the returned rStatus is not MQ_OK:
If the returned rStatus is MQ_ERROR_ILLEGAL_CURSOR_ACTION, and the ReceiveTimeout input parameter equals 0:
Fire the ArrivedError (section 3.16.4.4.2) event on the MSMQEvent object that is identified by the Event input parameter. Specify the ErrorCode parameter as MQ_ERROR_MESSAGE_NOT_FOUND (0xc00e0008), and take no further action.
If the returned rStatus is MQ_ERROR_IO_TIMEOUT, and the ReceiveTimeout input parameter is greater than 0 and does not equal INFINITE, and the time-out identified by the ReceiveTimeout input parameter expires:
Fire the ArrivedError event on the MSMQEvent object identified by the Event input parameter. Specify the ErrorCode parameter as MQ_ERROR_IO_TIMEOUT (0xc00e001b), and take no further action.
Else, if the returned rStatus is MQ_OK:
If the Message returned in rMessage is a suitable message:
Fire the Arrived (section 3.16.4.4.1) event on the MSMQEvent object identified by the Event input parameter, and take no further action.
If iCursor.MessagePositionReference is equivalent to iQueue.MessagePositionList.End:
The Wait for New Message event MUST be raised with the following arguments:
iQueueDesc: Reference to an OpenQueueDescriptor that specifies the queue that this event will wait on.
iTimeout: The amount of time to wait in seconds.
iDestructiveRead: This value MUST be set to False.
iCursor: Reference to a Cursor object that is associated with this wait request.
If the returned rStatus equals Success:
Set iCursor.MessagePositionReference to the returned rMessagePosition.
Else:
Define suitable message as the Message at the head of the MessagePositionList of the referenced queue for which the MessagePosition.State attribute does not equal Locked or Message.AllowPeekWhenLocked equals True.
Attempt to retrieve the suitable message.
If no suitable message can be located:
If the ReceiveTimeout input parameter is 0:
Fire the ArrivedError event on the MSMQEvent object identified by the Event input parameter. Specify the ErrorCode parameter as MQ_ERROR_MESSAGE_NOT_FOUND (0xc00e0008), and take no further action.
If the ReceiveTimeout input parameter is INFINITE (0xFFFFFFFF):
Wait until a suitable message is available.
Fire the Arrived event on the MSMQEvent object identified by the Event input parameter, and take no further action.
If the ReceiveTimeout input parameter is neither 0 nor INFINITE (0xFFFFFFFF):
Wait until either of the following events occurs:
The time-out specified by the ReceiveTimeout input parameters expires:
Fire the ArrivedError event on the MSMQEvent object that is identified by the Event input parameter. Specify the ErrorCode parameter as MQ_ERROR_IO_TIMEOUT (0xc00e001b), and take no further action.
A suitable message becomes available:
Fire the Arrived event on the MSMQEvent object identified by the Event input parameter, and take no further action.
Else, if one or more suitable messages are available:
Fire the Arrived event on the MSMQEvent object identified by the Event input parameter, and take no further action.