一。在能够使用 MAPI 规则客户端之前,我们需要将其注册为 COM 对象,同时将它的类标识符添加到下面的注册表项中:HKEY_CLASSES_ROOT/CLSID/。为了使收件箱意识到 MAPI 规则客户端的存在,我们还必须将它的类标识符写入下面的注册表项中: HKEY_LOCAL_MACHINE/Software/Microsoft/Inbox/Svc/SMS/Rules。
//注册为COM对象
lr = RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("//CLSID//{3AB4C10E-673C-494c-98A2-CC2E91A48115}"),
0, NULL, 0, 0, NULL,
&hKey, &dwDisposition);
lr = RegCreateKeyEx(hKey, TEXT("InprocServer32"),
0, NULL, 0, 0, NULL,
&hSubKey, &dwDisposition);
lstrcpy(wszValue, TEXT("//windows//mapirule.dll"));
lr = RegSetValueEx(hSubKey, NULL, 0, REG_SZ, (LPBYTE) wszValue, (lstrlen(wszValue) + 1) * sizeof(TCHAR));
//注册到Inbox:
lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("//Software//Microsoft//Inbox//Svc//SMS//Rules"),
0, NULL, 0, 0, NULL,
&hKey, &dwDisposition);
lr = RegSetValueEx(hKey, TEXT("{3AB4C10E-673C-494c-98A2-CC2E91A48115}"), 0, REG_DWORD,
(LPBYTE) &dwDisposition, sizeof(DWORD));
二。注册成功后系统会自动调用函数ProcessMessage接收短信,当接收到短信内容是"zzz"时放入内存映射文件中
(还有其它方法传递给应用程序,比如消息等),然后删除该短信。
HRESULT CMailRuleClient::ProcessMessage(IMsgStore *pMsgStore, ULONG cbMsg, LPENTRYID lpMsg,
ULONG cbDestFolder, LPENTRYID lpDestFolder, ULONG *pulEventType, MRCHANDLED *pHandled)
{
HRESULT hr = S_OK;
SizedSPropTagArray(1, sptaSubject) = { 1, PR_SUBJECT};
SizedSPropTagArray(1, sptaEmail) = { 1, PR_SENDER_EMAIL_ADDRESS};
ULONG cValues = 0;
SPropValue *pspvSubject = NULL;
SPropValue *pspvEmail = NULL;
IMessage *pMsg = NULL;
HRESULT hrRet = S_OK;
// Get the message from the entry ID
hr = pMsgStore->OpenEntry(cbMsg, lpMsg, NULL, 0, NULL, (LPUNKNOWN *) &pMsg);
if (FAILED(hr))
{
RETAILMSG(TRUE, (TEXT("Unable to get the message!/r/n")));
goto Exit;
}
// For SMS, the subject is also the message body
hr = pMsg->GetProps((SPropTagArray *) &sptaSubject, MAPI_UNICODE, &cValues, &pspvSubject);
if (FAILED(hr))
{
RETAILMSG(TRUE, (TEXT("Unable to get the message body!/r/n")));
goto Exit;
}
// get the sender's address or phone number
hr = pMsg->GetProps((SPropTagArray *) &sptaEmail, MAPI_UNICODE, &cValues, &pspvEmail);
if (FAILED(hr))
{
RETAILMSG(TRUE, (TEXT("Couldn't get the sender's address!/r/n")));
goto Exit;
}
// Here we filter the message on some predetermined string. For sample purposes
// here we use "zzz". What happens when the filter condition(s) are met is up to
// you. You can send WM_COPYDATA messages to other app windows for light IPC, send
// an SMS message in response, or whatever you need to do.
if (wcsstr(pspvSubject->Value.lpszW, L"zzz") != NULL)
{
if (g_hSmsAvailableEvent != NULL) {
// We have received an SMS message that needs to be send to our client.
// Since we run in the process space of Inbox, we are using a memory mapped
// file to pass the message and phone number to our client, that typically
// runs in another process space (therefor we can not simply copy strings).
// We protect the memory mapped file with a Mutex to make sure that we are
// not writing new SMS data while the reading client is still processing
// a previous SMS message.
WaitForSingleObject(g_hMutex, INFINITE);
lstrcpy(g_pSmsBuffer->g_szPhoneNr, pspvEmail->Value.lpszW);
lstrcpy(g_pSmsBuffer->g_szMessageBody, pspvSubject->Value.lpszW);
ReleaseMutex(g_hMutex);
SetEvent(g_hSmsAvailableEvent);
}
// Delete the message and mark it as handled so it won't show up in Inbox
hr = DeleteMessage(pMsgStore, pMsg, cbMsg, lpMsg, cbDestFolder, lpDestFolder, pulEventType, pHandled);
}
else
{
// a 'normal' message, pass it on
*pHandled = MRC_NOT_HANDLED;
}
// Clean up
Exit:
if (pspvEmail)
{
MAPIFreeBuffer(pspvEmail);
}
if (pspvSubject)
{
MAPIFreeBuffer(pspvSubject);
}
if (pMsg)
{
pMsg->Release();
}
return hr;
}
三。应用程序监听内存映射文件(调用TerminateSMSMessagePassing )
void TerminateSMSMessagePassing (void)
{
// Make sure to have one last empty string available to copy to the client.
memset(g_pClientSmsBuffer, 0, sizeof(SMS_BUFFER));
SetEvent(g_hClientEvent); // optionally allow the calling application to return from GetData.
CloseHandle(g_hClientEvent);
CloseHandle(g_hClientMutex);
if (g_pClientSmsBuffer) {
UnmapViewOfFile(g_pClientSmsBuffer);
g_pClientSmsBuffer = NULL;
}
if (g_hClientMMObj) {
CloseHandle(g_hClientMMObj);
g_hClientMMObj = NULL;
}
}
四。应用得到短信内容和发短信的号(调用SMSMessageAvailable )
BOOL SMSMessageAvailable (wchar_t *lpDestination, wchar_t *lpPhoneNr)
{
WaitForSingleObject(g_hClientEvent, INFINITE);
if (g_pClientSmsBuffer != NULL) {
WaitForSingleObject(g_hClientMutex, INFINITE);
lstrcpy(lpPhoneNr, g_pClientSmsBuffer->g_szPhoneNr);
lstrcpy(lpDestination, g_pClientSmsBuffer->g_szMessageBody);
ReleaseMutex(g_hClientMutex);
} else {
*lpPhoneNr = '/0';
*lpDestination = '/0';
}
return *lpPhoneNr != '/0';
}
五。注销MailRuleClient对象
STDAPI DllUnregisterServer()
{
HKEY hKey = NULL;
HRESULT hr = E_FAIL;
LRESULT lr;
DWORD dwDisposition;
// Delete registry keys
RegDeleteKey(HKEY_CLASSES_ROOT, TEXT("//CLSID//{3AB4C10E-673C-494c-98A2-CC2E91A48115}"));
lr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("//Software//Microsoft//Inbox//Svc//SMS//Rules"),
0, NULL, 0, 0, NULL,
&hKey, &dwDisposition);
if (lr != ERROR_SUCCESS)
{
goto Exit;
}
lr = RegDeleteValue(hKey, TEXT("{3AB4C10E-673C-494c-98A2-CC2E91A48115}"));
hr = S_OK;
Exit:
if (hKey)
{
RegCloseKey(hKey);
}
return hr;
}
六。在C++中调用过程如下:
HINSTANCE hInstLibrary = LoadLibrary(_T("//windows//mapirule.dll"));
if (hInstLibrary == NULL) {
FreeLibrary(hInstLibrary);
return 0;
}
//注册
if (DllRegisterServer() == 0)
{
MessageBox("Could not initialize the IMailRuleClient DLL");
FreeLibrary(hInstLibrary);
return 0;
}
CaptureSMSMessages();
while(true){
SMSMessageAvailable(lpDestination,lpPhoneNr);
if(*lpDestination != '/0'){
OutputDebugString(lpDestination);
break;
}
}
TerminateSMSMessagePassing();
DllUnregisterServer();
FreeLibrary(hInstLibrary);
七。在C#中调用
//导入库文件
#region P/Invoke helpers
[DllImport("mapirule.dll")]
public static extern int DllRegisterServer();
[DllImport("mapirule.dll")]
public static extern void DllUnregisterServer();
[DllImport("coredll.dll")]
public static extern IntPtr LoadLibrary(string libName);
[DllImport("coredll.dll")]
public static extern bool FreeLibrary(IntPtr hLibModule);
#endregion
public class UnmanagedAPI
{
[DllImport("mapirule.dll")]
public static extern int SMSMessageAvailable(StringBuilder message, StringBuilder phoneNumber);
[DllImport("mapirule.dll")]
public static extern void CaptureSMSMessages();
[DllImport("mapirule.dll")]
public static extern void TerminateSMSMessagePassing();
}
#endregion
//注册
hLibModule = LoadLibrary("mapirule.dll");
if (DllRegisterServer() != 0)
{
MessageBox.Show("Could not initialize the IMailRuleClient DLL");
}
//监听并取得消息
UnmanagedAPI.CaptureSMSMessages();
while (! bDone)
{
UnmanagedAPI.SMSMessageAvailable(sbSms, sbPhoneNr);
if (sbSms.Length != 0)
{
parentForm.ReceivedSMSMessage = sbPhoneNr.ToString() + " - " + sbSms.ToString();
parentForm.Invoke(new EventHandler(parentForm.UpdateListBox));
}
}
//注销
DllUnregisterServer();
FreeLibrary(hLibModule);