|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/
/*
Servpp.h Server properties implementation file
FILE HISTORY: */
#include "stdafx.h"
#include "Servpp.h"
#include "server.h"
#include "service.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
const DWORD c_dwChangableFlagMask = TAPISERVERCONFIGFLAGS_ENABLESERVER | TAPISERVERCONFIGFLAGS_SETACCOUNT | TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
const TCHAR szPasswordNull[] = _T(" "); // Empty password
BOOL IsLocalSystemAccount(LPCTSTR pszAccount) { BOOL bRet = FALSE; DWORD dwSidSize = 128; DWORD dwDomainNameSize = 128; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID pLocalSid = NULL; PSID pLocalServiceSid = NULL; PSID pNetworkServiceSid = NULL; PSID accountSid = NULL; SID_NAME_USE SidType; LPWSTR pwszDomainName;
do { // Attempt to allocate a buffer for the SID. Note that apparently in the
// absence of any error theData->m_Sid is freed only when theData goes
// out of scope.
accountSid = LocalAlloc( LMEM_FIXED, dwSidSize ); pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
// Was space allocated for the SID and domain name successfully?
if ( accountSid == NULL || pwszDomainName == NULL ) { if ( accountSid != NULL ) { LocalFree( accountSid ); accountSid = NULL; }
if ( pwszDomainName != NULL ) { LocalFree( pwszDomainName ); }
goto ExitHere; }
// Attempt to Retrieve the SID and domain name. If LookupAccountName failes
// because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
// will be set correctly for the next attempt.
if (LookupAccountName (NULL, pszAccount, accountSid, &dwSidSize, pwszDomainName, &dwDomainNameSize, &SidType )) { break; }
if (ERROR_INSUFFICIENT_BUFFER != GetLastError ()) { goto ExitHere; }
// domain name isn't needed at any time
LocalFree (pwszDomainName); LocalFree (accountSid);
} while ( TRUE );
if (!AllocateAndInitializeSid ( &NtAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pLocalSid) || !AllocateAndInitializeSid ( &NtAuthority, 1, SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pLocalServiceSid) || !AllocateAndInitializeSid ( &NtAuthority, 1, SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, &pNetworkServiceSid) ) { goto ExitHere; }
if (EqualSid(pLocalSid, accountSid) || EqualSid(pLocalServiceSid, accountSid) || EqualSid(pNetworkServiceSid, accountSid)) { bRet = TRUE; }
ExitHere:
if (NULL != pwszDomainName) { LocalFree (pwszDomainName); }
if (NULL != accountSid) { LocalFree (accountSid); }
if (NULL != pLocalSid) { FreeSid(pLocalSid); } if (NULL != pLocalServiceSid) { FreeSid (pLocalServiceSid); } if (NULL != pNetworkServiceSid) { FreeSid (pNetworkServiceSid); }
return bRet; }
/////////////////////////////////////////////////////////////////////////////
//
// CServerProperties holder
//
/////////////////////////////////////////////////////////////////////////////
CServerProperties::CServerProperties ( ITFSNode * pNode, IComponentData * pComponentData, ITFSComponentData * pTFSCompData, ITapiInfo * pTapiInfo, LPCTSTR pszSheetName, BOOL fTapiInfoLoaded ) : CPropertyPageHolderBase(pNode, pComponentData, pszSheetName), m_fTapiInfoLoaded(fTapiInfoLoaded) { //ASSERT(pFolderNode == GetContainerNode());
m_bAutoDeletePages = FALSE; // we have the pages as embedded members
AddPageToList((CPropertyPageBase*) &m_pageSetup); AddPageToList((CPropertyPageBase*) &m_pageRefresh);
Assert(pTFSCompData != NULL); m_spTFSCompData.Set(pTFSCompData); m_spTapiInfo.Set(pTapiInfo);
m_hScManager = NULL; m_paQSC = NULL;
m_pszServiceName = TAPI_SERVICE_NAME;
}
CServerProperties::~CServerProperties() { // Close the service control manager database
if (m_hScManager != NULL) { (void)::CloseServiceHandle(m_hScManager); }
// Free the allocated pointers
if (m_paQSC) delete m_paQSC; RemovePageFromList((CPropertyPageBase*) &m_pageSetup, FALSE); RemovePageFromList((CPropertyPageBase*) &m_pageRefresh, FALSE); }
BOOL CServerProperties::FInit() { // get the service account information here
SC_HANDLE hService = NULL; DWORD cbBytesNeeded = 0; BOOL fSuccess = TRUE; BOOL f; DWORD dwErr;
m_uFlags = 0;
if (!FOpenScManager()) { // Unable to open service control database
return FALSE; }
/*
** Open service with querying access-control */ hService = ::OpenService(m_hScManager, m_pszServiceName, SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG); if (hService == NULL) { TapiMessageBox(::GetLastError()); return FALSE; }
/*
** Query the service status */ Trace1("# QueryServiceStatus(%s)...\n", m_pszServiceName); f = ::QueryServiceStatus(hService, OUT &m_SS); if (f) { //m_uFlags |= mskfValidSS;
} else { ::TapiMessageBox(::GetLastError()); fSuccess = FALSE; }
/*
** Query the service config */ Trace1("# QueryServiceConfig(%s)...\n", m_pszServiceName); f = ::QueryServiceConfig(hService, NULL, 0, OUT &cbBytesNeeded); // Compute how many bytes we need to allocate
cbBytesNeeded += 100; // Add extra bytes (just in case)
delete m_paQSC; // Free previously allocated memory (if any)
m_paQSC = (QUERY_SERVICE_CONFIG *) new BYTE[cbBytesNeeded]; f = ::QueryServiceConfig(hService, OUT m_paQSC, cbBytesNeeded, OUT &cbBytesNeeded); if (f) { m_strServiceDisplayName = m_paQSC->lpDisplayName; m_strLogOnAccountName = m_paQSC->lpServiceStartName; } else { ::TapiMessageBox(::GetLastError()); fSuccess = FALSE; }
VERIFY(::CloseServiceHandle(hService)); return fSuccess; }
/////////////////////////////////////////////////////////////////////
// FOpenScManager()
//
// Open the service control manager database (if not already opened).
// The idea for such a function is to recover from a broken connection.
//
// Return TRUE if the service control database was opened successfully,
// othersise false.
//
BOOL CServerProperties::FOpenScManager() { if (m_hScManager == NULL) { m_hScManager = ::OpenSCManager(m_strMachineName, NULL, SC_MANAGER_CONNECT); } if (m_hScManager == NULL) { TapiMessageBox(::GetLastError()); return FALSE; } return TRUE; } // CServicePropertyData::FOpenScManager()
BOOL CServerProperties::FUpdateServiceInfo(LPCTSTR pszName, LPCTSTR pszPassword, DWORD dwStartType) { SC_HANDLE hService = NULL; BOOL fSuccess = TRUE; BOOL f; DWORD dwServiceType = 0;
Trace1("INFO: Updating data for service %s...\n", (LPCTSTR)m_pszServiceName); // Re-open service control manager (in case it was closed)
if (!FOpenScManager()) { return FALSE; }
/*
** Open service with write access ** ** CODEWORK Could provide a more specific error message ** if SERVICE_CHANGE_CONFIG is available but not SERVICE_START */ hService = ::OpenService(m_hScManager, m_pszServiceName, SERVICE_CHANGE_CONFIG); if (hService == NULL) { TapiMessageBox(::GetLastError()); return FALSE; }
Trace1("# ChangeServiceConfig(%s)...\n", m_pszServiceName); if (pszName) { if (IsLocalSystemAccount(pszName)) { pszPassword = szPasswordNull; } dwServiceType = m_paQSC->dwServiceType & ~SERVICE_INTERACTIVE_PROCESS; } else { dwServiceType = SERVICE_NO_CHANGE; }
f = ::ChangeServiceConfig(hService, // Handle to service
dwServiceType, // Type of service
dwStartType, // When/How to start service
SERVICE_NO_CHANGE, // dwErrorControl - severity if service fails to start
NULL, // Pointer to service binary file name
NULL, // lpLoadOrderGroup - pointer to load ordering group name
NULL, // lpdwTagId - pointer to variable to get tag identifier
NULL, // lpDependencies - pointer to array of dependency names
pszName, // Pointer to account name of service
pszPassword, // Pointer to password for service account
m_strServiceDisplayName); if (!f) { DWORD dwErr = ::GetLastError(); Assert(dwErr != ERROR_SUCCESS); Trace2("ERR: ChangeServiceConfig(%s) failed. err= %u.\n", m_pszServiceName, dwErr); TapiMessageBox(dwErr); fSuccess = FALSE; } else { m_strLogOnAccountName = pszName;
// if pszName is null, we aren't changing the account info, so don't check
// the logon as service info
if (pszName && !IsLocalSystemAccount(pszName)) { /*
** Make sure there is an LSA account with POLICY_MODE_SERVICE privilege ** This function reports its own errors, failure is only advisory */ FCheckLSAAccount(); } }
VERIFY(::CloseServiceHandle(hService));
return fSuccess; }
//Check if the user has the write access on service config info
BOOL CServerProperties::FHasServiceControl() { BOOL fRet = FALSE;
if (FIsTapiInfoLoaded()) { fRet = m_spTapiInfo->FHasServiceControl(); } else { if (!FOpenScManager()) { fRet = FALSE; } else { SC_HANDLE hService = NULL;
hService = ::OpenService(m_hScManager, m_pszServiceName, SERVICE_CHANGE_CONFIG);
fRet = (hService != NULL); if (hService) { VERIFY(::CloseServiceHandle(hService)); } } }
return fRet; }
/////////////////////////////////////////////////////////////////////////////
// CServerPropRefresh property page
IMPLEMENT_DYNCREATE(CServerPropRefresh, CPropertyPageBase)
CServerPropRefresh::CServerPropRefresh() : CPropertyPageBase(CServerPropRefresh::IDD) { //{{AFX_DATA_INIT(CServerPropRefresh)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
CServerPropRefresh::~CServerPropRefresh() { }
void CServerPropRefresh::DoDataExchange(CDataExchange* pDX) { CPropertyPageBase::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServerPropRefresh)
DDX_Control(pDX, IDC_EDIT_MINUTES, m_editMinutes); DDX_Control(pDX, IDC_EDIT_HOURS, m_editHours); DDX_Control(pDX, IDC_SPIN_MINUTES, m_spinMinutes); DDX_Control(pDX, IDC_SPIN_HOURS, m_spinHours); DDX_Control(pDX, IDC_CHECK_ENABLE_STATS, m_checkEnableStats); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServerPropRefresh, CPropertyPageBase) //{{AFX_MSG_MAP(CServerPropRefresh)
ON_BN_CLICKED(IDC_CHECK_ENABLE_STATS, OnCheckEnableStats) ON_EN_KILLFOCUS(IDC_EDIT_HOURS, OnKillfocusEditHours) ON_EN_KILLFOCUS(IDC_EDIT_MINUTES, OnKillfocusEditMinutes) ON_EN_CHANGE(IDC_EDIT_HOURS, OnChangeEditHours) ON_EN_CHANGE(IDC_EDIT_MINUTES, OnChangeEditMinutes) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerPropRefresh message handlers
BOOL CServerPropRefresh::OnInitDialog() { CPropertyPageBase::OnInitDialog(); m_spinHours.SetRange(0, AUTO_REFRESH_HOURS_MAX); m_spinMinutes.SetRange(0, AUTO_REFRESH_MINUTES_MAX);
m_checkEnableStats.SetCheck(m_bAutoRefresh);
// update the refresh interval
int nHours, nMinutes; DWORD dwRefreshInterval = m_dwRefreshInterval;
nHours = dwRefreshInterval / MILLISEC_PER_HOUR; dwRefreshInterval -= nHours * MILLISEC_PER_HOUR;
nMinutes = dwRefreshInterval / MILLISEC_PER_MINUTE; dwRefreshInterval -= nMinutes * MILLISEC_PER_MINUTE;
m_spinHours.SetPos(nHours); m_spinMinutes.SetPos(nMinutes);
m_editHours.LimitText(2); m_editMinutes.LimitText(2);
// set the button states
UpdateButtons();
SetDirty(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CServerPropRefresh::UpdateButtons() { int nCheck = m_checkEnableStats.GetCheck();
GetDlgItem(IDC_EDIT_HOURS)->EnableWindow(nCheck != 0); GetDlgItem(IDC_EDIT_MINUTES)->EnableWindow(nCheck != 0);
GetDlgItem(IDC_SPIN_HOURS)->EnableWindow(nCheck != 0); GetDlgItem(IDC_SPIN_MINUTES)->EnableWindow(nCheck != 0); }
void CServerPropRefresh::OnCheckEnableStats() { SetDirty(TRUE); UpdateButtons(); }
void CServerPropRefresh::OnKillfocusEditHours() { }
void CServerPropRefresh::OnKillfocusEditMinutes() { }
void CServerPropRefresh::OnChangeEditHours() { ValidateHours(); SetDirty(TRUE); }
void CServerPropRefresh::OnChangeEditMinutes() { ValidateMinutes(); SetDirty(TRUE); }
void CServerPropRefresh::ValidateHours() { CString strValue; int nValue;
if (m_editHours.GetSafeHwnd() != NULL) { m_editHours.GetWindowText(strValue); if (!strValue.IsEmpty()) { nValue = _ttoi(strValue);
if ((nValue >= 0) && (nValue <= AUTO_REFRESH_HOURS_MAX)) { // everything is good
return; }
if (nValue > AUTO_REFRESH_HOURS_MAX) nValue = AUTO_REFRESH_HOURS_MAX; else if (nValue < 0) nValue = 0;
// set the new value and beep
CString strText; LPTSTR pBuf = strText.GetBuffer(5); _itot(nValue, pBuf, 10); strText.ReleaseBuffer();
MessageBeep(MB_ICONEXCLAMATION);
m_editHours.SetWindowText(strText); m_editHours.SetSel(0, -1); m_editHours.SetFocus(); } } }
void CServerPropRefresh::ValidateMinutes() { CString strValue; int nValue;
if (m_editMinutes.GetSafeHwnd() != NULL) { m_editMinutes.GetWindowText(strValue); if (!strValue.IsEmpty()) { nValue = _ttoi(strValue);
if ((nValue >= 0) && (nValue <= AUTO_REFRESH_MINUTES_MAX)) { // everything is good
return; } if (nValue > AUTO_REFRESH_MINUTES_MAX) nValue = AUTO_REFRESH_MINUTES_MAX; else if (nValue < 0) nValue = 0;
CString strText; LPTSTR pBuf = strText.GetBuffer(5); _itot(nValue, pBuf, 10); strText.ReleaseBuffer();
MessageBeep(MB_ICONEXCLAMATION);
m_editMinutes.SetWindowText(strText); m_editMinutes.SetSel(0, -1); m_editMinutes.SetFocus(); } } }
BOOL CServerPropRefresh::OnApply() { if (!IsDirty()) return TRUE;
UpdateData();
m_bAutoRefresh = (m_checkEnableStats.GetCheck() == 1) ? TRUE : FALSE;
int nHours = m_spinHours.GetPos(); int nMinutes = m_spinMinutes.GetPos(); m_dwRefreshInterval = nHours * MILLISEC_PER_HOUR; m_dwRefreshInterval += nMinutes * MILLISEC_PER_MINUTE;
if (m_bAutoRefresh && m_dwRefreshInterval == 0) { CString strMessage; AfxMessageBox(IDS_ERR_AUTO_REFRESH_ZERO); m_editHours.SetSel(0, -1); m_editHours.SetFocus();
return FALSE; } BOOL bRet = CPropertyPageBase::OnApply();
if (bRet == FALSE) { // Something bad happened... grab the error code
AFX_MANAGE_STATE(AfxGetStaticModuleState( )); ::TapiMessageBox(GetHolder()->GetError()); }
return bRet; }
BOOL CServerPropRefresh::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask) { SPITFSNode spNode; CTapiServer * pServer; DWORD dwError;
// do stuff here.
BEGIN_WAIT_CURSOR;
spNode = GetHolder()->GetNode(); pServer = GETHANDLER(CTapiServer, spNode);
pServer->SetAutoRefresh(spNode, m_bAutoRefresh, m_dwRefreshInterval);
SPITFSNodeMgr spNodeMgr; SPITFSNode spRootNode;
spNode->GetNodeMgr(&spNodeMgr); spNodeMgr->GetRootNode(&spRootNode); spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
END_WAIT_CURSOR; return FALSE; }
/////////////////////////////////////////////////////////////////////////////
// CServerPropSetup property page
IMPLEMENT_DYNCREATE(CServerPropSetup, CPropertyPageBase)
CServerPropSetup::CServerPropSetup() : CPropertyPageBase(CServerPropSetup::IDD) { //{{AFX_DATA_INIT(CServerPropSetup)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_dwNewFlags = 0; }
CServerPropSetup::~CServerPropSetup() { }
void CServerPropSetup::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServerPropSetup)
DDX_Control(pDX, IDC_LIST_ADMINS, m_listAdmins); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServerPropSetup, CPropertyPageBase) //{{AFX_MSG_MAP(CServerPropSetup)
ON_BN_CLICKED(IDC_BUTTON_ADD_ADMIN, OnButtonAdd) ON_BN_CLICKED(IDC_BUTTON_CHOOSE_USER, OnButtonChooseUser) ON_BN_CLICKED(IDC_BUTTON_REMOVE_ADMIN, OnButtonRemove) ON_BN_CLICKED(IDC_CHECK_ENABLE_SERVER, OnCheckEnableServer) ON_EN_CHANGE(IDC_EDIT_NAME, OnChangeEditName) ON_EN_CHANGE(IDC_EDIT_PASSWORD, OnChangeEditPassword) ON_LBN_SELCHANGE(IDC_LIST_ADMINS, OnSelchangeListAdmins) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServerPropSetup message handlers
BOOL CServerPropSetup::OnInitDialog() { SPITapiInfo spTapiInfo; CString strName; HRESULT hr = hrOK;
CPropertyPageBase::OnInitDialog();
CServerProperties * pServerProp = (CServerProperties * ) GetHolder(); pServerProp->GetTapiInfo(&spTapiInfo); Assert(spTapiInfo);
BOOL fIsNTS = TRUE;
if (pServerProp->FIsServiceRunning()) { fIsNTS = spTapiInfo->IsServer();
hr = spTapiInfo->GetConfigInfo(&m_tapiConfigInfo); if (FAILED(hr)) { Panic1("ServerPropSetup - GetConfigInfo failed! %x", hr); }
// update the checkbox
((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->SetCheck(spTapiInfo->IsTapiServer());
// now update any TAPI administrators
for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++) { ((CListBox *) GetDlgItem(IDC_LIST_ADMINS))->AddString(m_tapiConfigInfo.m_arrayAdministrators[i].m_strName); } } else { // check to see if the machine is NTS
TFSIsNTServer(pServerProp->m_strMachineName, &fIsNTS); }
if (fIsNTS) { // fill in the username and password
strName = pServerProp->GetServiceAccountName(); GetDlgItem(IDC_EDIT_NAME)->SetWindowText(strName); GetDlgItem(IDC_EDIT_PASSWORD)->SetWindowText(szPasswordNull);
m_dwNewFlags = TAPISERVERCONFIGFLAGS_ISSERVER; } else { m_dwNewFlags = 0; } EnableButtons(fIsNTS);
m_fRestartService = FALSE; m_dwInitFlags = m_tapiConfigInfo.m_dwFlags;
SetDirty(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CServerPropSetup::OnButtonAdd() { CGetUsers getUsers(TRUE);
if (!getUsers.GetUsers(GetSafeHwnd())) return;
for (int nCount = 0; nCount < getUsers.GetSize(); nCount++) { CUserInfo userTemp;
userTemp = getUsers[nCount];
BOOL fDuplicate = FALSE; for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++) { if (m_tapiConfigInfo.m_arrayAdministrators[i].m_strName.CompareNoCase(userTemp.m_strName) == 0) { fDuplicate = TRUE; break; } }
if (!fDuplicate) { // add to the array
int nIndex = (int)m_tapiConfigInfo.m_arrayAdministrators.Add(userTemp);
// now add to the listbox
m_listAdmins.AddString(m_tapiConfigInfo.m_arrayAdministrators[nIndex].m_strName); } else { // tell the user we're not adding this to the list
CString strMessage; AfxFormatString1(strMessage, IDS_ADMIN_ALREADY_IN_LIST, userTemp.m_strName); AfxMessageBox(strMessage); }
SetDirty(TRUE); }
m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
EnableButtons(); }
void CServerPropSetup::OnButtonRemove() { CString strSelectedName; int nCurSel = m_listAdmins.GetCurSel();
m_listAdmins.GetText(nCurSel, strSelectedName);
// remove from the list
for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++) { if (strSelectedName.Compare(m_tapiConfigInfo.m_arrayAdministrators[i].m_strName) == 0) { // found it. remove from the list
m_tapiConfigInfo.m_arrayAdministrators.RemoveAt(i); break; } }
// now remove from the list box
m_listAdmins.DeleteString(nCurSel);
m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
SetDirty(TRUE);
EnableButtons(); }
void CServerPropSetup::OnButtonChooseUser() { CGetUsers getUsers;
if (!getUsers.GetUsers(GetSafeHwnd())) return;
if (0 == getUsers.GetSize()) return;
CUserInfo userTemp;
userTemp = getUsers[0];
GetDlgItem(IDC_EDIT_NAME)->SetWindowText(userTemp.m_strName); m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
SetDirty(TRUE); EnableButtons(); }
void CServerPropSetup::OnCheckEnableServer() { if (((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck()) { m_dwNewFlags |= TAPISERVERCONFIGFLAGS_ENABLESERVER; } else { m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_ENABLESERVER; }
EnableButtons ();
SetDirty(TRUE); }
void CServerPropSetup::OnChangeEditName() { m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
SetDirty(TRUE); }
void CServerPropSetup::OnChangeEditPassword() { m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT; m_fRestartService = TRUE;
SetDirty(TRUE); }
void CServerPropSetup::OnSelchangeListAdmins() { EnableButtons(); }
void CServerPropSetup::EnableButtons(BOOL fIsNtServer) { BOOL fServiceRunning = ((CServerProperties *) GetHolder())->FIsServiceRunning(); //if we are unable to get the write access to tapisrv service, we need to disable
// some controls
BOOL fHasServiceControl = ((CServerProperties *) GetHolder())->FHasServiceControl();
//We enable the admin controls only if we sucessfully loaded the tapi info
BOOL fTapiInfoLoaded = ((CServerProperties *) GetHolder())->FIsTapiInfoLoaded();
BOOL fIsAdmin = ((CServerProperties *) GetHolder())->FIsAdmin();
// if this isn't an NT server, disable all controls
if (!fIsNtServer) fServiceRunning = FALSE; //Enable the Admin controls only if
//(1) the service is running
//(2) successfully loaded the tapi config info
//(3) the user is a machine admin or tapi admin
BOOL fEnableAdminControls = fServiceRunning && fTapiInfoLoaded && fIsAdmin;
// enable the admin controls on
GetDlgItem(IDC_STATIC_ADMINS)->EnableWindow(fEnableAdminControls); GetDlgItem(IDC_STATIC_NOTE)->EnableWindow(fEnableAdminControls); GetDlgItem(IDC_STATIC_LISTBOX)->EnableWindow(fEnableAdminControls); GetDlgItem(IDC_BUTTON_ADD_ADMIN)->EnableWindow(fEnableAdminControls); GetDlgItem(IDC_BUTTON_REMOVE_ADMIN)->EnableWindow(fEnableAdminControls); GetDlgItem(IDC_LIST_ADMINS)->EnableWindow(fEnableAdminControls);
//If the user is not admin, then they don't have ServiceControl write access
//So fHasServiceControl covers fIsAdmin
GetDlgItem(IDC_CHECK_ENABLE_SERVER)->EnableWindow(fServiceRunning && fHasServiceControl && fTapiInfoLoaded); // these should always be available if we have service control access
// and we are running on server
GetDlgItem(IDC_STATIC_USERNAME)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_STATIC_PASSWORD)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_STATIC_ACCOUNT)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_BUTTON_CHOOSE_USER)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_EDIT_NAME)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_EDIT_PASSWORD)->EnableWindow(fIsNtServer && fHasServiceControl); GetDlgItem(IDC_STATIC_ACCOUNT_INFO)->EnableWindow(fIsNtServer && fHasServiceControl);
if (fServiceRunning) {
// enable the remove button if something is selected
BOOL fEnableRemove = m_listAdmins.GetCurSel() != LB_ERR;
//if we will disable the remove button and the remove button has the focus,
//we should change focus to the next control
CWnd * pwndRemove = GetDlgItem(IDC_BUTTON_REMOVE_ADMIN);
if (!fEnableRemove && GetFocus() == pwndRemove) { NextDlgCtrl(); }
pwndRemove->EnableWindow(fEnableRemove); } }
BOOL CServerPropSetup::OnApply() { CString strAccount, strPassword; BOOL fUpdateAccount = FALSE; BOOL fUpdateTapiServer = FALSE; BOOL bRet = TRUE; BOOL bWasServer, bToBeServer; DWORD dwStartType = SERVICE_NO_CHANGE;
if (!IsDirty()) return bRet;
CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
UpdateData();
// Check to see if there is any change on enabling server
// or user account name, that requires service restarting
if (!m_fRestartService) { bWasServer = m_dwInitFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER; bToBeServer = ((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck(); if (bWasServer && !bToBeServer || !bWasServer && bToBeServer) { m_fRestartService = TRUE; } if (m_dwNewFlags & TAPISERVERCONFIGFLAGS_SETACCOUNT) { GetDlgItem(IDC_EDIT_NAME)->GetWindowText(strAccount); if (strAccount.CompareNoCase(pServerProp->GetServiceAccountName()) != 0) { m_fRestartService = TRUE; } else { m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_SETACCOUNT; } } }
// if the account information has changed, the update the info struct now
if (m_dwNewFlags & TAPISERVERCONFIGFLAGS_SETACCOUNT) { GetDlgItem(IDC_EDIT_NAME)->GetWindowText(strAccount); GetDlgItem(IDC_EDIT_PASSWORD)->GetWindowText(strPassword);
// verify that the user is an admin on the machine
if (!IsLocalSystemAccount(strAccount)) { DWORD dwErr; BOOL fIsAdmin; CString strMessage; dwErr = ::IsAdmin(pServerProp->m_strMachineName, strAccount, strPassword, &fIsAdmin);
if (!fIsAdmin) { AfxFormatString1(strMessage, IDS_ERR_USER_NOT_ADMIN, pServerProp->m_strMachineName); AfxMessageBox(strMessage); GetDlgItem(IDC_EDIT_NAME)->SetFocus(); ((CEdit *) GetDlgItem(IDC_EDIT_NAME))->SetSel(0, -1);
return FALSE; } }
// clear the flag so we don't use the TAPI MMC APIs to set this
m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_SETACCOUNT; fUpdateAccount = TRUE; }
// if we are changing the server state or admin stuff then
if (((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck()) { m_dwNewFlags |= TAPISERVERCONFIGFLAGS_ENABLESERVER; }
// only update config information if it has changed
if ((pServerProp->FIsServiceRunning()) && (m_tapiConfigInfo.m_dwFlags != m_dwNewFlags)) { // if we modify the tapi server status then we need to change the
// service statrt type as well.
if ((m_dwNewFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER) && !(m_tapiConfigInfo.m_dwFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER)) { fUpdateTapiServer = TRUE; }
dwStartType = (m_dwNewFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER) ? SERVICE_AUTO_START : SERVICE_DEMAND_START; bRet = CPropertyPageBase::OnApply(); }
if (bRet == FALSE) { // Something bad happened... grab the error code
AFX_MANAGE_STATE(AfxGetStaticModuleState( )); ::TapiMessageBox(WIN32_FROM_HRESULT(GetHolder()->GetError()));
// restore the flag
if (fUpdateAccount) m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT; } else { m_dwNewFlags = TAPISERVERCONFIGFLAGS_ISSERVER;
if (fUpdateAccount || fUpdateTapiServer) { // do the account change
BEGIN_WAIT_CURSOR
LPCTSTR pszAccount = (fUpdateAccount) ? (LPCTSTR) strAccount : NULL; LPCTSTR pszPassword = (fUpdateAccount) ? (LPCTSTR) strPassword : NULL;
bRet = pServerProp->FUpdateServiceInfo(pszAccount, pszPassword, dwStartType); if (bRet) { /*$REVIEW
Tapisrv occupies a seperate house in NT server. It lives with the other services on NT Professional Edition(workstation). We do not need to sperate/merge services anymore. Users should not be allowed to change account information from TAPI MMC on NT workstation(Disabled).
HRESULT hr;
// if the change was successful, update the svc host information
hr = UpdateSvcHostInfo(pServerProp->m_strMachineName, IsLocalSystemAccount(strAccount)); if (FAILED(hr)) { // restore the flag
if (fUpdateAccount) { m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT; }
::TapiMessageBox(WIN32_FROM_HRESULT(hr)); return FALSE; } */ } else if (fUpdateAccount) { // set account failed, so set the flag again.
m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT; }
END_WAIT_CURSOR }
// if everything went OK and we changed something that requires a service restart then
// do ask the user if they want to do it now
if (bRet && m_fRestartService) { CString strText; BOOL fServiceRunning = pServerProp->FIsServiceRunning(); ::TFSIsServiceRunning(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, &fServiceRunning);
if (fServiceRunning) strText.LoadString(IDS_ACCOUNT_CHANGE_RESTART); else strText.LoadString(IDS_ACCOUNT_CHANGE_START);
// Tell the user the service needs to be restarted in order to make the changes
if (AfxMessageBox(strText, MB_YESNO) == IDYES) { if (RestartService() == ERROR_SUCCESS) { m_fRestartService = FALSE; m_dwInitFlags = m_tapiConfigInfo.m_dwFlags; } } } }
if (!bRet) SetDirty(TRUE);
return bRet; }
BOOL CServerPropSetup::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask) { SPITapiInfo spTapiInfo; HRESULT hr = hrOK; BOOL fServiceRunning = TRUE; DWORD dwOldFlags; DWORD dwErr = ERROR_SUCCESS;
CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
pServerProp->GetTapiInfo(&spTapiInfo); Assert(spTapiInfo);
// if the service isn't running, try to start it
//if (!pServerProp->FIsServiceRunning())
dwErr = ::TFSIsServiceRunning(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, &fServiceRunning); if (!fServiceRunning) { // service has stopped from under us. Return an error.
GetHolder()->SetError(HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)); return FALSE; }
// if everything is cool then make the changes
if (dwErr == ERROR_SUCCESS) { dwOldFlags = m_tapiConfigInfo.m_dwFlags;
//clear the changable bits in old flags
m_tapiConfigInfo.m_dwFlags &= ~c_dwChangableFlagMask;
//set the changable bits
m_tapiConfigInfo.m_dwFlags |= (m_dwNewFlags & c_dwChangableFlagMask); hr = spTapiInfo->SetConfigInfo(&m_tapiConfigInfo);
//Bug 276787 We should clear the two write bits
m_tapiConfigInfo.m_dwFlags &= ~(TAPISERVERCONFIGFLAGS_SETACCOUNT | TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS);
if (FAILED(hr)) { GetHolder()->SetError(hr); m_tapiConfigInfo.m_dwFlags = dwOldFlags; } }
return FALSE; }
HRESULT CServerPropSetup::UpdateSvcHostInfo(LPCTSTR pszMachine, BOOL fLocalSystemAccount) { HRESULT hr = hrOK; MULTI_QI qi; SPIRemoteNetworkConfig spRemote; hr = CoInitialize(NULL); if (FAILED(hr)) { return hr; }
if (IsLocalMachine(pszMachine)) { hr = CoCreateInstance(CLSID_RemoteRouterConfig, NULL, CLSCTX_SERVER, IID_IRemoteNetworkConfig, (LPVOID *) &(qi.pItf)); } else { COSERVERINFO csi; qi.pIID = &IID_IRemoteNetworkConfig; qi.pItf = NULL; qi.hr = 0; csi.dwReserved1 = 0; csi.dwReserved2 = 0; csi.pwszName = (LPWSTR) (LPCTSTR) pszMachine; csi.pAuthInfo = NULL; hr = CoCreateInstanceEx(CLSID_RemoteRouterConfig, NULL, CLSCTX_SERVER, &csi, 1, &qi); } Trace1("CServerPropSetup::UpdateSvcHostInfo - CoCreateInstance returned %lx\n", hr);
if (hr == S_OK) { CString strGroup;
strGroup = _T("Tapisrv");
spRemote = (IRemoteNetworkConfig *)qi.pItf; hr = spRemote->SetUserConfig(TAPI_SERVICE_NAME, strGroup); Trace1("CServerPropSetup::UpdateSvcHostInfo - SetUserConfig returned %lx\n", hr); }
CoUninitialize();
return hr; }
DWORD CServerPropSetup::RestartService() { // restart the service if requested
CServerProperties * pServerProp = (CServerProperties * ) GetHolder(); DWORD dwErr = ERROR_SUCCESS; BOOL fRestart = FALSE; SPITapiInfo spTapiInfo; pServerProp->GetTapiInfo(&spTapiInfo);
// gotta clean up before the service stops
spTapiInfo->Destroy();
// any time we stop/start the service we need to call this
::UnloadTapiDll();
// stop the service if it is running
BOOL fServiceRunning = pServerProp->FIsServiceRunning(); ::TFSIsServiceRunning(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, &fServiceRunning);
if (fServiceRunning) { dwErr = ::TFSStopService(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, pServerProp->GetServiceDisplayName()); }
if (dwErr != ERROR_SUCCESS) { CString strText; strText.LoadString(IDS_ERR_SERVICE_NOT_STOPPED); TapiMessageBox(dwErr, MB_OK, strText); }
// start the service
if (dwErr == ERROR_SUCCESS) { dwErr = ::TFSStartService(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, pServerProp->GetServiceDisplayName());
if (dwErr != ERROR_SUCCESS) { CString strText; strText.LoadString(IDS_ERR_SERVICE_NOT_STARTED); TapiMessageBox(dwErr, MB_OK, strText); } }
StartRefresh();
return dwErr; }
void CServerPropSetup::StartRefresh() { // refresh the snapin to reflect the changes
SPITFSNode spNode; CTapiServer * pServer;
spNode = GetHolder()->GetNode(); pServer = GETHANDLER(CTapiServer, spNode);
pServer->OnRefresh(spNode, NULL, 0, 0, 0); }
|