一。在能够使用 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);