📄 provisionmanager.cpp
字号:
//
// 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 + -