locked
AdviseSink::OnNotify not called when new SMS arrives or when SMS deleted RRS feed

  • Question

  • hi,

    i've created an AdviseSink as below for Windows Mobile.  When I use CreateMessage as listed below, I get a notification and OnNotify is called, but I don't get any notifications when I actually send an SMS or delete an SMS from the Inbox.  I am currently running this as a standalone application (not in Services.exe).   Can someone please help?

    Also, if I were to run this as a service (in Services.exe), would the notification not arrive and why?


    int _tmain( int argc, TCHAR* argv[] )
    {
        InitMAPISession();
        Sleep(1000000);
        return 0;
    }


    BOOL  InitMAPISession (void)
    {
        HRESULT hr;
        DEBUGMSG(1, (TEXT("SmsClass::InitMAPISession\r\n")));

        LPMAPITABLE      pTable   = NULL;
        IMsgStore      * pStore   = NULL;
        SRowSet        * pSRowSet = NULL;
        ULONG ulConnId = 10;
        HINSTANCE mapiDLL ;
        ULONG ulTotalMessages = 555;
        LPMAPIFOLDER pFolder = NULL;

        if (mapiDLL = LoadLibrary(TEXT("CEMAPI.dll")))
        {
     
            hr = MAPIInitialize(NULL);
            hr = MAPILogonEx(0, NULL, NULL, 0, (LPMAPISESSION *)&pSession);
           
            // Initialize MAPI

            //variable to be used when setting the columns of the table we're going to retrieve
            static const SizedSPropTagArray(3, Columns) = { 3, {PR_DISPLAY_NAME, PR_ENTRYID, PR_CONTENT_COUNT} };

            // Get table of different message stores
            hr = pSession->GetMsgStoresTable(0, &pTable);

            // set the columns of the table we will query
            hr = pTable->SetColumns((LPSPropTagArray) &Columns, NULL);
           
            // Get table row item MsgStore we loop over the message stores opening each msgstore
            // and getting its name to see if the name matches SMS.  If so, we break out of the loop
            while (TRUE)
            {
                FreeProws(pSRowSet);
                pSRowSet = NULL;
               
                hr = pTable->QueryRows(1, 0, &pSRowSet);
               
                // If we failed to query the rows then we need to break
                if (FAILED(hr))
                {
                    break;
                }

                SPropValue *pval = pSRowSet->aRow[0].lpProps;

                // If the name matches SMS then break and as hr == S_OK the current
                // MsgStore smart pointer will correctly be set.
                if (_tcsicmp(pval[0].Value.lpszW, _T("SMS")) == 0)
                {
                    RETAILMSG(1, (TEXT("Name matches SMS")));
                    hr = pSession->OpenMsgStore(0, pval[1].Value.bin.cb, (LPENTRYID)pval[1].Value.bin.lpb, 0, 0, &pStore);
                   
                    ULONG cbEntryId = 0;
                    LPENTRYID pEntryId = NULL;
                    ULONG ulObjType = 0;
                    //LPMAPIFOLDER pFolder = NULL;
                   
                    // Get the inbox folder
                    hr = pStore->GetReceiveFolder(NULL, MAPI_UNICODE, &cbEntryId, &pEntryId, NULL);

                    // We have the entryid of the inbox folder, let's get the folder and messages in it
                    hr = pStore->OpenEntry(cbEntryId, pEntryId, NULL, 0, &ulObjType, (LPUNKNOWN*)&pFolder);

                    ULONG rgTags[] = {2, PR_CONTENT_COUNT, PR_FOLDER_TYPE};
                    ULONG cValues = 0;
                    IMAPIProp *pProp = NULL;
                    SPropValue *rgFolderProps= NULL;
                   
                    // Get an IMAPIProp Interface
                    hr = pFolder->QueryInterface(IID_IMAPIProp, (LPVOID *) &pProp);

                    // Get the Folder PR_CONTENT_COUNT property
                    hr = pProp->GetProps((LPSPropTagArray)rgTags, MAPI_UNICODE, &cValues, &rgFolderProps);          
                   
                    //Set #messages
                    ulTotalMessages = rgFolderProps[0].Value.ul;
                   
                    RETAILMSG(1, (TEXT("Value of MsgCount is: %d"), ulTotalMessages));
                    break;
                }

            }

            pSink = new CMAPIAdviseSink(pSession);

            // Register to receive notifications
            RETAILMSG(1, (TEXT("Advise")));
            hr = pStore->Advise(0,
                              NULL,
                              fnevNewMail | fnevObjectCopied | fnevObjectCreated|
                              fnevObjectDeleted | fnevObjectModified | fnevObjectMoved,
                              pSink,
                              &ulConnId);
            if (S_OK == hr)
                RETAILMSG(1, (TEXT("Advise Succeeded")));

            IMessage* pMessage;
            HRESULT hr = pFolder->CreateMessage(NULL, 0, &pMessage);

            FreeLibrary ( mapiDLL ) ;
        }

        return hr;
    }



    STDMETHODIMP_(ULONG) CMAPIAdviseSink::OnNotify
    (
        ULONG cNotif,
        LPNOTIFICATION lpNotifications
    )
    {
        HRESULT hr = 1;
        RETAILMSG(1, (TEXT("IMAPIAdviseSink::OnNotify")));
       
        switch (lpNotifications->ulEventType)
        {
        case fnevNewMail:
        {
            RETAILMSG(1, (TEXT("New Mail")));
            hr = 0;
            break;
        }
        case fnevObjectCopied:
        {
            RETAILMSG(1, (TEXT("New Mail")));
            hr = 0;
            break;
        }
        case fnevObjectCreated:
        {
            RETAILMSG(1, (TEXT("Object Created")));
            hr = 0;
            break;
        }
        case fnevObjectDeleted:
        {
            RETAILMSG(1, (TEXT("Object Deleted")));
            hr = 0;
            break;
        }
        case fnevObjectModified:
        {
            RETAILMSG(1, (TEXT("New Mail")));
            hr = 0;
            break;
        }
        case fnevObjectMoved:
        {
            RETAILMSG(1, (TEXT("New Mail")));
            hr = 0;
            break;
        }
        }
       
        return hr;
    }

    Thanks,
    RT
    Tuesday, March 24, 2009 1:21 AM

