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

📄 provisionmanager.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "ProvisionManager.hpp"
#include "CommonFunctions.hpp"
#include <atlbase.h>
#include <regext.h>
#include "RegistryStore.hpp"
#include "FileStore.hpp"
#include "VoIPNotify.hpp"
#include "Provision.hpp"
#include "DialPlanParser.hpp"
#include "Common.hpp"

#define WNDCLASS_PROVISIONMGR       L"VoIPProvisionMgr"
#define WM_RTC_SHUTDOWN_COMPLETE    (WM_APP + 1)

const WCHAR ProvisionManager_t::sc_MutexName[] = L"SYSTEM/VoIPSettingsMutex";     
const DWORD ProvisionManager_t::sc_MutexTimeoutValue = 6 * 1000;                  

const DWORD ProvisionManager_t::PROCESSING_XML    = 0x00000001;
const DWORD ProvisionManager_t::VALIDATE_XML_ONLY = 0x00000002;

const WCHAR ProvisionManager_t::sc_QueryElement[] = L"query"; 
const WCHAR ProvisionManager_t::sc_StartElement[] = L"voip-provision"; 

const ProvisionManager_t::XMLElement_t ProvisionManager_t::sc_ProvisionElements[] =
{
    {L"voip-provision", ProvisionManager_t::ElementStart,     ProvisionManager_t::ElementUnknown,   0}, 
    {L"set",            ProvisionManager_t::ElementSet,       ProvisionManager_t::ElementStart,     1}, 
    {L"delete",         ProvisionManager_t::ElementDelete,    ProvisionManager_t::ElementStart,     1}, 
    {L"query",          ProvisionManager_t::ElementQuery,     ProvisionManager_t::ElementStart,     1}, 
};


const ProvisionManager_t::XMLAttribute_t ProvisionManager_t::sc_ProvisionAttributes[] =
{
    {L"Name",    ProvisionManager_t::AttributeName}, 
    {L"Value",   ProvisionManager_t::AttributeValue}, 
};


ProvisionSetting_t
ProvisionManager_t::s_SIPSettings(
    SIP_SETTINGS, 
    VOIP_SIP_SETTINGS_BITMASK,
    new FileStore_t(SIP_SETTINGS),             
    true
    ); 

ProvisionSetting_t
ProvisionManager_t::s_BackupSIPSettings(
    BACKUP_SIP_SETTINGS, 
    VOIP_BACKUP_SIP_SETTINGS_BITMASK, 
    new FileStore_t(BACKUP_SIP_SETTINGS), 
    true
    ); 

ProvisionSetting_t
ProvisionManager_t::s_VoicemailSettings(
    VOICEMAIL_SETTINGS, 
    VOIP_VOICEMAIL_SETTINGS_BITMASK, 
    new FileStore_t(VOICEMAIL_SETTINGS), 
    true
    ); 
    
ProvisionSetting_t
ProvisionManager_t::s_VoicemailNumber(
    VOICEMAIL_NUMBER, 
    VOIP_VOICEMAIL_NUMBER_BITMASK, 
    new RegistryStore_t(VOICEMAIL_NUMBER), 
    false
    ); 

ProvisionSetting_t
ProvisionManager_t::s_DialPlan(
    DIALPLAN, 
    VOIP_DIALPLAN_BITMASK, 
    new FileStore_t(DIALPLAN), 
    false
    ); 

ProvisionManager_t::SettingValidatorMap  ProvisionManager_t::sc_ProvisionSettings[] = 
{
    {&ProvisionManager_t::s_SIPSettings,         ProvisionManager_t::IsValidRTCXML}, 
    {&ProvisionManager_t::s_BackupSIPSettings,   ProvisionManager_t::IsValidRTCXML}, 
    {&ProvisionManager_t::s_VoicemailNumber,     ProvisionManager_t::IsValidPhoneNumber}, 
    {&ProvisionManager_t::s_VoicemailSettings,   ProvisionManager_t::IsValidRTCXML}, 
    {&ProvisionManager_t::s_DialPlan,            ProvisionManager_t::IsValidDialPlan}, 
}; 

/*------------------------------------------------------------------------------
    ProvisionManager_t::ProvisionManager_t

    Constructor
------------------------------------------------------------------------------*/
ProvisionManager_t::ProvisionManager_t(
    )
{
    m_Mutex         = NULL; 
    m_UpdatedFlags  = 0; 

    m_cpRTCClient           = NULL; 
    m_cpConnectionPt        = NULL;     
    m_ListenerWindow        = NULL; 
    m_ConnectionPtCookie    = 0; 

}

