📄 settings.cpp
字号:
WM_CHANGE_PHONE_SETTINGS,
Index
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not register callback for phone related setting notifications"));
return hr;
}
}
return S_OK;
}
/*------------------------------------------------------------------------------
Settings_t::s_ListenerWindowProc
handles messages sent to our Listener window
------------------------------------------------------------------------------*/
LRESULT
Settings_t::s_ListenerWindowProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
Settings_t* pSettings = NULL;
if (Message == WM_CREATE)
{
//On WM_CREATE we pack the settings_t object into the createstruct
//now we need to extract the object and store it into USERDATA section of the window
CREATESTRUCT* pCreateStruct = reinterpret_cast<CREATESTRUCT*>(lParam);
if (!pCreateStruct)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Create Struct is empty -- can not create this window"));
return -1;
}
pSettings = reinterpret_cast<Settings_t*>(pCreateStruct->lpCreateParams);
if (pSettings == NULL)
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"No canvas object in the create struct - cannot create this window"));
return -1;
}
SetWindowLong(
hwnd,
GWL_USERDATA,
reinterpret_cast<LONG>(pSettings)
);
}
else
{
pSettings = reinterpret_cast<Settings_t*>(GetWindowLong(hwnd, GWL_USERDATA));
}
if (pSettings == NULL)
{
return DefWindowProc(hwnd, Message, wParam, lParam);
}
return pSettings->ListenerWindowProc(hwnd, Message, wParam, lParam);
}
LRESULT
Settings_t::ListenerWindowProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
DWORD StatStoreSettingChange = SEF_NONE;
switch(Message)
{
case WM_CHANGE_PROVISION_SETTINGS:
StatStoreSettingChange |= GetUpdatedVoIPSettingFlags();
break;
case WM_CHANGE_PHONE_SETTINGS:
s_PhoneSettings[(DWORD)lParam]->Update();
break;
default:
return DefWindowProc(hwnd, Message, wParam, lParam);
}
if (m_PendingSettingUpdateFlags != SEF_NONE)
{
//add the pending settings to the updated settings
StatStoreSettingChange |= m_PendingSettingUpdateFlags;
//reset the pending settins to 0
m_PendingSettingUpdateFlags = SEF_NONE;
}
NotifySettingHandlers(StatStoreSettingChange);
return 0;
}
/*------------------------------------------------------------------------------
OnTimerExpires
implements the ITimerHandler_t::OnTimerExpires
Parameters:
TimerIdentifier: [IN] the timer identifier
Returns: none
------------------------------------------------------------------------------*/
void
Settings_t::OnTimerExpires(
UINT TimerIdentifier
)
{
if (TimerIdentifier == m_RetryTimerIdentifier)
{
//kill the timer first
(GetApp()->GetTimers()).RemoveTimer(m_RetryTimerIdentifier);
//get the pending setting flags
DWORD UpdatedSettingFlags = m_PendingSettingUpdateFlags;
//reset the pending setting flags
m_PendingSettingUpdateFlags = SEF_NONE;
//re-try to notify the setting handlers for the pending setting changes
NotifySettingHandlers(UpdatedSettingFlags);
}
return;
}
/*------------------------------------------------------------------------------
NotifySettingHandlers
Dispatch the updated setting flags to corresponding setting handler to process
Parameters:
UpdatedSettingFlags: [IN] the updated setting flags that need to be dispatched.
Returns:
S_OK indicates success, means we grab the mutex and updated each setting handlers
S_FALSE means we didn't get the mutex right away, so we set a timer for retry
otherwise failure
------------------------------------------------------------------------------*/
HRESULT
Settings_t::NotifySettingHandlers(
DWORD UpdatedSettingFlags
)
{
if (m_VoIPSettingMutex == NULL)
{
return E_UNEXPECTED;
}
HRESULT hr = S_OK;
bool GotMutex = false;
//check whether we need to aquire the mutex, if so, get the mutex
//note: if the setting is only phone status flags change, we don't need to get the mutex,
//the setting can be dispatched to Connection Manager directly, otherwise, we have to get
//the mutex first
if (UpdatedSettingFlags != SEF_NONE)
{
//for all the sttings except SEF_PHONE_STATUS_FLAGS, we need to get mutex first
DWORD Result = WaitForSingleObject(
m_VoIPSettingMutex,
0
);
switch(Result)
{
case WAIT_TIMEOUT:
//if we don't get timer right away, set the pending setting flags
m_PendingSettingUpdateFlags = UpdatedSettingFlags;
//fire up a timer for later re-try
hr = (GetApp()->GetTimers()).AddTimer(
sc_RetryTimeout,
static_cast<ITimerHandler_t*>(this),
&m_RetryTimerIdentifier
);
if (FAILED(hr))
{
return E_FAIL;
}
return S_FALSE;
case WAIT_FAILED:
//fall through to the WAIT_TIME out case
hr = CommonUtilities_t::GetErrorFromWin32();
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at waitting for VoIP Settings mutex, hr = 0x%x", hr));
return hr;
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
GotMutex = true;
break;
default:
ASSERT(FALSE); //not possible got here
return E_FAIL;
}
}
// Duplicate the file with the new settings for DialPlan
if (UpdatedSettingFlags & SEF_VOIP_DIALPLAN)
{
WCHAR FileName[MAX_PATH] = L"";
hr = GetSettingFileName(
m_pActiveFilePrefix,
sc_VoIPSettings[SettingTypeDialPlan].pSettingName,
FileName,
ARRAYSIZE(FileName)
);
if (SUCCEEDED(hr))
{
//set the dialplan file to NORMAL attribute so that it can be re-written
SetFileAttributes(sc_DialPlanFile, FILE_ATTRIBUTE_NORMAL);
//copy the dial plan file from provision location
if (!CopyFile(FileName, sc_DialPlanFile, FALSE))
{
hr = CommonUtilities_t::GetErrorFromWin32();
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at copying data, hr = 0x%x", hr));
}
}
if (FAILED(hr))
{
//if error happens during copy, wipe out the old dial plan and continue with other settings
DeleteFile(sc_DialPlanFile);
}
}
//we got the mutx, now go through the setting handler list to notify each handler
//Note: there might be a chance that when a setting handler handles the setting change, it will
//trigger another setting handlers to unregister/register itself to this list. for example,
//when ConnectionManager_t handles the network prefereence setting change, it will most likely to
//trigger the DialEngine_t and VoIPPhoneCanvas_t register/unregister themselve to this list.
//But in this scenario we are safe here, because
// 1: ConnectionManager_t will always be there in the list and always be the first one
// 2: after DialEngine_t and VoIPPhoneCanvas_t register/unregister themselves to the list, the iteraotr
// will get adjusted as well, so we don't have to worry about a invalid iterator.
// 3: None of the setting handlers will unregister itself when it handles its setting flags
for (HandlerList_t::iterator SettingHandlerMapping = m_HandlerList.begin();
SettingHandlerMapping != m_HandlerList.end(); SettingHandlerMapping++)
{
//notify the setting handler if setting flag matches
if (UpdatedSettingFlags & ((*SettingHandlerMapping).SettingFlags))
{
((*SettingHandlerMapping).pSettingChangeHandler)->OnSettingsChange(UpdatedSettingFlags);
}
}
//release the mutex
if (GotMutex)
{
ReleaseMutex(m_VoIPSettingMutex);
}
return S_OK;
}
/*------------------------------------------------------------------------------
Settings_t::RegisterHandler
Register a setting handler
Parameters:
SettingFlags: [in] the DWORD of the setting flags
pSettingHandler: [in] the pointer to the ISettingChangeHandler_t interface
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::RegisterHandler(
DWORD SettingFlags,
ISettingChangeHandler_t* pSettingHandler
)
{
ASSERT(pSettingHandler != NULL);
//if we don't find one existed, we need to add a new one!
SettingHandlerMapping_t NewHandlerMapping = {SettingFlags, pSettingHandler};
//always push the new handler at the end of the handler list
if (! m_HandlerList.push_back(NewHandlerMapping))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"OOM - could not push the new call onto the call list"));
return E_OUTOFMEMORY;
}
return S_OK;
}
/*------------------------------------------------------------------------------
Settings_t::UnregisterHandler
Unregister a setting handler that used to handle certain setting flags
Parameters:
pSettingHandler: [in] the pointer of the ISettingChangeHandler_t object
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::UnregisterHandler(
ISettingChangeHandler_t* pSettingHandler
)
{
ASSERT(pSettingHandler != NULL);
for (HandlerList_t::iterator SettingHandlerMapping = m_HandlerList.begin();
SettingHandlerMapping != m_HandlerList.end(); SettingHandlerMapping ++)
{
if ((*SettingHandlerMapping).pSettingChangeHandler == pSettingHandler)
{
m_HandlerList.erase(SettingHandlerMapping);
return S_OK;
}
}
return E_INVALIDARG;
}
/*------------------------------------------------------------------------------
Settings_t::GetUpdatedVoIPSettingFlags
Find out what VoIP setting flags have been updated
Parameters: None
Returns: DWORD that specify what VoIP Setting flag have been updated
------------------------------------------------------------------------------*/
DWORD
Settings_t::GetUpdatedVoIPSettingFlags(
void
)
{
struct VSF_SEF_Mapping
{
DWORD VSF_FLAG;
DWORD SEF_FLAG;
};
//mapping array between VSF_ flags to SEF_ flags
static struct VSF_SEF_Mapping VSF_SEF_Array[] =
{
{VOIP_SIP_SETTINGS_BITMASK, SEF_VOIP_SIP_SETTINGS},
{VOIP_VOICEMAIL_SETTINGS_BITMASK, SEF_VOIP_VOICEMAIL_SETTINGS},
{VOIP_VOICEMAIL_NUMBER_BITMASK, SEF_VOIP_VOICEMAIL_NUMBER},
{VOIP_BACKUP_SIP_SETTINGS_BITMASK, SEF_VOIP_BACKUP_SIP_SETTINGS},
{VOIP_DIALPLAN_BITMASK, SEF_VOIP_DIALPLAN},
};
DWORD UpdatedSettings = 0;
DWORD UpdatedVoIPSettingFlags = 0;
HRESULT hr = RegistryGetDWORD(
SN_VOIP_UPDATEDSETTINGS_ROOT,
SN_VOIP_UPDATEDSETTINGS_PATH,
SN_VOIP_UPDATEDSETTINGS_VALUE,
&UpdatedSettings
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at getting statstore data, hr =0x%x", hr));
goto exit;
}
//adjust the registry key name and file prefix for current 'active' settings
if (UpdatedSettings & VOIP_UPDATEDSETTINGS_ACTIVEREG_BITMASK)
{
m_pActiveFilePrefix = Settings_t::sc_SettingFilePrefix1;
m_pActiveRegKeyName = REG_szSecurityVoIPPhoneSetting_ProvisioningKey1;
}
else
{
//otherwise, set it to default value
m_pActiveFilePrefix = Settings_t::sc_SettingFilePrefix0;
m_pActiveRegKeyName = REG_szSecurityVoIPPhoneSetting_ProvisioningKey0;
}
//map the flags from VSF_ to SEF_
for (int Index = 0; Index < ARRAYSIZE(VSF_SEF_Array); Index ++)
{
if (UpdatedSettings & VSF_SEF_Array[Index].VSF_FLAG)
{
UpdatedVoIPSettingFlags |= VSF_SEF_Array[Index].SEF_FLAG;
}
}
exit:
return UpdatedVoIPSettingFlags;
}
/*------------------------------------------------------------------------------
Settings_t::InitializeActiveRegKeyNameAndFilePrefix
query the statstore flag SDID_VOIP_UPDATEDSETTINGS to initialize active reg sub key name
and active file namre prefix, so that we know where we should read data from
Parameters:
none
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::InitializeActiveRegKeyNameAndFilePrefix(
void
)
{
DWORD UpdatedSettings;
HRESULT hr = RegistryGetDWORD(
SN_VOIP_UPDATEDSETTINGS_ROOT,
SN_VOIP_UPDATEDSETTINGS_PATH,
SN_VOIP_UPDATEDSETTINGS_VALUE,
&UpdatedSettings
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at getting statstore data, hr =0x%x", hr));
UpdatedSettings = 0;
}
//check out the registry key name and file prefix for current 'active' settings
if (UpdatedSettings & VOIP_UPDATEDSETTINGS_ACTIVEREG_BITMASK)
{
m_pActiveFilePrefix = Settings_t::sc_SettingFilePrefix1;
m_pActiveRegKeyName = REG_szSecurityVoIPPhoneSetting_ProvisioningKey1;
}
else
{
//otherwise, set it to default value, this includes the scenario that
//the statstore value is not there yet
m_pActiveFilePrefix = Settings_t::sc_SettingFilePrefix0;
m_pActiveRegKeyName = REG_szSecurityVoIPPhoneSetting_ProvisioningKey0;
}
return S_OK;
}
/*------------------------------------------------------------------------------
Settings_t::GetRegistrationProfile
Get the main registry RTC profile
Parameters:
SIPSettingsType: [in] indicates this is a Main SIP server or Backup SIP server
ppRegistrationProfile: [out] pointer to a pointer which points the a IRTCProfile object
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::GetRegistrationProfile(
SettingType_e SIPSettingsType,
__deref_out_opt IRTCProfile** ppRegistrationProfile
)
{
ASSERT(ppRegistrationProfile != NULL);
if ((SIPSettingsType != SettingTypeSIPSettings) && (SIPSettingsType != SettingTypeBackupSIPSettings))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -