Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1364 lines
38 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. Servpp.h
  7. Server properties implementation file
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "Servpp.h"
  12. #include "server.h"
  13. #include "service.h"
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. const DWORD c_dwChangableFlagMask =
  20. TAPISERVERCONFIGFLAGS_ENABLESERVER |
  21. TAPISERVERCONFIGFLAGS_SETACCOUNT |
  22. TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
  23. const TCHAR szPasswordNull[] = _T(" "); // Empty password
  24. BOOL
  25. IsLocalSystemAccount(LPCTSTR pszAccount)
  26. {
  27. BOOL bRet = FALSE;
  28. DWORD dwSidSize = 128;
  29. DWORD dwDomainNameSize = 128;
  30. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  31. PSID pLocalSid = NULL;
  32. PSID pLocalServiceSid = NULL;
  33. PSID pNetworkServiceSid = NULL;
  34. PSID accountSid = NULL;
  35. SID_NAME_USE SidType;
  36. LPWSTR pwszDomainName;
  37. do
  38. {
  39. // Attempt to allocate a buffer for the SID. Note that apparently in the
  40. // absence of any error theData->m_Sid is freed only when theData goes
  41. // out of scope.
  42. accountSid = LocalAlloc( LMEM_FIXED, dwSidSize );
  43. pwszDomainName = (LPWSTR) LocalAlloc( LMEM_FIXED, dwDomainNameSize * sizeof(WCHAR) );
  44. // Was space allocated for the SID and domain name successfully?
  45. if ( accountSid == NULL || pwszDomainName == NULL )
  46. {
  47. if ( accountSid != NULL )
  48. {
  49. LocalFree( accountSid );
  50. accountSid = NULL;
  51. }
  52. if ( pwszDomainName != NULL )
  53. {
  54. LocalFree( pwszDomainName );
  55. }
  56. goto ExitHere;
  57. }
  58. // Attempt to Retrieve the SID and domain name. If LookupAccountName failes
  59. // because of insufficient buffer size(s) dwSidSize and dwDomainNameSize
  60. // will be set correctly for the next attempt.
  61. if (LookupAccountName (NULL,
  62. pszAccount,
  63. accountSid,
  64. &dwSidSize,
  65. pwszDomainName,
  66. &dwDomainNameSize,
  67. &SidType ))
  68. {
  69. break;
  70. }
  71. if (ERROR_INSUFFICIENT_BUFFER != GetLastError ())
  72. {
  73. goto ExitHere;
  74. }
  75. // domain name isn't needed at any time
  76. LocalFree (pwszDomainName);
  77. LocalFree (accountSid);
  78. } while ( TRUE );
  79. if (!AllocateAndInitializeSid (
  80. &NtAuthority,
  81. 1,
  82. SECURITY_LOCAL_SYSTEM_RID,
  83. 0, 0, 0, 0, 0, 0, 0,
  84. &pLocalSid) ||
  85. !AllocateAndInitializeSid (
  86. &NtAuthority,
  87. 1,
  88. SECURITY_LOCAL_SERVICE_RID,
  89. 0, 0, 0, 0, 0, 0, 0,
  90. &pLocalServiceSid) ||
  91. !AllocateAndInitializeSid (
  92. &NtAuthority,
  93. 1,
  94. SECURITY_NETWORK_SERVICE_RID,
  95. 0, 0, 0, 0, 0, 0, 0,
  96. &pNetworkServiceSid)
  97. )
  98. {
  99. goto ExitHere;
  100. }
  101. if (EqualSid(pLocalSid, accountSid) ||
  102. EqualSid(pLocalServiceSid, accountSid) ||
  103. EqualSid(pNetworkServiceSid, accountSid))
  104. {
  105. bRet = TRUE;
  106. }
  107. ExitHere:
  108. if (NULL != pwszDomainName)
  109. {
  110. LocalFree (pwszDomainName);
  111. }
  112. if (NULL != accountSid)
  113. {
  114. LocalFree (accountSid);
  115. }
  116. if (NULL != pLocalSid)
  117. {
  118. FreeSid(pLocalSid);
  119. }
  120. if (NULL != pLocalServiceSid)
  121. {
  122. FreeSid (pLocalServiceSid);
  123. }
  124. if (NULL != pNetworkServiceSid)
  125. {
  126. FreeSid (pNetworkServiceSid);
  127. }
  128. return bRet;
  129. }
  130. /////////////////////////////////////////////////////////////////////////////
  131. //
  132. // CServerProperties holder
  133. //
  134. /////////////////////////////////////////////////////////////////////////////
  135. CServerProperties::CServerProperties
  136. (
  137. ITFSNode * pNode,
  138. IComponentData * pComponentData,
  139. ITFSComponentData * pTFSCompData,
  140. ITapiInfo * pTapiInfo,
  141. LPCTSTR pszSheetName,
  142. BOOL fTapiInfoLoaded
  143. ) : CPropertyPageHolderBase(pNode, pComponentData, pszSheetName),
  144. m_fTapiInfoLoaded(fTapiInfoLoaded)
  145. {
  146. //ASSERT(pFolderNode == GetContainerNode());
  147. m_bAutoDeletePages = FALSE; // we have the pages as embedded members
  148. AddPageToList((CPropertyPageBase*) &m_pageSetup);
  149. AddPageToList((CPropertyPageBase*) &m_pageRefresh);
  150. Assert(pTFSCompData != NULL);
  151. m_spTFSCompData.Set(pTFSCompData);
  152. m_spTapiInfo.Set(pTapiInfo);
  153. m_hScManager = NULL;
  154. m_paQSC = NULL;
  155. m_pszServiceName = TAPI_SERVICE_NAME;
  156. }
  157. CServerProperties::~CServerProperties()
  158. {
  159. // Close the service control manager database
  160. if (m_hScManager != NULL)
  161. {
  162. (void)::CloseServiceHandle(m_hScManager);
  163. }
  164. // Free the allocated pointers
  165. if (m_paQSC)
  166. delete m_paQSC;
  167. RemovePageFromList((CPropertyPageBase*) &m_pageSetup, FALSE);
  168. RemovePageFromList((CPropertyPageBase*) &m_pageRefresh, FALSE);
  169. }
  170. BOOL
  171. CServerProperties::FInit()
  172. {
  173. // get the service account information here
  174. SC_HANDLE hService = NULL;
  175. DWORD cbBytesNeeded = 0;
  176. BOOL fSuccess = TRUE;
  177. BOOL f;
  178. DWORD dwErr;
  179. m_uFlags = 0;
  180. if (!FOpenScManager())
  181. {
  182. // Unable to open service control database
  183. return FALSE;
  184. }
  185. /*
  186. ** Open service with querying access-control
  187. */
  188. hService = ::OpenService(m_hScManager,
  189. m_pszServiceName,
  190. SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG);
  191. if (hService == NULL)
  192. {
  193. TapiMessageBox(::GetLastError());
  194. return FALSE;
  195. }
  196. /*
  197. ** Query the service status
  198. */
  199. Trace1("# QueryServiceStatus(%s)...\n", m_pszServiceName);
  200. f = ::QueryServiceStatus(hService, OUT &m_SS);
  201. if (f)
  202. {
  203. //m_uFlags |= mskfValidSS;
  204. }
  205. else
  206. {
  207. ::TapiMessageBox(::GetLastError());
  208. fSuccess = FALSE;
  209. }
  210. /*
  211. ** Query the service config
  212. */
  213. Trace1("# QueryServiceConfig(%s)...\n", m_pszServiceName);
  214. f = ::QueryServiceConfig(hService,
  215. NULL,
  216. 0,
  217. OUT &cbBytesNeeded); // Compute how many bytes we need to allocate
  218. cbBytesNeeded += 100; // Add extra bytes (just in case)
  219. delete m_paQSC; // Free previously allocated memory (if any)
  220. m_paQSC = (QUERY_SERVICE_CONFIG *) new BYTE[cbBytesNeeded];
  221. f = ::QueryServiceConfig(hService,
  222. OUT m_paQSC,
  223. cbBytesNeeded,
  224. OUT &cbBytesNeeded);
  225. if (f)
  226. {
  227. m_strServiceDisplayName = m_paQSC->lpDisplayName;
  228. m_strLogOnAccountName = m_paQSC->lpServiceStartName;
  229. }
  230. else
  231. {
  232. ::TapiMessageBox(::GetLastError());
  233. fSuccess = FALSE;
  234. }
  235. VERIFY(::CloseServiceHandle(hService));
  236. return fSuccess;
  237. }
  238. /////////////////////////////////////////////////////////////////////
  239. // FOpenScManager()
  240. //
  241. // Open the service control manager database (if not already opened).
  242. // The idea for such a function is to recover from a broken connection.
  243. //
  244. // Return TRUE if the service control database was opened successfully,
  245. // othersise false.
  246. //
  247. BOOL
  248. CServerProperties::FOpenScManager()
  249. {
  250. if (m_hScManager == NULL)
  251. {
  252. m_hScManager = ::OpenSCManager(m_strMachineName,
  253. NULL,
  254. SC_MANAGER_CONNECT);
  255. }
  256. if (m_hScManager == NULL)
  257. {
  258. TapiMessageBox(::GetLastError());
  259. return FALSE;
  260. }
  261. return TRUE;
  262. } // CServicePropertyData::FOpenScManager()
  263. BOOL
  264. CServerProperties::FUpdateServiceInfo(LPCTSTR pszName, LPCTSTR pszPassword, DWORD dwStartType)
  265. {
  266. SC_HANDLE hService = NULL;
  267. BOOL fSuccess = TRUE;
  268. BOOL f;
  269. DWORD dwServiceType = 0;
  270. Trace1("INFO: Updating data for service %s...\n", (LPCTSTR)m_pszServiceName);
  271. // Re-open service control manager (in case it was closed)
  272. if (!FOpenScManager())
  273. {
  274. return FALSE;
  275. }
  276. /*
  277. ** Open service with write access
  278. **
  279. ** CODEWORK Could provide a more specific error message
  280. ** if SERVICE_CHANGE_CONFIG is available but not SERVICE_START
  281. */
  282. hService = ::OpenService(m_hScManager,
  283. m_pszServiceName,
  284. SERVICE_CHANGE_CONFIG);
  285. if (hService == NULL)
  286. {
  287. TapiMessageBox(::GetLastError());
  288. return FALSE;
  289. }
  290. Trace1("# ChangeServiceConfig(%s)...\n", m_pszServiceName);
  291. if (pszName)
  292. {
  293. if (IsLocalSystemAccount(pszName))
  294. {
  295. pszPassword = szPasswordNull;
  296. }
  297. dwServiceType = m_paQSC->dwServiceType & ~SERVICE_INTERACTIVE_PROCESS;
  298. }
  299. else
  300. {
  301. dwServiceType = SERVICE_NO_CHANGE;
  302. }
  303. f = ::ChangeServiceConfig(hService, // Handle to service
  304. dwServiceType, // Type of service
  305. dwStartType, // When/How to start service
  306. SERVICE_NO_CHANGE, // dwErrorControl - severity if service fails to start
  307. NULL, // Pointer to service binary file name
  308. NULL, // lpLoadOrderGroup - pointer to load ordering group name
  309. NULL, // lpdwTagId - pointer to variable to get tag identifier
  310. NULL, // lpDependencies - pointer to array of dependency names
  311. pszName, // Pointer to account name of service
  312. pszPassword, // Pointer to password for service account
  313. m_strServiceDisplayName);
  314. if (!f)
  315. {
  316. DWORD dwErr = ::GetLastError();
  317. Assert(dwErr != ERROR_SUCCESS);
  318. Trace2("ERR: ChangeServiceConfig(%s) failed. err= %u.\n", m_pszServiceName, dwErr);
  319. TapiMessageBox(dwErr);
  320. fSuccess = FALSE;
  321. }
  322. else
  323. {
  324. m_strLogOnAccountName = pszName;
  325. // if pszName is null, we aren't changing the account info, so don't check
  326. // the logon as service info
  327. if (pszName && !IsLocalSystemAccount(pszName))
  328. {
  329. /*
  330. ** Make sure there is an LSA account with POLICY_MODE_SERVICE privilege
  331. ** This function reports its own errors, failure is only advisory
  332. */
  333. FCheckLSAAccount();
  334. }
  335. }
  336. VERIFY(::CloseServiceHandle(hService));
  337. return fSuccess;
  338. }
  339. //Check if the user has the write access on service config info
  340. BOOL
  341. CServerProperties::FHasServiceControl()
  342. {
  343. BOOL fRet = FALSE;
  344. if (FIsTapiInfoLoaded())
  345. {
  346. fRet = m_spTapiInfo->FHasServiceControl();
  347. }
  348. else
  349. {
  350. if (!FOpenScManager())
  351. {
  352. fRet = FALSE;
  353. }
  354. else
  355. {
  356. SC_HANDLE hService = NULL;
  357. hService = ::OpenService(m_hScManager,
  358. m_pszServiceName,
  359. SERVICE_CHANGE_CONFIG);
  360. fRet = (hService != NULL);
  361. if (hService)
  362. {
  363. VERIFY(::CloseServiceHandle(hService));
  364. }
  365. }
  366. }
  367. return fRet;
  368. }
  369. /////////////////////////////////////////////////////////////////////////////
  370. // CServerPropRefresh property page
  371. IMPLEMENT_DYNCREATE(CServerPropRefresh, CPropertyPageBase)
  372. CServerPropRefresh::CServerPropRefresh() : CPropertyPageBase(CServerPropRefresh::IDD)
  373. {
  374. //{{AFX_DATA_INIT(CServerPropRefresh)
  375. // NOTE: the ClassWizard will add member initialization here
  376. //}}AFX_DATA_INIT
  377. }
  378. CServerPropRefresh::~CServerPropRefresh()
  379. {
  380. }
  381. void CServerPropRefresh::DoDataExchange(CDataExchange* pDX)
  382. {
  383. CPropertyPageBase::DoDataExchange(pDX);
  384. //{{AFX_DATA_MAP(CServerPropRefresh)
  385. DDX_Control(pDX, IDC_EDIT_MINUTES, m_editMinutes);
  386. DDX_Control(pDX, IDC_EDIT_HOURS, m_editHours);
  387. DDX_Control(pDX, IDC_SPIN_MINUTES, m_spinMinutes);
  388. DDX_Control(pDX, IDC_SPIN_HOURS, m_spinHours);
  389. DDX_Control(pDX, IDC_CHECK_ENABLE_STATS, m_checkEnableStats);
  390. //}}AFX_DATA_MAP
  391. }
  392. BEGIN_MESSAGE_MAP(CServerPropRefresh, CPropertyPageBase)
  393. //{{AFX_MSG_MAP(CServerPropRefresh)
  394. ON_BN_CLICKED(IDC_CHECK_ENABLE_STATS, OnCheckEnableStats)
  395. ON_EN_KILLFOCUS(IDC_EDIT_HOURS, OnKillfocusEditHours)
  396. ON_EN_KILLFOCUS(IDC_EDIT_MINUTES, OnKillfocusEditMinutes)
  397. ON_EN_CHANGE(IDC_EDIT_HOURS, OnChangeEditHours)
  398. ON_EN_CHANGE(IDC_EDIT_MINUTES, OnChangeEditMinutes)
  399. //}}AFX_MSG_MAP
  400. END_MESSAGE_MAP()
  401. /////////////////////////////////////////////////////////////////////////////
  402. // CServerPropRefresh message handlers
  403. BOOL CServerPropRefresh::OnInitDialog()
  404. {
  405. CPropertyPageBase::OnInitDialog();
  406. m_spinHours.SetRange(0, AUTO_REFRESH_HOURS_MAX);
  407. m_spinMinutes.SetRange(0, AUTO_REFRESH_MINUTES_MAX);
  408. m_checkEnableStats.SetCheck(m_bAutoRefresh);
  409. // update the refresh interval
  410. int nHours, nMinutes;
  411. DWORD dwRefreshInterval = m_dwRefreshInterval;
  412. nHours = dwRefreshInterval / MILLISEC_PER_HOUR;
  413. dwRefreshInterval -= nHours * MILLISEC_PER_HOUR;
  414. nMinutes = dwRefreshInterval / MILLISEC_PER_MINUTE;
  415. dwRefreshInterval -= nMinutes * MILLISEC_PER_MINUTE;
  416. m_spinHours.SetPos(nHours);
  417. m_spinMinutes.SetPos(nMinutes);
  418. m_editHours.LimitText(2);
  419. m_editMinutes.LimitText(2);
  420. // set the button states
  421. UpdateButtons();
  422. SetDirty(FALSE);
  423. return TRUE; // return TRUE unless you set the focus to a control
  424. // EXCEPTION: OCX Property Pages should return FALSE
  425. }
  426. void CServerPropRefresh::UpdateButtons()
  427. {
  428. int nCheck = m_checkEnableStats.GetCheck();
  429. GetDlgItem(IDC_EDIT_HOURS)->EnableWindow(nCheck != 0);
  430. GetDlgItem(IDC_EDIT_MINUTES)->EnableWindow(nCheck != 0);
  431. GetDlgItem(IDC_SPIN_HOURS)->EnableWindow(nCheck != 0);
  432. GetDlgItem(IDC_SPIN_MINUTES)->EnableWindow(nCheck != 0);
  433. }
  434. void CServerPropRefresh::OnCheckEnableStats()
  435. {
  436. SetDirty(TRUE);
  437. UpdateButtons();
  438. }
  439. void CServerPropRefresh::OnKillfocusEditHours()
  440. {
  441. }
  442. void CServerPropRefresh::OnKillfocusEditMinutes()
  443. {
  444. }
  445. void CServerPropRefresh::OnChangeEditHours()
  446. {
  447. ValidateHours();
  448. SetDirty(TRUE);
  449. }
  450. void CServerPropRefresh::OnChangeEditMinutes()
  451. {
  452. ValidateMinutes();
  453. SetDirty(TRUE);
  454. }
  455. void CServerPropRefresh::ValidateHours()
  456. {
  457. CString strValue;
  458. int nValue;
  459. if (m_editHours.GetSafeHwnd() != NULL)
  460. {
  461. m_editHours.GetWindowText(strValue);
  462. if (!strValue.IsEmpty())
  463. {
  464. nValue = _ttoi(strValue);
  465. if ((nValue >= 0) &&
  466. (nValue <= AUTO_REFRESH_HOURS_MAX))
  467. {
  468. // everything is good
  469. return;
  470. }
  471. if (nValue > AUTO_REFRESH_HOURS_MAX)
  472. nValue = AUTO_REFRESH_HOURS_MAX;
  473. else
  474. if (nValue < 0)
  475. nValue = 0;
  476. // set the new value and beep
  477. CString strText;
  478. LPTSTR pBuf = strText.GetBuffer(5);
  479. _itot(nValue, pBuf, 10);
  480. strText.ReleaseBuffer();
  481. MessageBeep(MB_ICONEXCLAMATION);
  482. m_editHours.SetWindowText(strText);
  483. m_editHours.SetSel(0, -1);
  484. m_editHours.SetFocus();
  485. }
  486. }
  487. }
  488. void CServerPropRefresh::ValidateMinutes()
  489. {
  490. CString strValue;
  491. int nValue;
  492. if (m_editMinutes.GetSafeHwnd() != NULL)
  493. {
  494. m_editMinutes.GetWindowText(strValue);
  495. if (!strValue.IsEmpty())
  496. {
  497. nValue = _ttoi(strValue);
  498. if ((nValue >= 0) &&
  499. (nValue <= AUTO_REFRESH_MINUTES_MAX))
  500. {
  501. // everything is good
  502. return;
  503. }
  504. if (nValue > AUTO_REFRESH_MINUTES_MAX)
  505. nValue = AUTO_REFRESH_MINUTES_MAX;
  506. else
  507. if (nValue < 0)
  508. nValue = 0;
  509. CString strText;
  510. LPTSTR pBuf = strText.GetBuffer(5);
  511. _itot(nValue, pBuf, 10);
  512. strText.ReleaseBuffer();
  513. MessageBeep(MB_ICONEXCLAMATION);
  514. m_editMinutes.SetWindowText(strText);
  515. m_editMinutes.SetSel(0, -1);
  516. m_editMinutes.SetFocus();
  517. }
  518. }
  519. }
  520. BOOL CServerPropRefresh::OnApply()
  521. {
  522. if (!IsDirty())
  523. return TRUE;
  524. UpdateData();
  525. m_bAutoRefresh = (m_checkEnableStats.GetCheck() == 1) ? TRUE : FALSE;
  526. int nHours = m_spinHours.GetPos();
  527. int nMinutes = m_spinMinutes.GetPos();
  528. m_dwRefreshInterval = nHours * MILLISEC_PER_HOUR;
  529. m_dwRefreshInterval += nMinutes * MILLISEC_PER_MINUTE;
  530. if (m_bAutoRefresh && m_dwRefreshInterval == 0)
  531. {
  532. CString strMessage;
  533. AfxMessageBox(IDS_ERR_AUTO_REFRESH_ZERO);
  534. m_editHours.SetSel(0, -1);
  535. m_editHours.SetFocus();
  536. return FALSE;
  537. }
  538. BOOL bRet = CPropertyPageBase::OnApply();
  539. if (bRet == FALSE)
  540. {
  541. // Something bad happened... grab the error code
  542. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  543. ::TapiMessageBox(GetHolder()->GetError());
  544. }
  545. return bRet;
  546. }
  547. BOOL CServerPropRefresh::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask)
  548. {
  549. SPITFSNode spNode;
  550. CTapiServer * pServer;
  551. DWORD dwError;
  552. // do stuff here.
  553. BEGIN_WAIT_CURSOR;
  554. spNode = GetHolder()->GetNode();
  555. pServer = GETHANDLER(CTapiServer, spNode);
  556. pServer->SetAutoRefresh(spNode, m_bAutoRefresh, m_dwRefreshInterval);
  557. SPITFSNodeMgr spNodeMgr;
  558. SPITFSNode spRootNode;
  559. spNode->GetNodeMgr(&spNodeMgr);
  560. spNodeMgr->GetRootNode(&spRootNode);
  561. spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
  562. END_WAIT_CURSOR;
  563. return FALSE;
  564. }
  565. /////////////////////////////////////////////////////////////////////////////
  566. // CServerPropSetup property page
  567. IMPLEMENT_DYNCREATE(CServerPropSetup, CPropertyPageBase)
  568. CServerPropSetup::CServerPropSetup() : CPropertyPageBase(CServerPropSetup::IDD)
  569. {
  570. //{{AFX_DATA_INIT(CServerPropSetup)
  571. // NOTE: the ClassWizard will add member initialization here
  572. //}}AFX_DATA_INIT
  573. m_dwNewFlags = 0;
  574. }
  575. CServerPropSetup::~CServerPropSetup()
  576. {
  577. }
  578. void CServerPropSetup::DoDataExchange(CDataExchange* pDX)
  579. {
  580. CPropertyPage::DoDataExchange(pDX);
  581. //{{AFX_DATA_MAP(CServerPropSetup)
  582. DDX_Control(pDX, IDC_LIST_ADMINS, m_listAdmins);
  583. //}}AFX_DATA_MAP
  584. }
  585. BEGIN_MESSAGE_MAP(CServerPropSetup, CPropertyPageBase)
  586. //{{AFX_MSG_MAP(CServerPropSetup)
  587. ON_BN_CLICKED(IDC_BUTTON_ADD_ADMIN, OnButtonAdd)
  588. ON_BN_CLICKED(IDC_BUTTON_CHOOSE_USER, OnButtonChooseUser)
  589. ON_BN_CLICKED(IDC_BUTTON_REMOVE_ADMIN, OnButtonRemove)
  590. ON_BN_CLICKED(IDC_CHECK_ENABLE_SERVER, OnCheckEnableServer)
  591. ON_EN_CHANGE(IDC_EDIT_NAME, OnChangeEditName)
  592. ON_EN_CHANGE(IDC_EDIT_PASSWORD, OnChangeEditPassword)
  593. ON_LBN_SELCHANGE(IDC_LIST_ADMINS, OnSelchangeListAdmins)
  594. //}}AFX_MSG_MAP
  595. END_MESSAGE_MAP()
  596. /////////////////////////////////////////////////////////////////////////////
  597. // CServerPropSetup message handlers
  598. BOOL CServerPropSetup::OnInitDialog()
  599. {
  600. SPITapiInfo spTapiInfo;
  601. CString strName;
  602. HRESULT hr = hrOK;
  603. CPropertyPageBase::OnInitDialog();
  604. CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
  605. pServerProp->GetTapiInfo(&spTapiInfo);
  606. Assert(spTapiInfo);
  607. BOOL fIsNTS = TRUE;
  608. if (pServerProp->FIsServiceRunning())
  609. {
  610. fIsNTS = spTapiInfo->IsServer();
  611. hr = spTapiInfo->GetConfigInfo(&m_tapiConfigInfo);
  612. if (FAILED(hr))
  613. {
  614. Panic1("ServerPropSetup - GetConfigInfo failed! %x", hr);
  615. }
  616. // update the checkbox
  617. ((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->SetCheck(spTapiInfo->IsTapiServer());
  618. // now update any TAPI administrators
  619. for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  620. {
  621. ((CListBox *) GetDlgItem(IDC_LIST_ADMINS))->AddString(m_tapiConfigInfo.m_arrayAdministrators[i].m_strName);
  622. }
  623. }
  624. else
  625. {
  626. // check to see if the machine is NTS
  627. TFSIsNTServer(pServerProp->m_strMachineName, &fIsNTS);
  628. }
  629. if (fIsNTS)
  630. {
  631. // fill in the username and password
  632. strName = pServerProp->GetServiceAccountName();
  633. GetDlgItem(IDC_EDIT_NAME)->SetWindowText(strName);
  634. GetDlgItem(IDC_EDIT_PASSWORD)->SetWindowText(szPasswordNull);
  635. m_dwNewFlags = TAPISERVERCONFIGFLAGS_ISSERVER;
  636. }
  637. else
  638. {
  639. m_dwNewFlags = 0;
  640. }
  641. EnableButtons(fIsNTS);
  642. m_fRestartService = FALSE;
  643. m_dwInitFlags = m_tapiConfigInfo.m_dwFlags;
  644. SetDirty(FALSE);
  645. return TRUE; // return TRUE unless you set the focus to a control
  646. // EXCEPTION: OCX Property Pages should return FALSE
  647. }
  648. void CServerPropSetup::OnButtonAdd()
  649. {
  650. CGetUsers getUsers(TRUE);
  651. if (!getUsers.GetUsers(GetSafeHwnd()))
  652. return;
  653. for (int nCount = 0; nCount < getUsers.GetSize(); nCount++)
  654. {
  655. CUserInfo userTemp;
  656. userTemp = getUsers[nCount];
  657. BOOL fDuplicate = FALSE;
  658. for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  659. {
  660. if (m_tapiConfigInfo.m_arrayAdministrators[i].m_strName.CompareNoCase(userTemp.m_strName) == 0)
  661. {
  662. fDuplicate = TRUE;
  663. break;
  664. }
  665. }
  666. if (!fDuplicate)
  667. {
  668. // add to the array
  669. int nIndex = (int)m_tapiConfigInfo.m_arrayAdministrators.Add(userTemp);
  670. // now add to the listbox
  671. m_listAdmins.AddString(m_tapiConfigInfo.m_arrayAdministrators[nIndex].m_strName);
  672. }
  673. else
  674. {
  675. // tell the user we're not adding this to the list
  676. CString strMessage;
  677. AfxFormatString1(strMessage, IDS_ADMIN_ALREADY_IN_LIST, userTemp.m_strName);
  678. AfxMessageBox(strMessage);
  679. }
  680. SetDirty(TRUE);
  681. }
  682. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
  683. EnableButtons();
  684. }
  685. void CServerPropSetup::OnButtonRemove()
  686. {
  687. CString strSelectedName;
  688. int nCurSel = m_listAdmins.GetCurSel();
  689. m_listAdmins.GetText(nCurSel, strSelectedName);
  690. // remove from the list
  691. for (int i = 0; i < m_tapiConfigInfo.m_arrayAdministrators.GetSize(); i++)
  692. {
  693. if (strSelectedName.Compare(m_tapiConfigInfo.m_arrayAdministrators[i].m_strName) == 0)
  694. {
  695. // found it. remove from the list
  696. m_tapiConfigInfo.m_arrayAdministrators.RemoveAt(i);
  697. break;
  698. }
  699. }
  700. // now remove from the list box
  701. m_listAdmins.DeleteString(nCurSel);
  702. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS;
  703. SetDirty(TRUE);
  704. EnableButtons();
  705. }
  706. void CServerPropSetup::OnButtonChooseUser()
  707. {
  708. CGetUsers getUsers;
  709. if (!getUsers.GetUsers(GetSafeHwnd()))
  710. return;
  711. if (0 == getUsers.GetSize())
  712. return;
  713. CUserInfo userTemp;
  714. userTemp = getUsers[0];
  715. GetDlgItem(IDC_EDIT_NAME)->SetWindowText(userTemp.m_strName);
  716. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  717. SetDirty(TRUE);
  718. EnableButtons();
  719. }
  720. void CServerPropSetup::OnCheckEnableServer()
  721. {
  722. if (((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck())
  723. {
  724. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_ENABLESERVER;
  725. }
  726. else
  727. {
  728. m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_ENABLESERVER;
  729. }
  730. EnableButtons ();
  731. SetDirty(TRUE);
  732. }
  733. void CServerPropSetup::OnChangeEditName()
  734. {
  735. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  736. SetDirty(TRUE);
  737. }
  738. void CServerPropSetup::OnChangeEditPassword()
  739. {
  740. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  741. m_fRestartService = TRUE;
  742. SetDirty(TRUE);
  743. }
  744. void CServerPropSetup::OnSelchangeListAdmins()
  745. {
  746. EnableButtons();
  747. }
  748. void CServerPropSetup::EnableButtons(BOOL fIsNtServer)
  749. {
  750. BOOL fServiceRunning = ((CServerProperties *) GetHolder())->FIsServiceRunning();
  751. //if we are unable to get the write access to tapisrv service, we need to disable
  752. // some controls
  753. BOOL fHasServiceControl = ((CServerProperties *) GetHolder())->FHasServiceControl();
  754. //We enable the admin controls only if we sucessfully loaded the tapi info
  755. BOOL fTapiInfoLoaded = ((CServerProperties *) GetHolder())->FIsTapiInfoLoaded();
  756. BOOL fIsAdmin = ((CServerProperties *) GetHolder())->FIsAdmin();
  757. // if this isn't an NT server, disable all controls
  758. if (!fIsNtServer)
  759. fServiceRunning = FALSE;
  760. //Enable the Admin controls only if
  761. //(1) the service is running
  762. //(2) successfully loaded the tapi config info
  763. //(3) the user is a machine admin or tapi admin
  764. BOOL fEnableAdminControls = fServiceRunning && fTapiInfoLoaded && fIsAdmin;
  765. // enable the admin controls on
  766. GetDlgItem(IDC_STATIC_ADMINS)->EnableWindow(fEnableAdminControls);
  767. GetDlgItem(IDC_STATIC_NOTE)->EnableWindow(fEnableAdminControls);
  768. GetDlgItem(IDC_STATIC_LISTBOX)->EnableWindow(fEnableAdminControls);
  769. GetDlgItem(IDC_BUTTON_ADD_ADMIN)->EnableWindow(fEnableAdminControls);
  770. GetDlgItem(IDC_BUTTON_REMOVE_ADMIN)->EnableWindow(fEnableAdminControls);
  771. GetDlgItem(IDC_LIST_ADMINS)->EnableWindow(fEnableAdminControls);
  772. //If the user is not admin, then they don't have ServiceControl write access
  773. //So fHasServiceControl covers fIsAdmin
  774. GetDlgItem(IDC_CHECK_ENABLE_SERVER)->EnableWindow(fServiceRunning
  775. && fHasServiceControl
  776. && fTapiInfoLoaded);
  777. // these should always be available if we have service control access
  778. // and we are running on server
  779. GetDlgItem(IDC_STATIC_USERNAME)->EnableWindow(fIsNtServer && fHasServiceControl);
  780. GetDlgItem(IDC_STATIC_PASSWORD)->EnableWindow(fIsNtServer && fHasServiceControl);
  781. GetDlgItem(IDC_STATIC_ACCOUNT)->EnableWindow(fIsNtServer && fHasServiceControl);
  782. GetDlgItem(IDC_BUTTON_CHOOSE_USER)->EnableWindow(fIsNtServer && fHasServiceControl);
  783. GetDlgItem(IDC_EDIT_NAME)->EnableWindow(fIsNtServer && fHasServiceControl);
  784. GetDlgItem(IDC_EDIT_PASSWORD)->EnableWindow(fIsNtServer && fHasServiceControl);
  785. GetDlgItem(IDC_STATIC_ACCOUNT_INFO)->EnableWindow(fIsNtServer && fHasServiceControl);
  786. if (fServiceRunning)
  787. {
  788. // enable the remove button if something is selected
  789. BOOL fEnableRemove = m_listAdmins.GetCurSel() != LB_ERR;
  790. //if we will disable the remove button and the remove button has the focus,
  791. //we should change focus to the next control
  792. CWnd * pwndRemove = GetDlgItem(IDC_BUTTON_REMOVE_ADMIN);
  793. if (!fEnableRemove && GetFocus() == pwndRemove)
  794. {
  795. NextDlgCtrl();
  796. }
  797. pwndRemove->EnableWindow(fEnableRemove);
  798. }
  799. }
  800. BOOL CServerPropSetup::OnApply()
  801. {
  802. CString strAccount, strPassword;
  803. BOOL fUpdateAccount = FALSE;
  804. BOOL fUpdateTapiServer = FALSE;
  805. BOOL bRet = TRUE;
  806. BOOL bWasServer, bToBeServer;
  807. DWORD dwStartType = SERVICE_NO_CHANGE;
  808. if (!IsDirty())
  809. return bRet;
  810. CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
  811. UpdateData();
  812. // Check to see if there is any change on enabling server
  813. // or user account name, that requires service restarting
  814. if (!m_fRestartService)
  815. {
  816. bWasServer = m_dwInitFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER;
  817. bToBeServer = ((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck();
  818. if (bWasServer && !bToBeServer || !bWasServer && bToBeServer)
  819. {
  820. m_fRestartService = TRUE;
  821. }
  822. if (m_dwNewFlags & TAPISERVERCONFIGFLAGS_SETACCOUNT)
  823. {
  824. GetDlgItem(IDC_EDIT_NAME)->GetWindowText(strAccount);
  825. if (strAccount.CompareNoCase(pServerProp->GetServiceAccountName()) != 0)
  826. {
  827. m_fRestartService = TRUE;
  828. }
  829. else
  830. {
  831. m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_SETACCOUNT;
  832. }
  833. }
  834. }
  835. // if the account information has changed, the update the info struct now
  836. if (m_dwNewFlags & TAPISERVERCONFIGFLAGS_SETACCOUNT)
  837. {
  838. GetDlgItem(IDC_EDIT_NAME)->GetWindowText(strAccount);
  839. GetDlgItem(IDC_EDIT_PASSWORD)->GetWindowText(strPassword);
  840. // verify that the user is an admin on the machine
  841. if (!IsLocalSystemAccount(strAccount))
  842. {
  843. DWORD dwErr;
  844. BOOL fIsAdmin;
  845. CString strMessage;
  846. dwErr = ::IsAdmin(pServerProp->m_strMachineName, strAccount, strPassword, &fIsAdmin);
  847. if (!fIsAdmin)
  848. {
  849. AfxFormatString1(strMessage, IDS_ERR_USER_NOT_ADMIN, pServerProp->m_strMachineName);
  850. AfxMessageBox(strMessage);
  851. GetDlgItem(IDC_EDIT_NAME)->SetFocus();
  852. ((CEdit *) GetDlgItem(IDC_EDIT_NAME))->SetSel(0, -1);
  853. return FALSE;
  854. }
  855. }
  856. // clear the flag so we don't use the TAPI MMC APIs to set this
  857. m_dwNewFlags &= ~TAPISERVERCONFIGFLAGS_SETACCOUNT;
  858. fUpdateAccount = TRUE;
  859. }
  860. // if we are changing the server state or admin stuff then
  861. if (((CButton *) GetDlgItem(IDC_CHECK_ENABLE_SERVER))->GetCheck())
  862. {
  863. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_ENABLESERVER;
  864. }
  865. // only update config information if it has changed
  866. if ((pServerProp->FIsServiceRunning()) &&
  867. (m_tapiConfigInfo.m_dwFlags != m_dwNewFlags))
  868. {
  869. // if we modify the tapi server status then we need to change the
  870. // service statrt type as well.
  871. if ((m_dwNewFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER) &&
  872. !(m_tapiConfigInfo.m_dwFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER))
  873. {
  874. fUpdateTapiServer = TRUE;
  875. }
  876. dwStartType = (m_dwNewFlags & TAPISERVERCONFIGFLAGS_ENABLESERVER) ? SERVICE_AUTO_START : SERVICE_DEMAND_START;
  877. bRet = CPropertyPageBase::OnApply();
  878. }
  879. if (bRet == FALSE)
  880. {
  881. // Something bad happened... grab the error code
  882. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  883. ::TapiMessageBox(WIN32_FROM_HRESULT(GetHolder()->GetError()));
  884. // restore the flag
  885. if (fUpdateAccount)
  886. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  887. }
  888. else
  889. {
  890. m_dwNewFlags = TAPISERVERCONFIGFLAGS_ISSERVER;
  891. if (fUpdateAccount || fUpdateTapiServer)
  892. {
  893. // do the account change
  894. BEGIN_WAIT_CURSOR
  895. LPCTSTR pszAccount = (fUpdateAccount) ? (LPCTSTR) strAccount : NULL;
  896. LPCTSTR pszPassword = (fUpdateAccount) ? (LPCTSTR) strPassword : NULL;
  897. bRet = pServerProp->FUpdateServiceInfo(pszAccount, pszPassword, dwStartType);
  898. if (bRet)
  899. {
  900. /*$REVIEW
  901. Tapisrv occupies a seperate house in NT server. It lives with the other
  902. services on NT Professional Edition(workstation). We do not need to
  903. sperate/merge services anymore. Users should not be allowed to change
  904. account information from TAPI MMC on NT workstation(Disabled).
  905. HRESULT hr;
  906. // if the change was successful, update the svc host information
  907. hr = UpdateSvcHostInfo(pServerProp->m_strMachineName, IsLocalSystemAccount(strAccount));
  908. if (FAILED(hr))
  909. {
  910. // restore the flag
  911. if (fUpdateAccount)
  912. {
  913. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  914. }
  915. ::TapiMessageBox(WIN32_FROM_HRESULT(hr));
  916. return FALSE;
  917. }
  918. */
  919. }
  920. else if (fUpdateAccount)
  921. {
  922. // set account failed, so set the flag again.
  923. m_dwNewFlags |= TAPISERVERCONFIGFLAGS_SETACCOUNT;
  924. }
  925. END_WAIT_CURSOR
  926. }
  927. // if everything went OK and we changed something that requires a service restart then
  928. // do ask the user if they want to do it now
  929. if (bRet && m_fRestartService)
  930. {
  931. CString strText;
  932. BOOL fServiceRunning = pServerProp->FIsServiceRunning();
  933. ::TFSIsServiceRunning(pServerProp->m_strMachineName,
  934. TAPI_SERVICE_NAME,
  935. &fServiceRunning);
  936. if (fServiceRunning)
  937. strText.LoadString(IDS_ACCOUNT_CHANGE_RESTART);
  938. else
  939. strText.LoadString(IDS_ACCOUNT_CHANGE_START);
  940. // Tell the user the service needs to be restarted in order to make the changes
  941. if (AfxMessageBox(strText, MB_YESNO) == IDYES)
  942. {
  943. if (RestartService() == ERROR_SUCCESS)
  944. {
  945. m_fRestartService = FALSE;
  946. m_dwInitFlags = m_tapiConfigInfo.m_dwFlags;
  947. }
  948. }
  949. }
  950. }
  951. if (!bRet)
  952. SetDirty(TRUE);
  953. return bRet;
  954. }
  955. BOOL CServerPropSetup::OnPropertyChange(BOOL bScope, LONG_PTR *ChangeMask)
  956. {
  957. SPITapiInfo spTapiInfo;
  958. HRESULT hr = hrOK;
  959. BOOL fServiceRunning = TRUE;
  960. DWORD dwOldFlags;
  961. DWORD dwErr = ERROR_SUCCESS;
  962. CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
  963. pServerProp->GetTapiInfo(&spTapiInfo);
  964. Assert(spTapiInfo);
  965. // if the service isn't running, try to start it
  966. //if (!pServerProp->FIsServiceRunning())
  967. dwErr = ::TFSIsServiceRunning(pServerProp->m_strMachineName,
  968. TAPI_SERVICE_NAME,
  969. &fServiceRunning);
  970. if (!fServiceRunning)
  971. {
  972. // service has stopped from under us. Return an error.
  973. GetHolder()->SetError(HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE));
  974. return FALSE;
  975. }
  976. // if everything is cool then make the changes
  977. if (dwErr == ERROR_SUCCESS)
  978. {
  979. dwOldFlags = m_tapiConfigInfo.m_dwFlags;
  980. //clear the changable bits in old flags
  981. m_tapiConfigInfo.m_dwFlags &= ~c_dwChangableFlagMask;
  982. //set the changable bits
  983. m_tapiConfigInfo.m_dwFlags |= (m_dwNewFlags & c_dwChangableFlagMask);
  984. hr = spTapiInfo->SetConfigInfo(&m_tapiConfigInfo);
  985. //Bug 276787 We should clear the two write bits
  986. m_tapiConfigInfo.m_dwFlags &= ~(TAPISERVERCONFIGFLAGS_SETACCOUNT |
  987. TAPISERVERCONFIGFLAGS_SETTAPIADMINISTRATORS);
  988. if (FAILED(hr))
  989. {
  990. GetHolder()->SetError(hr);
  991. m_tapiConfigInfo.m_dwFlags = dwOldFlags;
  992. }
  993. }
  994. return FALSE;
  995. }
  996. HRESULT CServerPropSetup::UpdateSvcHostInfo(LPCTSTR pszMachine, BOOL fLocalSystemAccount)
  997. {
  998. HRESULT hr = hrOK;
  999. MULTI_QI qi;
  1000. SPIRemoteNetworkConfig spRemote;
  1001. hr = CoInitialize(NULL);
  1002. if (FAILED(hr))
  1003. {
  1004. return hr;
  1005. }
  1006. if (IsLocalMachine(pszMachine))
  1007. {
  1008. hr = CoCreateInstance(CLSID_RemoteRouterConfig,
  1009. NULL,
  1010. CLSCTX_SERVER,
  1011. IID_IRemoteNetworkConfig,
  1012. (LPVOID *) &(qi.pItf));
  1013. }
  1014. else
  1015. {
  1016. COSERVERINFO csi;
  1017. qi.pIID = &IID_IRemoteNetworkConfig;
  1018. qi.pItf = NULL;
  1019. qi.hr = 0;
  1020. csi.dwReserved1 = 0;
  1021. csi.dwReserved2 = 0;
  1022. csi.pwszName = (LPWSTR) (LPCTSTR) pszMachine;
  1023. csi.pAuthInfo = NULL;
  1024. hr = CoCreateInstanceEx(CLSID_RemoteRouterConfig,
  1025. NULL,
  1026. CLSCTX_SERVER,
  1027. &csi,
  1028. 1,
  1029. &qi);
  1030. }
  1031. Trace1("CServerPropSetup::UpdateSvcHostInfo - CoCreateInstance returned %lx\n", hr);
  1032. if (hr == S_OK)
  1033. {
  1034. CString strGroup;
  1035. strGroup = _T("Tapisrv");
  1036. spRemote = (IRemoteNetworkConfig *)qi.pItf;
  1037. hr = spRemote->SetUserConfig(TAPI_SERVICE_NAME, strGroup);
  1038. Trace1("CServerPropSetup::UpdateSvcHostInfo - SetUserConfig returned %lx\n", hr);
  1039. }
  1040. CoUninitialize();
  1041. return hr;
  1042. }
  1043. DWORD CServerPropSetup::RestartService()
  1044. {
  1045. // restart the service if requested
  1046. CServerProperties * pServerProp = (CServerProperties * ) GetHolder();
  1047. DWORD dwErr = ERROR_SUCCESS;
  1048. BOOL fRestart = FALSE;
  1049. SPITapiInfo spTapiInfo;
  1050. pServerProp->GetTapiInfo(&spTapiInfo);
  1051. // gotta clean up before the service stops
  1052. spTapiInfo->Destroy();
  1053. // any time we stop/start the service we need to call this
  1054. ::UnloadTapiDll();
  1055. // stop the service if it is running
  1056. BOOL fServiceRunning = pServerProp->FIsServiceRunning();
  1057. ::TFSIsServiceRunning(pServerProp->m_strMachineName,
  1058. TAPI_SERVICE_NAME,
  1059. &fServiceRunning);
  1060. if (fServiceRunning)
  1061. {
  1062. dwErr = ::TFSStopService(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, pServerProp->GetServiceDisplayName());
  1063. }
  1064. if (dwErr != ERROR_SUCCESS)
  1065. {
  1066. CString strText;
  1067. strText.LoadString(IDS_ERR_SERVICE_NOT_STOPPED);
  1068. TapiMessageBox(dwErr, MB_OK, strText);
  1069. }
  1070. // start the service
  1071. if (dwErr == ERROR_SUCCESS)
  1072. {
  1073. dwErr = ::TFSStartService(pServerProp->m_strMachineName, TAPI_SERVICE_NAME, pServerProp->GetServiceDisplayName());
  1074. if (dwErr != ERROR_SUCCESS)
  1075. {
  1076. CString strText;
  1077. strText.LoadString(IDS_ERR_SERVICE_NOT_STARTED);
  1078. TapiMessageBox(dwErr, MB_OK, strText);
  1079. }
  1080. }
  1081. StartRefresh();
  1082. return dwErr;
  1083. }
  1084. void CServerPropSetup::StartRefresh()
  1085. {
  1086. // refresh the snapin to reflect the changes
  1087. SPITFSNode spNode;
  1088. CTapiServer * pServer;
  1089. spNode = GetHolder()->GetNode();
  1090. pServer = GETHANDLER(CTapiServer, spNode);
  1091. pServer->OnRefresh(spNode, NULL, 0, 0, 0);
  1092. }