BUG: OnRead() Event Calls In Wrong Context When Opening Report Messages (225009)



The information in this article applies to:

  • Microsoft Outlook 97
  • Microsoft Outlook 98

This article was previously published under Q225009

SYMPTOMS

When your Microsoft Outlook extension is registered for the context "EECONTEXT_READNOTEMESSAGE", your extension is called when opening Report messages.

CAUSE

When Outlook opens a Report message for the first time, it also opens the original Note message internally to update it's tracking information. When this internal opening happens, it causes the OnRead() event to occur on it.

For example, lets say you have an extension registered for EECONTEXT_READNOTEMESSAGE and EECONTEXT_READREPORTMESSAGE. When you open a read receipt (Report message) for the first time, you will see the extension get called twice. First, it will get called for the report message(REPORT.IPM.Note.IPNRN), and immediately following this, it will get called for the original Note message(IPM.Note).

Note that after the tracking info has been updated from the first opening of the message, subsequent openings of the read receipt will not result in our IPM.Note being opened.

RESOLUTION

Typically, developers will not want the READ_NOTEMESSAGE extensions to be called when the user opens a report. To detect when your OnRead() is being called from within the OnRead() of a Report message, do the following:
  1. Register your extension to include EECONTEXT_READREPORTMESSAGE in addition to any other contexts you want.
  2. In your OnRead() code, add some logic to detect if the message being opened is of message class "REPORT.IPM.Note.IPNRN".
  3. If the message is a "REPORT>IPM.Note.IPNRN", you'll need to check if the property PR_PROCESSED has been set. This flag is set by Outlook the first time it opens a Report message. You will use it to determine if this is the first time the report has been opened. PR_PROCESSED is defined as:
             #define PR_PROCESSED	PROP_TAG( PT_BOOLEAN, 0x7D01) 
    					
  4. If PR_PROCESSED is not set or equals FALSE, you know it needs to ignore the next call to OnRead() as it will be the internal call from Outlook opening the original message.
#define PR_PROCESSED	PROP_TAG( PT_BOOLEAN, 0x7D01)

STDMETHODIMP CExchExtMessageEvents::OnRead( LPEXCHEXTCALLBACK lpeecb )
{
   LPMESSAGE 	pMessage=NULL;
   LPMAPIPROP 	pPropObj=NULL;
   LPSPropValue	lpspvMsgClass = NULL;
   LPSPropValue	lpspvProcessed = NULL;
   HRESULT	hr = S_OK;
   char		sOut[256];

   if(lpeecb->GetObject(NULL,&pPropObj)!=S_OK)
	goto ret;

   if(pPropObj->QueryInterface(IID_IMessage,(LPVOID *)&pMessage)!=S_OK)
	goto ret;

   hr = HrGetOneProp(pMessage, PR_MESSAGE_CLASS, &lpspvMsgClass);
   sprintf(sOut, "Message Class = %s", lpspvMsgClass->Value.lpszA);
   ::MessageBox( NULL, sOut, "Message Class", MB_OK );

   // Is this a report?
   if(0 == strcmp("REPORT.IPM.Note.IPNRN", lpspvMsgClass->Value.lpszA))
   {
	// Has this report been processed before?
	hr = HrGetOneProp(pMessage, PR_PROCESSED, &lpspvProcessed);
	if(MAPI_E_NOT_FOUND == hr || !lpspvProcessed->Value.b)
	{
 	     ::MessageBox( NULL, "This msg has NOT been Processed\n Ignore the next call to OnRead!", "Process State", MB_OK );
	}
	else
	{
	     ::MessageBox( NULL, "This Msg has already been Processed", "Process State", MB_OK );
	}
   }

ret:
    if(pMessage) pMessage->Release();
    if(pPropObj) pPropObj->Release();
    if (lpspvMsgClass) MAPIFreeBuffer(lpspvMsgClass);
    if (lpspvProcessed) MAPIFreeBuffer(lpspvProcessed);

    return S_FALSE;

}
Note that if you want to be called when opening Report messages, you should register for the context "EECONTEXT_READREPORTMESSAGE")

STATUS

Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

Modification Type:MinorLast Reviewed:3/4/2004
Keywords:kbbug kbMsg kbpending KB225009