Answers

  • Hi Shindo2006,

    If we remove the code you mentioned, we will never get the notification. Because once you move the thread, OS will notify your application, your application will invoke following code to dispatch message to proper place to handle:

    while (GetMessage(&msg, NULL, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

    If we romove them, it will not be notified.

     

     

    Best regards,
    Guang-Ming Bian - MSFT


    Please remember to mark the replies as answers if they help and unmark them if they provide no help
    • Marked as answer by Shindou2006 Saturday, April 4, 2009 1:06 AM
    Tuesday, March 31, 2009 3:35 AM
  • Hi Shindou1006,

    I tried a sample, it works fine. Both sending SMS and deleting SMS fire onNotify event. The sample is just for testing purpose.

    void CMyDialog::OnBnClickedButton1()  
    {      
        DoSetAdviceSink();     
    }  
    BOOL DoSetAdviceSink()  
    {  
        HRESULT hr = MAPIInitialize(NULL);  
        if (FAILED(hr))  
        {  
            MessageBox(0,_T("MAPIInitialize"),0,0);  
            return hr;  
        }  
        else  
        ; // initialized the MAPI subsystem  
     
        BOOL bRet = FALSE;  
       // hr = MAPILogonEx(0 ,NULL, NULL, 0, &spAdviceSession);  
        hr = MAPILogonEx(0, NULL, NULL, 0, (LPMAPISESSION *)&spAdviceSession);  
        if (FAILED(hr))  
        {  
            MessageBox(0,_T("MAPILogonEx"),0,0);  
        }  
        else  
        {  
            HRESULT hr = GetSMSMsgStore(spAdviceSession, spAdvMsgStore);  
            if (FAILED(hr))  
            {  
                MessageBox(0,_T("GetSMSMsgStore"),0,0);  
                return FALSE;  
            }  
            //AdviseSink = new MAPIAdviseSink();  
            MAPIAdviseSink *AdviseSink = new MAPIAdviseSink();  
            ULONG ulConn = 0;  
            spAdvMsgStore->Advise(0,NULL,fnevNewMail | fnevObjectCopied | fnevObjectCreated|fnevObjectDeleted | fnevObjectModified | fnevObjectMoved,AdviseSink,&ulConn);  
        }  
        return bRet;  
    }  
    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))  
        {  
            MessageBox(0,_T("GetMsgStoresTable"),0,0);  
            return FALSE;  
        }  
     
          
                enum{  
            ePR_DISPLAY_NAME,  
            ePR_ENTRYID,//ePR_CE_UNIQUE_STORE_ID,  
            NUM_COLS  
            };  
            SizedSPropTagArray(NUM_COLS,Columns) =  
            {    
            NUM_COLS,  
            PR_DISPLAY_NAME,  
            PR_ENTRYID,  
            };  
        hrspTable->SetColumns((LPSPropTagArray)&Columns,0);  
     
        SRowSet* pRowSet = NULL;  
        while (TRUE)  
        {  
              
            hr = spTable->QueryRows(1, 0, &pRowSet);  
     
            // If we failed to query the  
            // rows then we need to break  
            if (FAILED(hr))  
            {  
                MessageBox(0,_T("QueryRows"),0,0);  
                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[1].ulPropTag == PR_ENTRYID);  
                SBinary& blob = pRowSet->aRow[0].lpProps[1].Value.bin;  
     
                TCHAR *pszStoreName =pRowSet->aRow[0].lpProps[0].Value.lpszW;  
     
     
                if (_tcsicmp(pRowSet->aRow[0].lpProps[0].Value.lpszW, _T("SMS")) == 0)  
                {             
            
                    hr = spSession->OpenMsgStore(0,   
                       pRowSet->aRow[0].lpProps[1].Value.bin.cb,   
                       (ENTRYID *)pRowSet->aRow[0].lpProps[1].Value.bin.lpb,   
                       NULL,   
                       0,   
                       &spMsgStore);  
                    if (FAILED(hr))  
                        MessageBox(0,_T("OpenMsgStore"),0,0);  
                    break;  
                  }  
     
            }  
            else  
            {  
                MessageBox(0,_T("MSGNOTFOUND"),0,0);  
                hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);  
            }  
     
              
        if (FAILED(hr))  
        {  
            spMsgStore.Release();  
        }  
     
        return hr;  
    }  
     

    You can try my code.



    Best regards,
    Guang-Ming Bian - MSFT
    Please remember to mark the replies as answers if they help and unmark them if they provide no help
    Thursday, March 26, 2009 9:12 AM

