Friday, August 29, 2008

What does DTM_BROWSERDISPATCH gives you?

Well,as some documentations state it gives you IBrowser,IBrowser2,IBrowser3 interfaces.
Remember they are different from IWebBrowser and IWebBrowser2 interfaces.
But where are the definitions of these interfaces?
Well actually from win ce 4.2,there are no such interfaces found in your SDK.So you have to use older SDKs found in for example PocketPC 2000/2002,and copy/paste them into your header file.
Unfortunately Microsoft also uses another interface to negotiate with HTML Document viewer,which there is no documentation for it.Interace GUID is {698e3fcb-70c3-11d0-81e8-00a0c90ad20a} but so far i haven't find any documentation for it.

But why do i need all these?
The problem is with Images.With use of DTM_SETIMAGE you can only give HTML Viewer a handle to your bitmap.The problem is i want to display it as transparent bitmap and so far i haven't find any way.
And tracing DTM_SETIMAGE,it gives these information to that undocumented interface.So i still don't know how can i use HTML Viewer with transparent images.

Wednesday, August 20, 2008

Why there is no information on....?

Why there is no information anywhere on BI_FOURCC ?
Why there is no information anywhere on BI_ALPHABITS ?
Why there is no information on 32 bit Bitmaps?
Why there is no information anywhere on How to embed OLE Browser on your application?
Why there is no information on How to use Memory bitmaps inside your OLE Browser?
Why there is no information on RIL interfaces?
Why there is no information on How to send SMS using RIL?
And why Windows Mobile development requires this much of undocumented information?
And Why Microsoft's own applications completely use different set of unnamed/undocumented APIs?

Well,actually i am really angry,but hey,i managed to find some information on some of questions above.
Hope i can share them with you.

Thursday, August 7, 2008

PocketPC Threaded Messaging (SMS) for everyone!

Microsoft added threaded messaging in WM6.1 but there is no way to use threaded messaging on earlier versions of windows mobile like wm5 and wm6.

But things have changed now!

SmileySMS can bring threaded messaging to wm5,wm6 devices and also to wm6.1 devices with support for smileys!

Here is the nice and sexy screenshot of newer versions of SmileySMS.

How do you know SMS belong to which folder in MAPI?

Well,somethimes you might want to know that this SMS is in which folder,for example in Drafts folder,in Inbox folder or...?
A quick not is that never rely on results from PR_DISPLAY_NAME because names like "Inbox","Drafts Folder" can be localized.
Here is the code snippet i use.
You have to use it like this.

if (isFolderTypeSame(pSession,pFolder,PR_CE_IPM_INBOX_ENTRYID))

You can use these values for third parameter.

bool isFolderTypeSame(IMAPISession *m_pSession,LPMAPIFOLDER pFolder,ULONG _PR_FOLDERTYPE)
CComPtr<IMsgStore> pms ;
ULONG cItems;
SizedSPropTagArray(2, rgtagsFldr) = {2 , PR_OWN_STORE_ENTRYID,PR_ENTRYID};
ULONG entryid[] = { 1, _PR_FOLDERTYPE };
LPSPropValue fldrprops=NULL,msgstoreprops = NULL;
ULONG result=0;

// This method assumes that the CALLER already logged on to a MAPISession
if (!m_pSession)

// Now request the PR_OWN_STORE_ENTRYID on the folder. This is the
// ENTRYID of the message store that owns the folder object.
hr = pFolder->GetProps((SPropTagArray *) &rgtagsFldr, MAPI_UNICODE, &cItems, &fldrprops);

// Now open the message store object.
hr = m_pSession->OpenEntry(fldrprops[0].Value.bin.cb,(LPENTRYID)fldrprops[0].Value.bin.lpb,NULL,
0, NULL, (LPUNKNOWN*)&pms);

// Get the ENTRYID of the wastebasket for the message store
hr = pms->GetProps((LPSPropTagArray)entryid, MAPI_UNICODE, &cItems, &msgstoreprops);


return result;

How to create and send SMS using MAPI?

Here is a code snippet i use to create and send my SMS in SmileySMS program.
From my experience,using fewer properties for ModifyRecipients or SetProps will make it fail on some devices.

IMsgStore *FindInboxSMSStore(IMAPISession *pSession)
const SizedSPropTagArray (2, spta) = { 2, PR_DISPLAY_NAME, PR_ENTRYID };
SRowSet *prowset = NULL;
CComPtr<IMAPITable> ptbl;
CComPtr<IMsgStore> pStore;

// Get the table of accounts
hr = pSession->GetMsgStoresTable(0, &ptbl);
// set the columns of the table we will query
hr = ptbl->SetColumns((SPropTagArray *) &spta, 0);