/*------------------------------------------------------------------------------
    ProvisionManager_t::~ProvisionManager_t

    Destructor
------------------------------------------------------------------------------*/
ProvisionManager_t::~ProvisionManager_t(
    )
{
    if (!m_ElementsStack.empty())
    {
        ASSERT(FALSE);
        m_ElementsStack.clear();
    }

    if (!m_QuerySettingsStack.empty())
    {
        ASSERT(FALSE); 
        ClearQuerySettingsStack(); 
    }

    //if the RTCClient was initialized duringt the process, shut it down
    if (m_cpRTCClient != NULL)
    {
        //we cannot be sure that RTC instances are usable when this is called from DLL_PROCESS_DETACH
        //as a result of ExitThread (terminate process) - server's (rtcclinet.dll) DllMain entry could
        //get called first and thus it cleans up reosurces before we have our chance.
        __try
        {
            HRESULT hr = m_cpRTCClient->PrepareForShutdown();
            if (SUCCEEDED(hr))
            {
                MSG msg = {0}; 
                while (GetMessage(&msg, NULL, 0, 0))
                {
                    if (msg.hwnd == m_ListenerWindow &&
                        msg.message == WM_RTC_SHUTDOWN_COMPLETE)
                    {
                        break; 
                    }

                    TranslateMessage(&msg); 
                    DispatchMessage(&msg);                     
                }
            }

            UnregisterCallbackInterface(); 
            
            m_cpRTCClient->Shutdown(); 
            
            m_cpRTCClient = NULL; 

        }
        __except( EXCEPTION_EXECUTE_HANDLER ) //catch (...)
        {
            // Null-out all the RTC instances without releasing the references - we cannot
            // be sure that the server is up if this is called from Dll Process Detach
            PhoneAppUtilities_t::NullOutCOMPtr<IRTCClient>(&m_cpRTCClient);
            PhoneAppUtilities_t::NullOutCOMPtr<IConnectionPoint>(&m_cpConnectionPt);
        }

    }

    if (m_Mutex != NULL)
    {
        if (!ReleaseMutex(m_Mutex))
        {
            ///TODO: debug output the failure reason
        }

        CloseHandle(m_Mutex); 
        m_Mutex = NULL; 
    }

    if (m_ListenerWindow != NULL)
    {
        DestroyWindow(m_ListenerWindow); 
        m_ListenerWindow = NULL;         
    }

    UnregisterClass(
        WNDCLASS_PROVISIONMGR, 
        GlobalData_t::s_ModuleInstance
        ); 
    
}

/*------------------------------------------------------------------------------
    ProvisionManager_t::GetElementType

    Gets the type of dial plan element

    Parameters:
        : IN - const WCHAR* - The element's name
        : IN - int - The length of the name
        : OUT - ProvisionElement_e* - The type of element

    Returns:
        - S_OK returned if no errors occur
        - E_INVALIDARG returned if caller passed a NULL pointer
------------------------------------------------------------------------------*/
HRESULT
ProvisionManager_t::GetElementType(
    const WCHAR*            pElementName,
    int                     ElementNameLength,
    ProvisionElement_e*     pElementType, 
    int*                    pElementIndex
    )
{
    int Index;

    ASSERT(pElementType);

    if (pElementName == NULL ||pElementType == NULL || pElementIndex == NULL) 
    {
        return E_INVALIDARG;
    }

    CASSERT(ElementUnknown == ARRAYSIZE(sc_ProvisionElements));

    for (Index = 0; Index < ARRAYSIZE(sc_ProvisionElements); Index++)
    {
        if ((ElementNameLength == wcslen(sc_ProvisionElements[Index].m_pName)) &&
            (0 == PhoneAppUtilities_t::InvStrCmpNI(
                        sc_ProvisionElements[Index].m_pName,
                        pElementName,
                        ElementNameLength
                        )))
        {
            // Found supported element
            break;
        }
    }

    ASSERT(Index <= ElementUnknown);
    *pElementType = sc_ProvisionElements[Index].m_Element;
    *pElementIndex = Index; 

    return S_OK;
}