All replies

  • Anyone have any idea on this?
    Tuesday, March 24, 2009 11:28 PM
  • If anyone with experience using MAPI could comment, I would really appreciate it!
    Thursday, March 26, 2009 3:27 AM
  • Hi Shindou1006,

    I tried a sample, it works fine. Both sending SMS and deleting SMS fire onNotify event. The sample is just for testing purpose.

    void CMyDialog::OnBnClickedButton1()  
    {      
        DoSetAdviceSink();     
    }  
    BOOL DoSetAdviceSink()  
    {  
        HRESULT hr = MAPIInitialize(NULL);  
        if (FAILED(hr))  
        {  
            MessageBox(0,_T("MAPIInitialize"),0,0);  
            return hr;  
        }  
        else  
        ; // initialized the MAPI subsystem  
     
        BOOL bRet = FALSE;  
       // hr = MAPILogonEx(0 ,NULL, NULL, 0, &spAdviceSession);  
        hr = MAPILogonEx(0, NULL, NULL, 0, (LPMAPISESSION *)&spAdviceSession);  
        if (FAILED(hr))  
        {  
            MessageBox(0,_T("MAPILogonEx"),0,0);  
        }  
        else  
        {  
            HRESULT hr = GetSMSMsgStore(spAdviceSession, spAdvMsgStore);  
            if (FAILED(hr))  
            {  
                MessageBox(0,_T("GetSMSMsgStore"),0,0);  
                return FALSE;  
            }  
            //AdviseSink = new MAPIAdviseSink();  
            MAPIAdviseSink *AdviseSink = new MAPIAdviseSink();  
            ULONG ulConn = 0;  
            spAdvMsgStore->Advise(0,NULL,fnevNewMail | fnevObjectCopied | fnevObjectCreated|fnevObjectDeleted | fnevObjectModified | fnevObjectMoved,AdviseSink,&ulConn);  
        }  
        return bRet;  
    }  
    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))  
        {  
            MessageBox(0,_T("GetMsgStoresTable"),0,0);  
            return FALSE;  
        }  
     
          
                enum{  
            ePR_DISPLAY_NAME,  
            ePR_ENTRYID,//ePR_CE_UNIQUE_STORE_ID,  
            NUM_COLS  
            };  
            SizedSPropTagArray(NUM_COLS,Columns) =  
            {    
            NUM_COLS,  
            PR_DISPLAY_NAME,  
            PR_ENTRYID,  
            };  
        hrspTable->SetColumns((LPSPropTagArray)&Columns,0);  
     
        SRowSet* pRowSet = NULL;  
        while (TRUE)  
        {  
              
            hr = spTable->QueryRows(1, 0, &pRowSet);  
     
            // If we failed to query the  
            // rows then we need to break  
            if (FAILED(hr))  
            {  
                MessageBox(0,_T("QueryRows"),0,0);  
                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[1].ulPropTag == PR_ENTRYID);  
                SBinary& blob = pRowSet->aRow[0].lpProps[1].Value.bin;  
     
                TCHAR *pszStoreName =pRowSet->aRow[0].lpProps[0].Value.lpszW;  
     
     
                if (_tcsicmp(pRowSet->aRow[0].lpProps[0].Value.lpszW, _T("SMS")) == 0)  
                {             
            
                    hr = spSession->OpenMsgStore(0,   
                       pRowSet->aRow[0].lpProps[1].Value.bin.cb,   
                       (ENTRYID *)pRowSet->aRow[0].lpProps[1].Value.bin.lpb,   
                       NULL,   
                       0,   
                       &spMsgStore);  
                    if (FAILED(hr))  
                        MessageBox(0,_T("OpenMsgStore"),0,0);  
                    break;  
                  }  
     
            }  
            else  
            {  
                MessageBox(0,_T("MSGNOTFOUND"),0,0);  
                hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);  
            }  
     
              
        if (FAILED(hr))  
        {  
            spMsgStore.Release();  
        }  
     
        return hr;  
    }  
     

    You can try my code.



    Best regards,
    Guang-Ming Bian - MSFT
    Please remember to mark the replies as answers if they help and unmark them if they provide no help
    Thursday, March 26, 2009 9:12 AM
  • Hi Guang-Ming,

    Thanks for the code.  I tried it with a button and it works.  However, I noticed when I put the code into WinMain() and remove the following

        while (GetMessage(&msg, NULL, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }


    I don't get any notifications.  This would be similar to what I was originally doing without any preset code that comes with Visual Studio projects.  Is MAPI based on those messages?

    Thanks,
    RT
    Monday, March 30, 2009 6:29 PM
  • Hi Shindo2006,

    If we remove the code you mentioned, we will never get the notification. Because once you move the thread, OS will notify your application, your application will invoke following code to dispatch message to proper place to handle:

    while (GetMessage(&msg, NULL, 0, 0))
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

    If we romove them, it will not be notified.

     

     

    Best regards,
    Guang-Ming Bian - MSFT


    Please remember to mark the replies as answers if they help and unmark them if they provide no help
    • Marked as answer by Shindou2006 Saturday, April 4, 2009 1:06 AM
    Tuesday, March 31, 2009 3:35 AM