⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdkemsviewerruleclient.cpp

📁 WIndows mobile 5.0 pocket pc sdk sample for win32
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/******************************************************************************

	File: SDKEMSViewerRuleClient.cpp
    
    Purpose: 
    Rule client to intercept EMS messages.  It parses the header and user data 
    and writes info to the message for the EMS custom form to read and process.

    Remarks:
    Must set these reg keys to register the rule client
    [HKCR\CLSID\{7D0E1A87-734C-4d46-B715-327A8884D38B}\InProcServer32]
    @="SDKEMSViewerRuleClient.dll"

    [HKLM\Software\Microsoft\Inbox\Svc\SMS\Rules]
    "{7D0E1A87-734C-4d46-B715-327A8884D38B}" = DWORD : 1

    For EMS to work we also need to set a reg key (requires a reboot if the 
    SMS router has been used)
    [HKEY_CURRENT_USER\Software\Microsoft\SMS\TextShared]
    DWORD : EMSHandlerInstalled = 1

******************************************************************************/
#define INITGUID
#include "SDKEMSViewerRuleClient.h"

//GLOBALS  ////////////////////////////////////////////////////////////////////
// {7D0E1A87-734C-4d46-B715-327A8884D38B}
DEFINE_GUID(CLSID_SDKEMSViewerRuleClient, 
0x7d0e1a87, 0x734c, 0x4d46, 0xb7, 0x15, 0x32, 0x7a, 0x88, 0x84, 0xd3, 0x8b);

int         g_cServerLocks  = 0;
HINSTANCE   g_hInstance     = NULL;

/*List of components handled in this DLL, each component must be listed here
if it wants to able to be loaded by the class factory
*/
CFactoryData g_rgFactoryData[] = 
{   
    {&CLSID_SDKEMSViewerRuleClient,     //CLSID
    CRuleClient_EMS::CreateInstance}    //Creation function ptr

    //Add additional component info here...
    //i.e. if you want to add another rule client
};
//Total number of registered components
int g_iFactoryDataEntries = sizeof(g_rgFactoryData) / sizeof(CFactoryData);

/******************************************************************************

    IsMultiPartEMS - Checks header for multipart info.

    Params:
    lpHeaderData[in] - Header data from SM
    lpEMShi[in/out] - Header info struct to fill

    Returns:
    TRUE if Multipart IEIs exits in header, FALSE OTW

    Remarks:

******************************************************************************/
BOOL IsMultiPartEMS(LPBYTE lpHeaderData, LPEMSHEADERINFO lpEMShi)
{
    BOOL bRet = FALSE;
    UINT uCount = 0;

    //Validate Params
    ASSERT((NULL != lpHeaderData) && (NULL != lpEMShi));
    CBR(((NULL != lpHeaderData) && (NULL != lpEMShi)), bRet);    

    //First IEI should be the Multipart ID if it exists
    if(IEI_MULTI_8BIT == lpHeaderData[uCount])
    {
        //Next octet is length of data, should be 3 octets
        uCount++;
        ASSERT(0x03 == lpHeaderData[uCount]);

        //Next octet is the 8-bit reference number
        uCount++;
        lpEMShi->smRefIDVal.chRefID = lpHeaderData[uCount];
        
        //Next is total parts
        uCount++;
        lpEMShi->uNumParts = lpHeaderData[uCount];
        
        //Next is current part
        uCount++;
        lpEMShi->uCurrPart = lpHeaderData[uCount];
               
        lpEMShi->fRef16Bit = FALSE;
        
        bRet = TRUE;
    }
    else
    if(IEI_MULTI_16BIT == lpHeaderData[uCount])
    {
        //Next octet is length of data, should be 3 octets
        uCount++;
        ASSERT(0x03 == lpHeaderData[uCount]);

        //Next 2 octets are the 16-bit reference number
        uCount++;
        lpEMShi->smRefIDVal.wRefID = ((lpHeaderData[uCount] << 8) | lpHeaderData[uCount+1]);

        //Next is total parts
        uCount++;
        lpEMShi->uNumParts = lpHeaderData[uCount];
        
        //Next is current part
        uCount++;
        lpEMShi->uCurrPart = lpHeaderData[uCount];
        
        lpEMShi->fRef16Bit = TRUE;

        bRet = TRUE;
    }
    
Exit:
    return bRet;
}

