📄 settings.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 "Settings.hpp"
#include "Common.hpp"
#include "CommonFunctions.hpp" //for common functions
#include <Wincrypt.h> //for DPAPI
#include <auto_xxx.hxx> //for auto_bstr, auto_hfile, auto_hfine etc
#include "VoIPApp.hpp"
#include "VoIPNotify.hpp"
#include "Debug.hpp"
#include "DatabaseAPI.hpp"
Setting_t::Setting_t(
HKEY RootKey,
const WCHAR* c_pSubKey,
const WCHAR* c_pValueName
)
{
if (
(RootKey == NULL) ||
(c_pSubKey == NULL) || (c_pSubKey[0] == NULL) ||
(c_pValueName == NULL) || (c_pValueName[0] == NULL)
)
{
ASSERT(FALSE);
}
m_NotifyHandle = NULL;
m_RootKey = RootKey;
if (
!m_SubKey.assign(c_pSubKey) ||
!m_ValueName.assign(c_pValueName)
)
{
ASSERT(FALSE);
}
}
Setting_t::~Setting_t(
void
)
{
if (m_NotifyHandle != NULL)
{
HRESULT hr = RegistryCloseNotification(
m_NotifyHandle
);
if (FAILED(hr))
{
ASSERT(FALSE);
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at closing the registry notification, error = 0x%x", hr));
}
}
}
HRESULT
Setting_t::RegisterForNotification(
HWND WindowHandle,
UINT Message,
DWORD UserData
)
{
if (WindowHandle == NULL)
{
return E_INVALIDARG;
}
return RegistryNotifyWindow(
m_RootKey,
m_SubKey,
m_ValueName,
WindowHandle,
Message,
UserData,
NULL,
&m_NotifyHandle
);
}
StringSetting_t::StringSetting_t(
HKEY RootKey,
const WCHAR* c_pSubKey,
const WCHAR* c_pValueName,
const WCHAR* pDefaultValue
) : Setting_t(RootKey, c_pSubKey, c_pValueName)
{
if ((pDefaultValue != NULL) &&
(pDefaultValue[0] != NULL))
{
if (!m_DefaultValue.assign(pDefaultValue))
{
ASSERT(FALSE);
}
}
Update();
}
HRESULT
StringSetting_t::Update(
void
)
{
WCHAR Value[MAX_PATH] = L"";
HRESULT hr = RegistryGetString(
m_RootKey,
m_SubKey,
m_ValueName,
Value,
ARRAYSIZE(Value)
);
if (FAILED(hr))
{
if (!m_SettingValue.assign(m_DefaultValue))
{
return E_OUTOFMEMORY;
}
return hr;
}
if (!m_SettingValue.assign(Value))
{
return E_OUTOFMEMORY;
}
return hr;
}
IntegerSetting_t::IntegerSetting_t(
HKEY RootKey,
const WCHAR* c_pSubKey,
const WCHAR* c_pValueName,
DWORD DefaultValue
) : Setting_t(RootKey, c_pSubKey, c_pValueName)
{
m_DefaultValue = (DefaultValue == -1) ? 0 : DefaultValue;
Update();
}
HRESULT
IntegerSetting_t::Update(
void
)
{
HRESULT hr = RegistryGetDWORD(
m_RootKey,
m_SubKey,
m_ValueName,
&m_SettingValue
);
if (FAILED(hr))
{
m_SettingValue = m_DefaultValue;
}
return hr;
}
///TODO: Need to consolidate those constants with Provision classes
#define REG_szSecurityVoIPPhoneSetting_ProvisioningKey0 TEXT("Security\\Phone\\VoIP\\Provisioning0")
#define REG_szSecurityVoIPPhoneSetting_ProvisioningKey1 TEXT("Security\\Phone\\VoIP\\Provisioning1")
#define WM_CHANGE_PROVISION_SETTINGS (WM_USER + 1)
#define WM_CHANGE_PHONE_SETTINGS (WM_USER + 2)
//public static constants, they are shared by both VoIPCSP_t and Settings_t
const Settings_t::VoIPSetting Settings_t::sc_VoIPSettings[] =
{
{SettingTypeSIPSettings, L"SIPSettings", true, StorageTypeFile, VOIP_SIP_SETTINGS_BITMASK, L"SIPSettings"},
{SettingTypeVoicemailSettings, L"VoicemailSettings", true, StorageTypeFile, VOIP_VOICEMAIL_SETTINGS_BITMASK, L"VoicemailSettings"},
{SettingTypeVoicemailNumber, L"VoicemailNumber", false, StorageTypeRegistry,VOIP_VOICEMAIL_NUMBER_BITMASK, L"VoicemailNumber"},
{SettingTypeBackupSIPSettings, L"BackupSIPSettings", true, StorageTypeFile, VOIP_BACKUP_SIP_SETTINGS_BITMASK, L"BackupSIPSettings"},
{SettingTypeDialPlan, L"DialPlan", false, StorageTypeFile, VOIP_DIALPLAN_BITMASK, L"DialPlan"},
};
const int Settings_t::sc_NumberOfVoIPSettings = ARRAYSIZE(Settings_t::sc_VoIPSettings);
//the 'SYSTEM/' prefix prevents untrusted applications from creating/opening this mutex.
const WCHAR Settings_t::sc_VoIPSettingsMutexName[] = L"SYSTEM/VoIPSettingsMutex";
const UINT Settings_t::sc_RetryTimeout = 60 * 1000; // time out value for re-try: 1 min
const WCHAR Settings_t::sc_SettingFilePrefix0[] = L"\\windows\\VoIP\\Prov0";
const WCHAR Settings_t::sc_SettingFilePrefix1[] = L"\\windows\\VoIP\\Prov1";
const WCHAR Settings_t::sc_SettingFileDirectory[] = L"\\windows\\VoIP\\";
const WCHAR Settings_t::sc_DialPlanFile[] = L"\\windows\\VoIP\\DialPlan";
//private static constants
const WCHAR Settings_t::sc_ListenerWindowClassName[] = L"VoIPSettingManagerListener";
const WCHAR Settings_t::sc_DefaultRingTone[] = L"\\Windows\\ring.wav";
StringSetting_t
Settings_t::s_ForwardingNumber(
SN_VOIP_FORWARDINGNUMBER_ROOT,
SN_VOIP_FORWARDINGNUMBER_PATH,
SN_VOIP_FORWARDINGNUMBER_VALUE
);
const UINT Settings_t::s_dwGenerateKeydown = 100;
const UINT Settings_t::s_msPressAndHold = 100;
const UINT Settings_t::s_msInactivityTimeout = 180000; // 3 mins
Setting_t* Settings_t::s_PhoneSettings[] =
{
&Settings_t::s_ForwardingNumber,
};
/*------------------------------------------------------------------------------
LoadXMLIntoBSTR
helper function to load an XML file to a BSTR
NOTE: copy from private\apps\tpcutil\settings.cpp
this function will go away after we have the bootstrapping xml file in place
------------------------------------------------------------------------------*/
HRESULT LoadXMLIntoBSTR(
HANDLE hFile,
__deref_out_opt BSTR* pbstrOutput
)
{
HRESULT hr = S_OK;
LPSTR pszLoadedData = NULL;
DWORD dwFileSize = 0;
DWORD dwRead = 0;
DWORD dwBSTRLen = 0;
BSTR bstrText = NULL;
ASSERT(hFile != INVALID_HANDLE_VALUE);
ASSERT(pbstrOutput != NULL);
dwFileSize = GetFileSize(hFile, NULL);
if (0xFFFFFFFF == dwFileSize)
{
hr = CommonUtilities_t::GetErrorFromWin32();
goto Error;
}
// Allocate return buffer, allowing space for the NUL terminator
pszLoadedData = (LPSTR)LocalAlloc(LMEM_FIXED, dwFileSize+1);
if (!pszLoadedData)
{
hr = E_OUTOFMEMORY;
goto Error;
}
if (!ReadFile(hFile, pszLoadedData, dwFileSize, &dwRead, 0))
{
hr = CommonUtilities_t::GetErrorFromWin32();
goto Error;
}
if (dwRead != dwFileSize)
{
ASSERT(0);
hr = E_FAIL;
goto Error;
}
// NULL terminate the input file
pszLoadedData[dwFileSize] = '\0';
dwBSTRLen = MultiByteToWideChar(CP_UTF8, 0, pszLoadedData, -1, NULL, 0);
if (dwBSTRLen == 0)
{
hr = E_FAIL;
goto Error;
}
bstrText = SysAllocStringLen(NULL, dwBSTRLen);
if (!bstrText)
{
hr = E_OUTOFMEMORY;
goto Error;
}
if (dwBSTRLen != (DWORD)MultiByteToWideChar(CP_UTF8, 0, pszLoadedData, -1, bstrText, dwBSTRLen + 1))
{
hr = E_FAIL;
goto Error;
}
// Hand off memory
*pbstrOutput = bstrText;
bstrText = NULL;
Error:
if (pszLoadedData)
{
LocalFree(pszLoadedData);
}
if (bstrText != NULL)
{
SysFreeString(bstrText);
}
return hr;
}
/*------------------------------------------------------------------------------
Settings_t::Settings_t
constructor
------------------------------------------------------------------------------*/
Settings_t::Settings_t() :
m_ListenerWindow(NULL),
m_pActiveRegKeyName(NULL),
m_pActiveFilePrefix(NULL),
m_VoIPSettingMutex(INVALID_HANDLE_VALUE),
m_RetryTimerIdentifier(0),
m_PendingSettingUpdateFlags(SEF_NONE)
{
;
}
/*------------------------------------------------------------------------------
Settings_t::~Settings_t
destructor
------------------------------------------------------------------------------*/
Settings_t::~Settings_t()
{
if (m_HandlerList.size() != 0)
{
m_HandlerList.clear();
}
if (m_ListenerWindow)
{
DestroyWindow(m_ListenerWindow);
m_ListenerWindow = NULL;
}
if (m_NotifyHandleForProvisionSettings)
{
RegistryCloseNotification(m_NotifyHandleForProvisionSettings);
}
//clean up the mutex handle
if (m_VoIPSettingMutex != NULL)
{
//close the mutex handle
CloseHandle(m_VoIPSettingMutex);
m_VoIPSettingMutex = INVALID_HANDLE_VALUE;
}
UnregisterClass(sc_ListenerWindowClassName, GlobalData_t::s_ModuleInstance);
}
/*------------------------------------------------------------------------------
Settings_t::Initialize
initializes the Settings_t object
Parameters:
pVoIPPhoneCanvas: [IN] the pointer to the VoIPPhoneCanvas_t object
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::Initialize(
void
)
{
HRESULT hr = S_OK;
//open the mutex first, if it failed, bail out
m_VoIPSettingMutex = CreateMutex(
NULL,
false,
sc_VoIPSettingsMutexName
);
if (m_VoIPSettingMutex == NULL)
{
hr = CommonUtilities_t::GetErrorFromWin32();
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Failed at creating/opening the VoIP settings mutex, hr =0x%x", hr));
return hr;
}
//register the listener window class
WNDCLASS WindowClass = {0};
WindowClass.lpfnWndProc = s_ListenerWindowProc;
WindowClass.hInstance = GlobalData_t::s_ModuleInstance;
WindowClass.lpszClassName = sc_ListenerWindowClassName;
//it's ok if our class already exists...
if (! RegisterClass(&WindowClass))
{
int LastError = GetLastError();
if (LastError != ERROR_CLASS_ALREADY_EXISTS)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not register Listener window class - LastError=%08X", LastError));
return CommonUtilities_t::GetErrorFromWin32();
}
}
//create the notification window and pack our 'this' pointer into the CREATESTRUCT
m_ListenerWindow = CreateWindow(
sc_ListenerWindowClassName,
NULL,
0,
0,
0,
0,
0,
NULL,
NULL,
GlobalData_t::s_ModuleInstance,
reinterpret_cast<VOID*>(this)
);
if (m_ListenerWindow == NULL)
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not create the listener window - LastError=%08X", GetLastError()));
return CommonUtilities_t::GetErrorFromWin32();
}
//initialize the active reg key name and file name prefix
hr = InitializeActiveRegKeyNameAndFilePrefix();
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"could not initialize the active regkey name and file prefix, hr = 0x%x", hr));
}
return hr;
}
/*------------------------------------------------------------------------------
Settings_t::StartListening
Star to listen the stat store setting changes
Parameters:
none
Returns: S_OK indicates success, otherwise failed
------------------------------------------------------------------------------*/
HRESULT
Settings_t::StartListening(
void
)
{
///TODO: consider encapusulate the provision settings into another Setting_t class
HRESULT hr = RegistryNotifyWindow(
SN_VOIP_UPDATEDSETTINGS_ROOT,
SN_VOIP_UPDATEDSETTINGS_PATH,
SN_VOIP_UPDATEDSETTINGS_VALUE,
m_ListenerWindow,
WM_CHANGE_PROVISION_SETTINGS,
0,
NULL,
&m_NotifyHandleForProvisionSettings
);
if (FAILED(hr))
{
PHONEAPP_DEBUGMSG(ZONE_PHONEAPP_ERROR, (L"Could not register callback for StatStore notifications"));
return hr;
}
for (int Index = 0; Index < ARRAYSIZE(s_PhoneSettings); Index ++)
{
hr = s_PhoneSettings[Index]->RegisterForNotification(
m_ListenerWindow,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -