Win Mobile利用mapirule接收短信

http://hi.baidu.com/zgcat/blog/item/2032cc82f0060a9af603a653.html

 

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

posted @ 2010-04-14 17:43  张兴业  阅读(193)  评论(0编辑  收藏  举报