/******************************************************************************

    ExtractEMSHeaderInfo - Copies header info to struct and fills in ID etc.

    Params:
    lpEMShi[in\out] - EMSHEADERINFO struct to fill in
    lpHeaderData[in] - EMS header data
    cbHeader[in] - size of header data buffer
    pszUserData[in] - User text with SM, can be NULL

    Returns:
    
    Remarks:

******************************************************************************/
HRESULT ExtractEMSHeaderInfo(LPEMSHEADERINFO lpEMShi, 
                             LPBYTE lpHeaderData, 
                             UINT cbHeader,
                             LPCTSTR pszUserData)
{
    HRESULT hr = S_OK;

    //Validate params
    ASSERT((NULL != pszUserData) && (NULL != lpEMShi) && (0 < cbHeader) && (NULL != lpHeaderData));
    CBRH(((NULL != pszUserData) && (NULL != lpEMShi) && (0 < cbHeader) && (NULL != lpHeaderData)), hr);

    //Clear the struct
    FREE_EMSHEADERINFO((*lpEMShi));

    lpEMShi->lpData = (LPBYTE)malloc(cbHeader);
    ASSERT(NULL != lpEMShi->lpData);
    CBRH((NULL != lpEMShi->lpData), hr);

    //Copy header info, check if multipart, etc
    lpEMShi->cbData = cbHeader;
    memcpy(lpEMShi->lpData, lpHeaderData, cbHeader);
    lpEMShi->fMultiPart = IsMultiPartEMS(lpHeaderData, lpEMShi);

    //Copy user data if we need to 
    if(NULL != *pszUserData)
    {
        lpEMShi->pszUserData = (LPTSTR)malloc(sizeof(TCHAR)*(_tcslen(pszUserData) + 1));
        CBRH((NULL != lpEMShi->pszUserData), hr);

        _tcscpy(lpEMShi->pszUserData, pszUserData);
    }

Exit:
    return hr;

}


/******************************************************************************

    SortHeaderInfo - BubbleSorts the list of EMS headers.  Not the fastest
    sorting algorithm, but the number of headers is almost always small.

    Params:
    lpemshi[in] - pointer to array of header info
    uNumHeaders[in] - count of headers stored in the array

    Returns:
    void

    Remarks:
    
******************************************************************************/
void SortHeaderInfo(LPEMSHEADERINFO lpemshi, UINT uNumHeaders)
{
    int             iIndex;
    int             iItem;
    EMSHEADERINFO   emshi;  //Temp storage

    //Bubblesort
    for(iIndex = uNumHeaders - 1; iIndex >= 0; iIndex--)
    {
        for(iItem = 1; iItem <= iIndex; iItem++)
        {
            if(lpemshi[iItem-1].uCurrPart > lpemshi[iItem].uCurrPart)
            {
                //swap headers
                memcpy(&emshi, &(lpemshi[iItem-1]), sizeof(EMSHEADERINFO));
                memcpy(&(lpemshi[iItem-1]), &(lpemshi[iItem]), sizeof(EMSHEADERINFO));
                memcpy(&(lpemshi[iItem]), &emshi, sizeof(EMSHEADERINFO));
            }
        }
    }
}