while (TRUE)
hr = ptbl->QueryRows (1, 0, &prowset);
if ((hr != S_OK) || (prowset == NULL) || (prowset->cRows == 0))

ASSERT (prowset->aRow[0].cValues == spta.cValues);
SPropValue *pval = prowset->aRow[0].lpProps;

ASSERT (pval[0].ulPropTag == PR_DISPLAY_NAME);
ASSERT (pval[1].ulPropTag == PR_ENTRYID);

if (!_tcscmp(pval[0].Value.lpszW, TEXT("SMS")))
// Get the Message Store pointer
hr = pSession->OpenMsgStore(0, pval[1].Value.bin.cb, (LPENTRYID)pval[1].Value.bin.lpb, 0, 0, &pStore);
FreeProws (prowset);

return pStore;
// Free the previous row
FreeProws (prowset);
prowset = NULL;
FreeProws (prowset);
return NULL;

HRESULT CreateSendSMSMessage(IMAPISession *spSession,LPCTSTR lpszToNumber, LPCTSTR lpszToDisplay,LPCTSTR lpszMessage,IMessage** pMsg)
CComPtr<IMsgStore> spMsgStore;
ULONG cItems;
ULONG rgtagsMsgStore[] = { 1, PR_CE_IPM_DRAFTS_ENTRYID };
LPSPropValue rgprops;

spMsgStore = FindInboxSMSStore(spSession);
if (spMsgStore == NULL)
return S_FALSE;

CComPtr<IMAPIFolder> spFolder;

hr = spMsgStore->GetProps((LPSPropTagArray)rgtagsMsgStore, MAPI_UNICODE, &cItems, &rgprops);
if (FAILED(hr))
return hr;

hr = spSession->OpenEntry(rgprops[0].Value.bin.cb,(LPENTRYID)rgprops[0].Value.bin.lpb,
NULL, 0, NULL, (LPUNKNOWN*)&spFolder);
if (FAILED(hr))
return hr;


hr = spFolder->CreateMessage(NULL, 0 ,&(*pMsg));
if (FAILED(hr))
return hr;

int cb;
LPSRowSet pRowSet = NULL;
LPSPropValue pVal = NULL;

// * 5 because there are 5 props
cb = sizeof(SRowSet) + sizeof(SPropValue) * 5; // SRowSet includes one SRow.

// Now allocate a buffer.
CPR((pb = new BYTE[cb]))

// Copy the properties over.
pRowSet = (LPSRowSet)pb;
pVal = (LPSPropValue)(pb + ( sizeof(SRowSet) + sizeof(SRow) ));

// initialize
pRowSet->aRow[0].cValues = 0;
pRowSet->aRow[0].lpProps = pVal;

// begin filling the values
pVal->ulPropTag = PR_RECIPIENT_TYPE;
pVal->Value.ul = MAPI_TO;

pVal->ulPropTag = PR_EMAIL_ADDRESS;
pVal->Value.lpszW = (LPWSTR)lpszToNumber;

pVal->ulPropTag = PR_DISPLAY_NAME;
pVal->Value.lpszW = (LPWSTR)lpszToDisplay;

pVal->ulPropTag = PR_ADDRTYPE;
pVal->Value.lpszW = L"SMS";

pVal->ulPropTag = PR_MESSAGE_CLASS;
pVal->Value.lpszW = (LPTSTR)L"IPM.SMStext";

pRowSet->cRows = 1;

hr = (*pMsg)->ModifyRecipients(MODRECIP_ADD, (LPADRLIST)pRowSet);

// now we set the additional properties for the
// message
SPropValue props[6];

ZeroMemory(&props, sizeof(props));

// first set the subject of the message
// as the sms we are going to send
props[0].ulPropTag = PR_SUBJECT;
props[0].Value.lpszW = (LPWSTR)lpszMessage;

props[1].ulPropTag = PR_MSG_STATUS;
props[1].Value.ul = MSGSTATUS_RECTYPE_SMS;

props[2].ulPropTag = PR_SENDER_ADDRTYPE;
props[2].Value.lpszW = L"SMS";

props[3].ulPropTag = PR_MESSAGE_CLASS;
props[3].Value.lpszW = L"IPM.SMStext";

props[4].ulPropTag = PR_MESSAGE_FLAGS;

props[5].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
props[5].Value.lpszW = (LPWSTR)lpszToNumber;

hr = (*pMsg)->SetProps(sizeof(props) / sizeof(props[0]), (LPSPropValue)&props, NULL);
if (FAILED(hr))
return hr;

// having set all the required fields we can now
// pass the message over to the msgstore transport
// to be delivered.
//hr = (*pMsg)->SubmitMessage(0);
//if (FAILED(hr))
//return hr;
delete [] pb;
return FALSE;