/*------------------------------------------------------------------------------
    ProvisionManager_t::GetAttributeType

    Gets the type of rule attribute

    Parameters:
        : IN - const WCHAR* - The attribute's name
        : IN - int - The length of the name
        : OUT - ProvisionAttribute_e* - The type of attribute

    Returns:
        - S_OK if no errors occur
        - E_INVALIDARG returned if caller passed a NULL pointer
------------------------------------------------------------------------------*/
HRESULT
ProvisionManager_t::GetAttributeType(
    const WCHAR*            pAttributeName,
    int                     AttributeNameLength,
    ProvisionAttribute_e*   pAttributeType
    )
{
    int Index;

    ASSERT(pAttributeType);

    if (!pAttributeName)
    {
        return E_INVALIDARG;
    }

    CASSERT(AttributeUnknown == ARRAYSIZE(sc_ProvisionAttributes));

    for (Index = 0; Index < ARRAYSIZE(sc_ProvisionAttributes); Index++)
    {
        if ((AttributeNameLength == wcslen(sc_ProvisionAttributes[Index].m_pName)) &&
            (0 == PhoneAppUtilities_t::InvStrCmpNI(
                        sc_ProvisionAttributes[Index].m_pName,
                        pAttributeName,
                        AttributeNameLength
                        )))
        {
            // Found supported element
            break;
        }
    }

    ASSERT(Index <= ElementUnknown);
    *pAttributeType = sc_ProvisionAttributes[Index].m_Attribute;

    return S_OK;
}

/*------------------------------------------------------------------------------
    ProvisionManager_t::IsXMLElementHierarchyValid

    Verifies hierarchy for an XMLElement_t 

    Parameters:
        : IN - XMLElement_t* - The XML element to verify

    Returns:
        - true returned if both parent and depth level match the stack
        - false returned otherwise
------------------------------------------------------------------------------*/
inline
bool
ProvisionManager_t::IsXMLElementHierarchyValid(
    const XMLElement_t * pThisElement
    )
{
    return ((pThisElement->m_Level == m_ElementsStack.size()) &&
        (pThisElement->m_ParentElement == m_ElementsStack.front()));
}

/*------------------------------------------------------------------------------
    ProvisionManager_t::ProcessXML

    Parses the XML and processes it at the same time

    Parameters:
        : IN - BSTR - The XML string for the dial plan

    Returns:
        - S_OK returned if no errors occur
        - Error code returned if the operation fails
------------------------------------------------------------------------------*/
HRESULT
ProvisionManager_t::ProcessXML(
    BSTR        ProvisionXML,
    bool        ValidateOnly, 
    WCHAR**     ppOutputXML
    )
{
    HRESULT hr;
    CComPtr<ISAXXMLReader> cpISAXReader;
    VARIANT varXML;
    bool    IsUpdated = false; 

    VariantInit(&varXML);

    if (m_Flags & PROCESSING_XML)
    {
        return E_FAIL;
    }

    m_Flags |= PROCESSING_XML;

    if (ValidateOnly)
    {
        m_Flags |= VALIDATE_XML_ONLY;
    }

    //do some preparation for the provision
    hr = DoPreparation(); 
    if (FAILED(hr))
    {
        goto exit; 
    }

    // Instantiate the SAX reader and add our event hook
    hr = cpISAXReader.CoCreateInstance(__uuidof(SAXXMLReader));
    if (FAILED(hr))
    {
        goto exit;
    }

    hr = cpISAXReader->putContentHandler(this);
    if (FAILED(hr))
    {
        goto exit;
    }

    static const WCHAR sc_FileScheme[] = L"file:\\\\";
    if (0 != PhoneAppUtilities_t::InvStrCmpNI(
                        ProvisionXML,
                        sc_FileScheme,
                        ARRAYSIZE(sc_FileScheme)-1
                        ))
    {
        varXML.vt = VT_BSTR;
        varXML.bstrVal = ProvisionXML;

        // Parse the XML and process it at the same time
        hr = cpISAXReader->parse(varXML);
    }
    else
    {
        // Parse XML from file and process it at the same time
        hr = cpISAXReader->parseURL(ProvisionXML);
    }

    // Always reset the stack
    m_ElementsStack.clear();

    if (SUCCEEDED(hr))
    {
        hr = FinishUp(&IsUpdated); 
    }

    if (SUCCEEDED(hr) && !m_QuerySettingsStack.empty())
    {
        GetReturnXML(ppOutputXML); 
    }

    ClearQuerySettingsStack(); 
    
    DeleteObsoleteSettings(IsUpdated); 

exit:

    m_Flags &= ~(PROCESSING_XML | VALIDATE_XML_ONLY);
    
    return hr;
}


////////////////////////////////////////////////////////////////////////////////
// IUnknown

/*------------------------------------------------------------------------------
    ProvisionManager_t::QueryInterface

    IUnknown::QueryInterface implementation
------------------------------------------------------------------------------*/
HRESULT
ProvisionManager_t::QueryInterface(
    REFIID riid, 
    void** ppvObject
    )
{
    if (! ppvObject)
    {

⌨️ 快捷键说明

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