/******************************************************************************

    ValidateHeaders - Checks if currently collected headers are ok 

    Params:
    lpemshi[in] - pointer to array of headers to validate
    uNumHeaders[in] - number of headers collected so far

    Returns:
    TRUE on success, FALSE OTW

    Remarks:
    Headers are invalid if we have more than one, and all the IDs don't match

******************************************************************************/
BOOL ValidateHeaders(LPEMSHEADERINFO lpemshi, UINT uNumHeaders)
{
    BOOL bRet = TRUE;
    WORD wRefID = 0;    //stuff 8-bit in here too...
    WORD wTemp = 0;
    UINT uIndex = 0;

    //Validate params
    ASSERT(lpemshi);
    ASSERT(uNumHeaders);
    CBR((lpemshi && uNumHeaders), bRet);

    if(1 == uNumHeaders) //Impossible to have a conflict yet
    {
        goto Exit;
    }
    
    //Get the ID from the first element
    wRefID = lpemshi[0].fRef16Bit ? lpemshi[0].smRefIDVal.wRefID : lpemshi[0].smRefIDVal.chRefID;

    //Multiple case
    for(uIndex = 1; uIndex < uNumHeaders; uIndex++)
    {
        //Every other one better match
        wTemp = lpemshi[uIndex].fRef16Bit ? lpemshi[uIndex].smRefIDVal.wRefID : lpemshi[uIndex].smRefIDVal.chRefID;

        CBR((wTemp == wRefID), bRet);
    }

Exit:
    return bRet;
}


/******************************************************************************

    DeleteMessage - Deletes a message

    Params:
    pMsgStore[in] - Store where message exists
    pMsg[in] - message to delete
    cbMsg[in] - size of message in bytes
    lpMsg[in] - entryid of message
    cbDestFolder[in] - size of dest folder
    lpDestFolder[in] - folder where message resides
    pulEventType[in/out] - tracks what's been done to the message
    pHandled[in/out] - has rule client handled the message or not?

    Returns:
    S_OK on success, HRESULT error code OTW

    Remarks:

******************************************************************************/
HRESULT DeleteMessage(IMsgStore *pMsgStore, 
                      IMessage *pMsg, 
                      ULONG cbMsg, 
                      LPENTRYID lpMsg, 
                      ULONG cbDestFolder, 
                      LPENTRYID lpDestFolder, 
                      ULONG *pulEventType, 
                      MRCHANDLED *pHandled)
{
    HRESULT     hr          = S_OK;
    IMAPIFolder *pFolder    = NULL;
    ENTRYLIST   lst;
    SBinary     sbin;

    UNREFERENCED_PARAMETER(pHandled);
    UNREFERENCED_PARAMETER(pMsg);
    
    //Get the folder the message is in
    hr = pMsgStore->OpenEntry(cbDestFolder, lpDestFolder, NULL, 0, NULL, (LPUNKNOWN*)&pFolder);
    if(FAILED(hr))
    {
        RETAILMSG(TRUE, (_T("Couldn't get the folder!\r\n")));
        goto Exit;
    }
    
    //Set up the entry list
    lst.cValues = 1;                //Just the one item
    lst.lpbin   = &sbin;            //binary entry
    sbin.cb     = cbMsg;            //Size of message in bytes
    sbin.lpb    = (LPBYTE)lpMsg;    //Pointer to message
    
    //Delete the message from the folder
    hr = pFolder->DeleteMessages(&lst, NULL, NULL, 0); 
    if(FAILED(hr))
    {
        RETAILMSG(TRUE, (_T("Couldn't delete messages!\r\n")));
        goto Exit;
    }

    //Record action taken on the message
    *pulEventType = fnevObjectDeleted;
    
Exit:
    //Done using the folder
    SAFE_RELEASE(pFolder);
    
    return hr;
}

