- It is currently Tue May 21, 2013 4:37 pm • All times are UTC + 2 hours
Send SMS
Moderator: Teksoft
7 posts
• Page 1 of 1
There are two ways of doing this :
using SMS api as in the sample provided in the SDK (\Samples\Win32\Cellcore\Sms\HelloSMS)
or you can do something like this ( i used it on 2005 devices with some "problematic RUUs" on wich standard SMS API just didn't work)
#include "stdafx.h"
#include <cemapi.h>
#include <mapiutil.h>
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the msgstore named SMS from msgstores on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSMsgStore(const CComPtr<IMAPISession>& spSession, CComPtr<IMsgStore>& spMsgStore)
{
// first we get the msgstores table from the session
CComPtr<IMAPITable> spTable;
HRESULT hr = spSession->GetMsgStoresTable(MAPI_UNICODE, &spTable);
if (FAILED(hr))
{
return FALSE;
}
// next we loop over the message stores opening each msgstore and
// getting its name to see if the name matches SMS.
// If it does then we break out of the loop
while (TRUE)
{
SRowSet* pRowSet = NULL;
hr = spTable->QueryRows(1, 0, &pRowSet);
// If we failed to query the
// rows then we need to break
if (FAILED(hr))
{
break;
}
// if we got no rows back then just exit the loop
//remembering to set an error
if (pRowSet->cRows == 1)
{
ASSERT(pRowSet->aRow[0].lpProps->ulPropTag == PR_ENTRYID);
SBinary& blob = pRowSet->aRow[0].lpProps->Value.bin;
hr = spSession->OpenMsgStore(NULL, blob.cb, (LPENTRYID)blob.lpb, NULL, 0, &spMsgStore);
if (FAILED(hr))
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
// now remember to free the row set
FreeProws(pRowSet);
if (FAILED(hr))
{
break;
}
// now get the display name property from the
// message store to compare it against the name
// 'SMS'
SPropTagArray props;
props.cValues = 1;
props.aulPropTag[0] = PR_DISPLAY_NAME;
ULONG cValues;
SPropValue* pProps = NULL;
hr = spMsgStore->GetProps(&props, MAPI_UNICODE, &cValues, &pProps);
if (FAILED(hr) || cValues != 1)
{
break;
}
// if the name matches SMS then break and as
// hr == S_OK the current MsgStore smart pointer
// will correctly be set.
if (_tcsicmp(pProps[0].Value.lpszW, _T("SMS")) == 0)
{
break;
}
}
// if we failed for some reason then we clear out
// the msgstore smartpointer and return the error.
if (FAILED(hr))
{
spMsgStore.Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the folder named drafts from the msgstore on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSFolder(const CComPtr<IMsgStore>& spMsgStore, CComPtr<IMAPIFolder>& spFolder)
{
// Now get the Drafts folder.
SPropTagArray propDefaultFolder;
propDefaultFolder.cValues = 1;
propDefaultFolder.aulPropTag[0] = PR_CE_IPM_DRAFTS_ENTRYID;
ULONG cValues;
LPSPropValue pPropVals;
HRESULT hr = spMsgStore->GetProps (&propDefaultFolder, MAPI_UNICODE, &cValues, &pPropVals);
if (FAILED(hr))
{
return hr;
}
SBinary& eidDrafts = pPropVals->Value.bin;
hr = spMsgStore->OpenEntry(eidDrafts.cb, (LPENTRYID)eidDrafts.lpb, NULL, MAPI_MODIFY, NULL, (LPUNKNOWN*)&spFolder);
if (FAILED(hr))
{
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the send the message.
// This uses an opened MAPI session
HRESULT SendSMSMessage(const CComPtr<IMAPISession>& spSession, LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{
// now get the SMS message store
CComPtr<IMsgStore> spMsgStore;
HRESULT hr = GetSMSMsgStore(spSession, spMsgStore);
if (FAILED(hr))
{
return hr;
}
CComPtr<IMAPIFolder> spFolder;
hr = GetSMSFolder(spMsgStore, spFolder);
if (FAILED(hr))
{
return hr;
}
CComPtr<IMessage> spMessage;
hr = spFolder->CreateMessage(NULL, 0 ,&spMessage);
if (FAILED(hr))
{
return hr;
}
// set the recipients
// set up the required fields for a recipient
SPropValue propRecipient[3];
// it is vital we clear the property structure
// as there are fields we do not use but MAPI seems
// to be sentative to them.
ZeroMemory(&propRecipient, sizeof(propRecipient));
// set the recipient type which coul be to, cc, bcc
// but ehre must at least be a to field
propRecipient[0].ulPropTag = PR_RECIPIENT_TYPE;
propRecipient[0].Value.l = MAPI_TO;
// we set the type of address to sms instead of
// smtp
propRecipient[1].ulPropTag = PR_ADDRTYPE;
propRecipient[1].Value.lpszW = _T("SMS");
// we finally set the email address to the
// phone number of the person we are sending the message
// to
propRecipient[2].ulPropTag = PR_EMAIL_ADDRESS;
propRecipient[2].Value.lpszW = (LPWSTR)lpszTo;
// set the addrlist to point to the properties
ADRLIST adrlist;
adrlist.cEntries = 1;
adrlist.aEntries[0].cValues = 3;
adrlist.aEntries[0].rgPropVals = (LPSPropValue)(&propRecipient);
// finally modify the recipients of the message
hr = spMessage->ModifyRecipients(MODRECIP_ADD, &adrlist);
if (FAILED(hr))
{
return hr;
}
else
; // added the recipient to the message
// now we set the additional properties for the
// message
SPropValue props[4];
//note how we zero out the contents of the
// structure as MAPI is sensative to the
// contents of other fields we do not use.
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;
// next set the senders email address to
// the phone number of the person we are
// sending the message to
props[1].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
props[1].Value.lpszW = (LPWSTR)lpszFrom;
// finally and most importantly tell mapi
// this is a sms message in need of delivery
props[2].ulPropTag = PR_MSG_STATUS;
props[2].Value.ul = MSGSTATUS_RECTYPE_SMS;
props[3].ulPropTag = PR_MESSAGE_FLAGS;
props[3].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT;
hr = spMessage->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 = spMessage->SubmitMessage(0);
if (FAILED(hr))
{
return hr;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////
// This is the function that creates the session, using the
// from, the recipient and the message.
// This opens the session, opens the sms message store and opens
// the drafts folder then create a new message and sets the sender,
// recipient and messag, then finally sends the message.
BOOL DoSendMessage(LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{
HRESULT hr = MAPIInitialize(NULL);
if (FAILED(hr))
{
return hr;
}
else
; // initialized the MAPI subsystem
CComPtr<IMAPISession> spSession;
BOOL bRet = FALSE;
hr = MAPILogonEx(0 ,NULL, NULL, 0, &spSession);
if (FAILED(hr))
{
}
else
{
bRet = SUCCEEDED(SendSMSMessage(spSession, lpszFrom, lpszTo, lpszMessage));
spSession->Logoff(0, 0, 0);
spSession.Release();
}
MAPIUninitialize();
return bRet;
}
You can call it like this
DoSendMessage(m_strFrom, m_strTo, m_strMessage);
DoSendMessage(_T("SMS"), _T("0742010027"), _T("We are here to answer your questions"));
using SMS api as in the sample provided in the SDK (\Samples\Win32\Cellcore\Sms\HelloSMS)
or you can do something like this ( i used it on 2005 devices with some "problematic RUUs" on wich standard SMS API just didn't work)
#include "stdafx.h"
#include <cemapi.h>
#include <mapiutil.h>
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the msgstore named SMS from msgstores on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSMsgStore(const CComPtr<IMAPISession>& spSession, CComPtr<IMsgStore>& spMsgStore)
{
// first we get the msgstores table from the session
CComPtr<IMAPITable> spTable;
HRESULT hr = spSession->GetMsgStoresTable(MAPI_UNICODE, &spTable);
if (FAILED(hr))
{
return FALSE;
}
// next we loop over the message stores opening each msgstore and
// getting its name to see if the name matches SMS.
// If it does then we break out of the loop
while (TRUE)
{
SRowSet* pRowSet = NULL;
hr = spTable->QueryRows(1, 0, &pRowSet);
// If we failed to query the
// rows then we need to break
if (FAILED(hr))
{
break;
}
// if we got no rows back then just exit the loop
//remembering to set an error
if (pRowSet->cRows == 1)
{
ASSERT(pRowSet->aRow[0].lpProps->ulPropTag == PR_ENTRYID);
SBinary& blob = pRowSet->aRow[0].lpProps->Value.bin;
hr = spSession->OpenMsgStore(NULL, blob.cb, (LPENTRYID)blob.lpb, NULL, 0, &spMsgStore);
if (FAILED(hr))
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
}
// now remember to free the row set
FreeProws(pRowSet);
if (FAILED(hr))
{
break;
}
// now get the display name property from the
// message store to compare it against the name
// 'SMS'
SPropTagArray props;
props.cValues = 1;
props.aulPropTag[0] = PR_DISPLAY_NAME;
ULONG cValues;
SPropValue* pProps = NULL;
hr = spMsgStore->GetProps(&props, MAPI_UNICODE, &cValues, &pProps);
if (FAILED(hr) || cValues != 1)
{
break;
}
// if the name matches SMS then break and as
// hr == S_OK the current MsgStore smart pointer
// will correctly be set.
if (_tcsicmp(pProps[0].Value.lpszW, _T("SMS")) == 0)
{
break;
}
}
// if we failed for some reason then we clear out
// the msgstore smartpointer and return the error.
if (FAILED(hr))
{
spMsgStore.Release();
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the folder named drafts from the msgstore on the
// device.
// I could have used just raw pointers but it is much easier and safer to just
// use smart pointers.
HRESULT GetSMSFolder(const CComPtr<IMsgStore>& spMsgStore, CComPtr<IMAPIFolder>& spFolder)
{
// Now get the Drafts folder.
SPropTagArray propDefaultFolder;
propDefaultFolder.cValues = 1;
propDefaultFolder.aulPropTag[0] = PR_CE_IPM_DRAFTS_ENTRYID;
ULONG cValues;
LPSPropValue pPropVals;
HRESULT hr = spMsgStore->GetProps (&propDefaultFolder, MAPI_UNICODE, &cValues, &pPropVals);
if (FAILED(hr))
{
return hr;
}
SBinary& eidDrafts = pPropVals->Value.bin;
hr = spMsgStore->OpenEntry(eidDrafts.cb, (LPENTRYID)eidDrafts.lpb, NULL, MAPI_MODIFY, NULL, (LPUNKNOWN*)&spFolder);
if (FAILED(hr))
{
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// This function is used to get the send the message.
// This uses an opened MAPI session
HRESULT SendSMSMessage(const CComPtr<IMAPISession>& spSession, LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{
// now get the SMS message store
CComPtr<IMsgStore> spMsgStore;
HRESULT hr = GetSMSMsgStore(spSession, spMsgStore);
if (FAILED(hr))
{
return hr;
}
CComPtr<IMAPIFolder> spFolder;
hr = GetSMSFolder(spMsgStore, spFolder);
if (FAILED(hr))
{
return hr;
}
CComPtr<IMessage> spMessage;
hr = spFolder->CreateMessage(NULL, 0 ,&spMessage);
if (FAILED(hr))
{
return hr;
}
// set the recipients
// set up the required fields for a recipient
SPropValue propRecipient[3];
// it is vital we clear the property structure
// as there are fields we do not use but MAPI seems
// to be sentative to them.
ZeroMemory(&propRecipient, sizeof(propRecipient));
// set the recipient type which coul be to, cc, bcc
// but ehre must at least be a to field
propRecipient[0].ulPropTag = PR_RECIPIENT_TYPE;
propRecipient[0].Value.l = MAPI_TO;
// we set the type of address to sms instead of
// smtp
propRecipient[1].ulPropTag = PR_ADDRTYPE;
propRecipient[1].Value.lpszW = _T("SMS");
// we finally set the email address to the
// phone number of the person we are sending the message
// to
propRecipient[2].ulPropTag = PR_EMAIL_ADDRESS;
propRecipient[2].Value.lpszW = (LPWSTR)lpszTo;
// set the addrlist to point to the properties
ADRLIST adrlist;
adrlist.cEntries = 1;
adrlist.aEntries[0].cValues = 3;
adrlist.aEntries[0].rgPropVals = (LPSPropValue)(&propRecipient);
// finally modify the recipients of the message
hr = spMessage->ModifyRecipients(MODRECIP_ADD, &adrlist);
if (FAILED(hr))
{
return hr;
}
else
; // added the recipient to the message
// now we set the additional properties for the
// message
SPropValue props[4];
//note how we zero out the contents of the
// structure as MAPI is sensative to the
// contents of other fields we do not use.
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;
// next set the senders email address to
// the phone number of the person we are
// sending the message to
props[1].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
props[1].Value.lpszW = (LPWSTR)lpszFrom;
// finally and most importantly tell mapi
// this is a sms message in need of delivery
props[2].ulPropTag = PR_MSG_STATUS;
props[2].Value.ul = MSGSTATUS_RECTYPE_SMS;
props[3].ulPropTag = PR_MESSAGE_FLAGS;
props[3].Value.ul = MSGFLAG_FROMME | MSGFLAG_UNSENT;
hr = spMessage->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 = spMessage->SubmitMessage(0);
if (FAILED(hr))
{
return hr;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////
// This is the function that creates the session, using the
// from, the recipient and the message.
// This opens the session, opens the sms message store and opens
// the drafts folder then create a new message and sets the sender,
// recipient and messag, then finally sends the message.
BOOL DoSendMessage(LPCTSTR lpszFrom, LPCTSTR lpszTo, LPCTSTR lpszMessage)
{
HRESULT hr = MAPIInitialize(NULL);
if (FAILED(hr))
{
return hr;
}
else
; // initialized the MAPI subsystem
CComPtr<IMAPISession> spSession;
BOOL bRet = FALSE;
hr = MAPILogonEx(0 ,NULL, NULL, 0, &spSession);
if (FAILED(hr))
{
}
else
{
bRet = SUCCEEDED(SendSMSMessage(spSession, lpszFrom, lpszTo, lpszMessage));
spSession->Logoff(0, 0, 0);
spSession.Release();
}
MAPIUninitialize();
return bRet;
}
You can call it like this
DoSendMessage(m_strFrom, m_strTo, m_strMessage);
DoSendMessage(_T("SMS"), _T("0742010027"), _T("We are here to answer your questions"));
- sad_ghost
- TEK-Giant

- Posts: 269
- Joined: Thu Apr 06, 2006 11:04 am
Hello,
Im a novice developer and know only VB.net
I downloaded a sample from msdn to send sms. They have writen a class named sms and using that as namespace, i use the code sms.sendmessage (number,message).Hope you would have seen the sample already. Now what i need is, this sends sms in class0. But i want them to be sent as class1 sms. Can you help me please,
Thanx a million in advance.
Regards
Carty..
Im a novice developer and know only VB.net
I downloaded a sample from msdn to send sms. They have writen a class named sms and using that as namespace, i use the code sms.sendmessage (number,message).Hope you would have seen the sample already. Now what i need is, this sends sms in class0. But i want them to be sent as class1 sms. Can you help me please,
Thanx a million in advance.
Regards
Carty..
Try to get the best out of you, that would be the key to Success - NiCK Carty..
- Carty
- TEK-Seeker
- Posts: 18
- Joined: Thu Jun 01, 2006 11:46 am
- Location: India
hello
Dear Carty,
As you are saying, if you are at the begining of your developer career, you are free to choose your tools.
For a beginner everything will be hard, both VB.net and VC++ so why not choosing VC++?
The idea is that as you have said, from time to time you need to modify a flag or a tiny aspect that the already-done classes that you are using cannot support, and then you are lost. But if you control everything (and you can do this from vc++), you are free to set everything as you like.
So I very warmly suggest to choose the vc++ path, at least for mobile devices is better (you wont have everything you need with VB.net, as almost everytime you will have to load third party .dll-s and so and that's not an option).
Back to your question:
Do you have the source code of that class?
// PS_MESSAGE_CLASS0 - flash msg, no storage
// PS_MESSAGE_CLASS1 - msg with storage
txtProviderData.psMessageClass = PS_MESSAGE_CLASS1;
txtProviderData.psReplaceOption = PSRO_NONE;
dwProviderLength = sizeof(TEXT_PROVIDER_SPECIFIC_DATA);
// Send the message
hr = SmsSendMessage(hSms, NULL, &smsDestination, NULL,
(BYTE *)tchMessage, dwMessageLength, (LPBYTE)&txtProviderData,
dwProviderLength, SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE,
&smsMsgId);
You need to look for the call to the SmsSendMessage, and for the 7th parameter (as above, txtProviderData) to change the .psMessageClass to PS_MESSAGE_CLASS0 so you can "flash" your sms.
Regards,
Radu
As you are saying, if you are at the begining of your developer career, you are free to choose your tools.
For a beginner everything will be hard, both VB.net and VC++ so why not choosing VC++?
The idea is that as you have said, from time to time you need to modify a flag or a tiny aspect that the already-done classes that you are using cannot support, and then you are lost. But if you control everything (and you can do this from vc++), you are free to set everything as you like.
So I very warmly suggest to choose the vc++ path, at least for mobile devices is better (you wont have everything you need with VB.net, as almost everytime you will have to load third party .dll-s and so and that's not an option).
Back to your question:
Do you have the source code of that class?
// PS_MESSAGE_CLASS0 - flash msg, no storage
// PS_MESSAGE_CLASS1 - msg with storage
txtProviderData.psMessageClass = PS_MESSAGE_CLASS1;
txtProviderData.psReplaceOption = PSRO_NONE;
dwProviderLength = sizeof(TEXT_PROVIDER_SPECIFIC_DATA);
// Send the message
hr = SmsSendMessage(hSms, NULL, &smsDestination, NULL,
(BYTE *)tchMessage, dwMessageLength, (LPBYTE)&txtProviderData,
dwProviderLength, SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE,
&smsMsgId);
You need to look for the call to the SmsSendMessage, and for the 7th parameter (as above, txtProviderData) to change the .psMessageClass to PS_MESSAGE_CLASS0 so you can "flash" your sms.
Regards,
Radu
- radhoo
- TEK-Insider

- Posts: 640
- Joined: Fri Mar 17, 2006 2:47 am
Thanx for the quick reply. This site gonna turn out a best one for pocket pc supports.
Well C# is ultimate but damn complicated i feel. VB.net is just too cool and easy i feel!
And, here is the sample im talking about.
Can you please download the VB.net version listed there. You can see a sms class used in it. It sends class0 sms but i want class1. Can you help me please.
I would much appreciate if you could edit it and send me
Thanx a million.
Regards
Carty..
Well C# is ultimate but damn complicated i feel. VB.net is just too cool and easy i feel!
And, here is the sample im talking about.
Can you please download the VB.net version listed there. You can see a sms class used in it. It sends class0 sms but i want class1. Can you help me please.
I would much appreciate if you could edit it and send me
Thanx a million.
Regards
Carty..
Try to get the best out of you, that would be the key to Success - NiCK Carty..
- Carty
- TEK-Seeker
- Posts: 18
- Joined: Thu Jun 01, 2006 11:46 am
- Location: India
re:
Well C# is ultimate but damn complicated i feel. VB.net is just too cool and easy i feel!
Not C# Carty, i said C++. C# is as useless as VB is.
Ok Carty, sooner or later you'll have to get to C++
Lets apple that sample you gave me the link to.
We don't care to place any options on the provider data structure, so we allocate space for its representative structure and keep its fields blank.
Byte[] ProvData = new Byte[12];
Well we need to 'care' about this one and change it a bit.
this ProvData corresponds to the API TEXT_PROVIDER_SPECIFIC_DATA structure, but its incorrectly defined, must be new Byte[164] (this is the correct size for the TEXT_PROVIDER_SPECIFIC_DATA).
Now we need to setup the psMessageClass field of TEXT_PROVIDER_SPECIFIC_DATA to PS_MESSAGE_CLASS1 (PS_MESSAGE_CLASS1=1).
The offset for psMessageClass is 4.
so do this:
Byte[] ProvData = new Byte[164];
and assuming that in VB arrays start from position 0 (i dont use VB...)
do ProvData[4] = 1;
(in case arrays start from 1, do ProvData[5] = 1).
Then you can call:
retVal = SmsSendMessage(smsHandle, 0, smsAddress, 0, smsMessage,
smsMessageTag.Length, ProvData, 164
notice the 8th parameter. its changed to 164 instead of 12 which is incorrect.
Hope this works for you, and dont forget C++ lets you see things much better
Radu
- radhoo
- TEK-Insider

- Posts: 640
- Joined: Fri Mar 17, 2006 2:47 am
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 0 guests
