Leaked source code of windows server 2003
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.

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