/******************************************************************************

    ProcessEMS - Process each EMS header.  Order is assured for this function

    Params:
    emshi[in] - header info for current part
    ppszOut[in/out] - Final string to write to message body, if NULL and return
        value is ok, then we're not done processing.  If non-NULL and return
        value is ok, then we're done
    pNumObjects[in/out] - number of objects in EMS, 0 if fail or not done

    Returns:
    S_OK on success, E_FAIL OTW

    Remarks:
    output format in string form is...
    [Obj Len1][Obj Data1]...[Obj'N' Len][Obj Data'N']
        4                         4          
    Bottom number is number of TCHARS... 
    
******************************************************************************/
HRESULT ProcessEMS(EMSHEADERINFO emshi,
                   LPTSTR* ppszOut,
                   UINT* pNumObjects)
{
        HRESULT hr                  = S_OK;
        BYTE    chIEI               = 0;
        BYTE    chIEIDL             = 0;
        UINT    uCount              = 0;
        TCHAR   szBuffer[MAX_PATH]  = _T("");
        LPTSTR  pszTemp             = NULL;
        UINT    uChar               = 0;
        UINT    uLenTemp            = 0;
static  TCHAR*  szBodyOut           = NULL;
static  UINT    uBaseOffset         = 0;
static  UINT    uObjCount           = 0;

    //Validate params, user data can be NULL
    ASSERT(NULL != ppszOut);
    ASSERT(NULL != pNumObjects);
    
    if((NULL == ppszOut) || (NULL == pNumObjects))
    {
        RETAILMSG(TRUE, (_T("ProcessEMS - ERROR!!! invalid argument(s)")));
        hr = E_INVALIDARG;
        goto Exit;
    }

    //skip to first IEI if multipart SM
    if(emshi.fMultiPart)
    {
        uCount += 5; //1 for length, 3 for IEID info, 1 to point to next IEI
    }

    //It's possible a portion of the EMS will contain only text
    //picture or other element won't fix so check for that
    if(uCount == emshi.cbData)
    {
        //[ID = IEI_TEXT_ONLY][Text Len][Text]
        UINT    uConv       = 0;
        UINT    uPos        = 0;
        UINT    uStrLen     = 0;
        TCHAR   szConv[3]   = _T("");

        //We'd better have text or else the message was empty?
        ASSERT(emshi.pszUserData);
        uStrLen = _tcslen(emshi.pszUserData);

        //Allocate room for the user data
        pszTemp = (TCHAR*)malloc(sizeof(TCHAR) * (uStrLen + 5));
        ASSERT(pszTemp);

        ZeroMemory(pszTemp, sizeof(TCHAR) * (_tcslen(emshi.pszUserData) + 5));
        
        //Add the ID
        _tcscat(pszTemp, _T("FF")); //IEI_TEXT_ONLY

        //Add the length
        szConv[0] = _T('0');
        uPos = (uStrLen < 0x10) ? 1 : 0;
        _itot(uStrLen, &(szConv[uPos]), BASE_HEX);
        _tcscat(pszTemp, szConv);

        //Add the data
        _tcscat(pszTemp, emshi.pszUserData);
        
        uObjCount++;            //Increase object count
        uBaseOffset += uStrLen; //Increase offset
    }
    else
    {
        //Get each IEI and IED segments
        while(uCount < emshi.cbData)
        {
            //Now we should be pointing to the next IEI
            chIEI = emshi.lpData[uCount];
            uCount++;

            //In all cases the next octet is the length of data IEIDL
            chIEIDL = emshi.lpData[uCount];
            uCount++;

            switch(chIEI)
            {
                //Only supported objects in the sample
                case IEI_LARGE_PICTURE:
                case IEI_SMALL_PICTURE:
                case IEI_VARIABLE_PICTURE:
                {
                    //This works since the IEIs are in order 0x10, 0x11, 0x12
                    int iType = chIEI - IEI_LARGE_PICTURE;

                    ASSERT((iType >= 0) && (iType <= 2));

                    //Create object to deal with the picture info
                    CEMSPicture* pPicture = new CEMSPicture(&(emshi.lpData[uCount]), 
                                                            chIEIDL, 
                                                            uBaseOffset, 
                                                            emshi.pszUserData, 
                                                            iType);
                    ASSERT(NULL != pPicture);
                    CBRH((NULL != pPicture), hr);
                    
                    //Grab the data
                    CBRH((pPicture->ExtractInfoFromHeader()), hr);
                    
                    //Do some validation on that data

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -