DoomBringer

Bear with me, this might take a while to explain.  Basically, I've written a menu extension for Pocket Outlook, using the example InboxMenuExtensibility that ships with both the smartphone and pocketpc SDKs.  (\Samples\CPP\Win32\Inboxmenuextensibility)  Essentially, I've followed the form of that sample but changed from a Inbox view menu extension to a Compose view extension.  That is, I've basically changed the extension key from "List_View" to "Compose_IPM.Note".  So, the menu entry is now in the email compose screen.

I've implemented all the necessary COM interfaces and class factories that I need for this thing, and yes, I've generated my own GUID (the sample was quite vociferous on that point, for good reason).

Basically, in my InvokeCommand function, I try to look up the contents pointed at by the pointer set by the IObjectWithSite interface (the application site pointer, whatever you want to call it).  According to MSDN documentation ("Menu Overview" is the topic), the ItemRefArray should first have a pointer to a IMessageFormEx, and a IMessage.  I retrieve the IMessageFormEx successfully, and I can do whatever I want on it.  If I try any operation on the IMessage object, an exception is thrown, and it looks like the pointer value there is completely invalid (it points to an arbitrary memory address that doesn't look like a real pointer).

Now, I've double checked my functions that retrieve the ItemRefArray and extract things from it, and like I said, I can perform any operation on the IMessageFormEx.  This tells me that I'm at least getting the references out of the array correctly.  The IMessage is what I really would like to have though, and it always, without fail, throws an exception.

HRESULT CSigShell::GetMessageFromItemArray(ItemRefArray *pItemArray, IMessage **pMessage)
{
	HRESULT hr = S_OK;
	int ixRefs = 0;
	ItemRef* pItem = NULL;
	if(pItemArray != NULL)
	{
		if(pItemArray->cRefs == 0) // pItemArray should have something in it
		{
			hr = E_FAIL;
		}
		else
		{
			if(*pMessage)
			{ // the caller shouldn't invoke us with a pointer to a non-NULL pointer, but check anyhow
				(*pMessage)->Release();
				*pMessage = NULL;
			}
			while(ixRefscRefs)
			{
				pItem = &pItemArray->rgRefs[ixRefs];
				if( IsEqualGUID(*(pItem->pType), ITI_MessageItemRef))
				{
					*pMessage = (IMessage*)(pItem->pRef);
					break;
				}
				ixRefs++;
			}
			if(*pMessage == NULL)
			{
				hr = E_NOINTERFACE;
			}
		}
	}
	else
	{
		hr = E_POINTER;
	}
	return hr;
}
Above is my function for getting the IMessage from the ItemRefArray. Getting a IMessageFormEx works by changing the pointers and ITI constant. I'm a little crazy with the error checking with the NULL thing, but I know this basic formula works because I can get IMessageFormEx in the same fashion.
 
I don't see what is causing the exception to be thrown. I've tried using MAPILogonEx or not, but I was under the impression that I would inherit it from my host, that is, PocketOutllook.
I can post some more code, but please be specific what you want to see.


Re: Smart Devices Native C++ Development Odd exception when operating on retrieved IMessage object as a menu extension

tdinneen

Hey do you ever solve this. I'm having exactly the same problem.

T.




Re: Smart Devices Native C++ Development Odd exception when operating on retrieved IMessage object as a menu extension

AlexFeinman

The ItemArray->rgRefs[ i ] cannot be cast direclty to IMessage*. It is a pointer to SBINARY. See this snippet from ReadViewMenuExt SDK sample:

Code Snippet

// Get the 1st item and verify that it is a Message item
pRefMsg = &pItemArray->rgRefs[0];

// Get the Entry Size - cbEntryID from the ItemRef
cbEntry = ((SBinary *)pRefMsg->pRef)->cb;

// Get the pointer to the EntryID from the ItemRef
pEntryID = (ENTRYID *) ((SBinary *)pRefMsg->pRef)->lpb;

// Open the Message
// Note if you have a Message's Entry ID you can go straight to it
// no need to open the folder first
hr = m_pSession->OpenEntry(cbEntry, pEntryID, NULL, 0, NULL, (LPUNKNOWN *)&pMsg);






Re: Smart Devices Native C++ Development Odd exception when operating on retrieved IMessage object as a menu extension

DoomBringer

I thought I tried that, but I will use this approach. Since I first wrote the above post, I've written a hack to screenscrape stuff out of the fields and drive the UI via simulated key presses. Hardly elegant but it got me working.



Re: Smart Devices Native C++ Development Odd exception when operating on retrieved IMessage object as a menu extension

DoomBringer

Sorry that it took me a while to get into this, but the ENTRYID for a newly composed message is invalid (blank), because newly composed messages don't have one until they are saved. Therefore, one should save the message to the drafts folder first, or do like I did, and drive the UI as necessary.

I'm not sure 100% if I'll adopt this new approach. For now, the thing has shipped, so no big deal.