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.

759 lines
14 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. fservic.cpp
  5. Abstract:
  6. FTP Service Property Page
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include "inetprop.h"
  19. #include "InetMgrApp.h"
  20. #include "shts.h"
  21. #include "ftpsht.h"
  22. #include "fservic.h"
  23. #include "usersess.h"
  24. #include "iisobj.h"
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static char BASED_CODE THIS_FILE[] = __FILE__;
  28. #endif
  29. //
  30. // Some sanity values on max connections
  31. //
  32. #define MAX_MAX_CONNECTIONS (1999999999L)
  33. #define INITIAL_MAX_CONNECTIONS ( 1000L)
  34. #define UNLIMITED_CONNECTIONS (2000000000L)
  35. #define MAX_TIMEOUT (0x7FFFFFFF)
  36. #define LIMITED_CONNECTIONS_MIN (10)
  37. #define LIMITED_CONNECTIONS_MAX (40)
  38. IMPLEMENT_DYNCREATE(CFtpServicePage, CInetPropertyPage)
  39. CFtpServicePage::CFtpServicePage(
  40. IN CInetPropertySheet * pSheet
  41. )
  42. /*++
  43. Routine Description:
  44. Constructor for FTP service property page
  45. Arguments:
  46. CInetPropertySheet * pSheet : Associated property sheet
  47. Return Value:
  48. N/A
  49. --*/
  50. : CInetPropertyPage(CFtpServicePage::IDD, pSheet)
  51. {
  52. #ifdef _DEBUG
  53. afxMemDF |= checkAlwaysMemDF;
  54. #endif // _DEBUG
  55. #if 0 // Keep Class Wizard happy
  56. //{{AFX_DATA_INIT(CFtpServicePage)
  57. m_strComment = _T("");
  58. m_nTCPPort = 20;
  59. m_nUnlimited = RADIO_LIMITED;
  60. m_nIpAddressSel = -1;
  61. m_fEnableLogging = FALSE;
  62. //}}AFX_DATA_INIT
  63. m_nMaxConnections = 50;
  64. m_nVisibleMaxConnections = 50;
  65. m_nConnectionTimeOut = 600;
  66. m_iaIpAddress = (LONG)0L;
  67. m_strDomainName = _T("");
  68. #endif // 0
  69. }
  70. CFtpServicePage::~CFtpServicePage()
  71. /*++
  72. Routine Description:
  73. Destructor
  74. Arguments:
  75. N/A
  76. Return Value:
  77. N/A
  78. --*/
  79. {
  80. }
  81. void
  82. CFtpServicePage::DoDataExchange(
  83. IN CDataExchange * pDX
  84. )
  85. /*++
  86. Routine Description:
  87. Initialise/Store control data
  88. Arguments:
  89. CDataExchange * pDX - DDX/DDV control structure
  90. Return Value:
  91. None
  92. --*/
  93. {
  94. CInetPropertyPage::DoDataExchange(pDX);
  95. if (!pDX->m_bSaveAndValidate)
  96. {
  97. m_fEnableLogging = LoggingEnabled(m_dwLogType);
  98. }
  99. //{{AFX_DATA_MAP(CFtpServicePage)
  100. DDX_Radio(pDX, IDC_RADIO_UNLIMITED, m_nUnlimited);
  101. DDX_Check(pDX, IDC_CHECK_ENABLE_LOGGING, m_fEnableLogging);
  102. DDX_Text(pDX, IDC_EDIT_COMMENT, m_strComment);
  103. DDV_MinMaxChars(pDX, m_strComment, 0, MAX_PATH);
  104. DDX_Control(pDX, IDC_EDIT_MAX_CONNECTIONS, m_edit_MaxConnections);
  105. DDX_Control(pDX, IDC_STATIC_LOG_PROMPT, m_static_LogPrompt);
  106. DDX_Control(pDX, IDC_STATIC_CONNECTIONS, m_static_Connections);
  107. DDX_Control(pDX, IDC_BUTTON_PROPERTIES, m_button_LogProperties);
  108. DDX_Control(pDX, IDC_COMBO_IP_ADDRESS, m_combo_IpAddresses);
  109. DDX_Control(pDX, IDC_COMBO_LOG_FORMATS, m_combo_LogFormats);
  110. //}}AFX_DATA_MAP
  111. DDX_Text(pDX, IDC_EDIT_TCP_PORT, m_nTCPPort);
  112. if (!IsMasterInstance())
  113. {
  114. DDV_MinMaxUInt(pDX, m_nTCPPort, 1, 65535);
  115. }
  116. if (pDX->m_bSaveAndValidate && !FetchIpAddressFromCombo(
  117. m_combo_IpAddresses,
  118. m_oblIpAddresses,
  119. m_iaIpAddress
  120. ))
  121. {
  122. pDX->Fail();
  123. }
  124. //
  125. // Private DDX/DDV Routines
  126. //
  127. int nMin = IsMasterInstance() ? 0 : 1;
  128. if (!pDX->m_bSaveAndValidate || !m_fUnlimitedConnections )
  129. {
  130. DDX_Text(pDX, IDC_EDIT_MAX_CONNECTIONS, m_nVisibleMaxConnections);
  131. }
  132. if (m_f10ConnectionLimit)
  133. {
  134. //
  135. // Special validation for unlimited connections. We use a bogus
  136. // numeric check for data validation. Number adjustment happens
  137. // later.
  138. //
  139. if (pDX->m_bSaveAndValidate &&
  140. (m_nVisibleMaxConnections < 0 ||
  141. m_nVisibleMaxConnections > UNLIMITED_CONNECTIONS))
  142. {
  143. TCHAR szMin[32];
  144. TCHAR szMax[32];
  145. wsprintf(szMin, _T("%ld"), 0);
  146. wsprintf(szMax, _T("%ld"), 40);
  147. CString prompt;
  148. AfxFormatString2(prompt, AFX_IDP_PARSE_INT_RANGE, szMin, szMax);
  149. AfxMessageBox(prompt, MB_ICONEXCLAMATION);
  150. prompt.Empty(); // exception prep
  151. pDX->Fail();
  152. }
  153. }
  154. else
  155. {
  156. DDV_MinMaxLong(pDX, m_nVisibleMaxConnections, 0, UNLIMITED_CONNECTIONS);
  157. }
  158. DDX_Text(pDX, IDC_EDIT_CONNECTION_TIMEOUT, m_nConnectionTimeOut);
  159. DDV_MinMaxLong(pDX, m_nConnectionTimeOut, nMin, MAX_TIMEOUT);
  160. if (pDX->m_bSaveAndValidate)
  161. {
  162. EnableLogging(m_dwLogType, m_fEnableLogging);
  163. }
  164. }
  165. //
  166. // Message Map
  167. //
  168. BEGIN_MESSAGE_MAP(CFtpServicePage, CInetPropertyPage)
  169. //{{AFX_MSG_MAP(CFtpServicePage)
  170. ON_BN_CLICKED(IDC_CHECK_ENABLE_LOGGING, OnCheckEnableLogging)
  171. ON_BN_CLICKED(IDC_RADIO_LIMITED, OnRadioLimited)
  172. ON_BN_CLICKED(IDC_RADIO_UNLIMITED, OnRadioUnlimited)
  173. ON_BN_CLICKED(IDC_BUTTON_CURRENT_SESSIONS, OnButtonCurrentSessions)
  174. ON_BN_CLICKED(IDC_BUTTON_PROPERTIES, OnButtonProperties)
  175. ON_WM_DESTROY()
  176. //}}AFX_MSG_MAP
  177. ON_EN_CHANGE(IDC_EDIT_TCP_PORT, OnItemChanged)
  178. ON_EN_CHANGE(IDC_EDIT_COMMENT, OnItemChanged)
  179. ON_EN_CHANGE(IDC_EDIT_MAX_CONNECTIONS, OnItemChanged)
  180. ON_EN_CHANGE(IDC_EDIT_CONNECTION_TIMEOUT, OnItemChanged)
  181. ON_CBN_EDITCHANGE(IDC_COMBO_IP_ADDRESS, OnItemChanged)
  182. ON_CBN_SELCHANGE(IDC_COMBO_IP_ADDRESS, OnItemChanged)
  183. ON_CBN_SELCHANGE(IDC_COMBO_LOG_FORMATS, OnItemChanged)
  184. END_MESSAGE_MAP()
  185. void
  186. CFtpServicePage::SetControlStates()
  187. /*++
  188. Routine Description:
  189. Set the states of the dialog control depending on its current
  190. values.
  191. Arguments:
  192. None
  193. Return Value:
  194. None
  195. --*/
  196. {
  197. if (m_edit_MaxConnections.m_hWnd)
  198. {
  199. m_edit_MaxConnections.EnableWindow(!m_fUnlimitedConnections);
  200. m_static_Connections.EnableWindow(!m_fUnlimitedConnections);
  201. }
  202. }
  203. void
  204. CFtpServicePage::PopulateKnownIpAddresses()
  205. /*++
  206. Routine Description:
  207. Fill the combo box with known ip addresses
  208. Arguments:
  209. None
  210. Return Value:
  211. None
  212. --*/
  213. {
  214. BeginWaitCursor();
  215. PopulateComboWithKnownIpAddresses(
  216. QueryServerName(),
  217. m_combo_IpAddresses,
  218. m_iaIpAddress,
  219. m_oblIpAddresses,
  220. m_nIpAddressSel
  221. );
  222. EndWaitCursor();
  223. }
  224. //
  225. // Message Handlers
  226. //
  227. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  228. BOOL
  229. CFtpServicePage::OnInitDialog()
  230. /*++
  231. Routine Description:
  232. WM_INITDIALOG handler. Initialize the dialog.
  233. Arguments:
  234. None.
  235. Return Value:
  236. TRUE if no focus is to be set automatically, FALSE if the focus
  237. is already set.
  238. --*/
  239. {
  240. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  241. CInetPropertyPage::OnInitDialog();
  242. //
  243. // Take our direction from a phony button
  244. //
  245. CRect rc(0, 0, 0, 0);
  246. m_ocx_LogProperties.Create(
  247. _T("LogUI"),
  248. WS_BORDER,
  249. rc,
  250. this,
  251. IDC_LOGUICTRL
  252. );
  253. //
  254. // Initialize the logging ocx; pass it the metabase path of the
  255. // virtual server.
  256. // TODO: Rewrite this crappy logui control to make it more predictable.
  257. // Here metabase path should not contain leading / and trailing Root
  258. //
  259. CString path_inst = QueryMetaPath();
  260. CString path;
  261. if (IsMasterInstance())
  262. {
  263. CMetabasePath::GetServicePath(path_inst, path);
  264. }
  265. else
  266. {
  267. CMetabasePath::GetInstancePath(path_inst, path);
  268. }
  269. if (path[0] == _T('/'))
  270. {
  271. path = path.Right(path.GetLength() - 1);
  272. }
  273. m_ocx_LogProperties.SetAdminTarget(QueryServerName(), path);
  274. m_ocx_LogProperties.SetComboBox(m_combo_LogFormats.m_hWnd);
  275. GetDlgItem(IDC_RADIO_UNLIMITED)->EnableWindow(!m_f10ConnectionLimit);
  276. if (IsMasterInstance() || !HasAdminAccess())
  277. {
  278. GetDlgItem(IDC_STATIC_IPADDRESS)->EnableWindow(FALSE);
  279. GetDlgItem(IDC_STATIC_TCP_PORT)->EnableWindow(FALSE);
  280. GetDlgItem(IDC_EDIT_TCP_PORT)->EnableWindow(FALSE);
  281. m_combo_IpAddresses.EnableWindow(FALSE);
  282. GetDlgItem(IDC_STATIC_DESCRIPTION)->EnableWindow(FALSE);
  283. GetDlgItem(IDC_EDIT_COMMENT)->EnableWindow(FALSE);
  284. }
  285. PopulateKnownIpAddresses();
  286. SetControlStates();
  287. SetLogState();
  288. GetDlgItem(IDC_BUTTON_CURRENT_SESSIONS)->EnableWindow(!IsMasterInstance());
  289. return TRUE;
  290. }
  291. /* virtual */
  292. HRESULT
  293. CFtpServicePage::FetchLoadedValues()
  294. /*++
  295. Routine Description:
  296. Move configuration data from sheet to dialog controls
  297. Arguments:
  298. None
  299. Return Value:
  300. HRESULT
  301. --*/
  302. {
  303. CError err;
  304. m_f10ConnectionLimit = Has10ConnectionLimit();
  305. BEGIN_META_INST_READ(CFtpSheet)
  306. FETCH_INST_DATA_FROM_SHEET(m_nMaxConnections);
  307. FETCH_INST_DATA_FROM_SHEET(m_nConnectionTimeOut);
  308. FETCH_INST_DATA_FROM_SHEET(m_iaIpAddress);
  309. FETCH_INST_DATA_FROM_SHEET(m_nTCPPort);
  310. FETCH_INST_DATA_FROM_SHEET(m_strDomainName);
  311. FETCH_INST_DATA_FROM_SHEET(m_strComment);
  312. FETCH_INST_DATA_FROM_SHEET(m_dwLogType);
  313. m_fUnlimitedConnections = m_nMaxConnections >= MAX_MAX_CONNECTIONS;
  314. if (m_f10ConnectionLimit)
  315. {
  316. m_fUnlimitedConnections = FALSE;
  317. if ((LONG)m_nMaxConnections > LIMITED_CONNECTIONS_MAX)
  318. {
  319. m_nMaxConnections = LIMITED_CONNECTIONS_MAX;
  320. }
  321. }
  322. m_nVisibleMaxConnections = m_fUnlimitedConnections
  323. ? INITIAL_MAX_CONNECTIONS
  324. : m_nMaxConnections;
  325. //
  326. // Set radio value
  327. //
  328. m_nUnlimited = m_fUnlimitedConnections ? RADIO_UNLIMITED : RADIO_LIMITED;
  329. m_nOldTCPPort = m_nTCPPort;
  330. END_META_INST_READ(err)
  331. return err;
  332. }
  333. HRESULT
  334. CFtpServicePage::SaveInfo()
  335. /*++
  336. Routine Description:
  337. Save the information on this property page
  338. Arguments:
  339. None
  340. Return Value:
  341. Error return code
  342. --*/
  343. {
  344. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  345. ASSERT(IsDirty());
  346. TRACEEOLID("Saving FTP service page now...");
  347. CError err;
  348. m_nMaxConnections = m_fUnlimitedConnections
  349. ? UNLIMITED_CONNECTIONS
  350. : m_nVisibleMaxConnections;
  351. //
  352. // Check to make sure we're not violating the license
  353. // agreement
  354. //
  355. if (m_f10ConnectionLimit)
  356. {
  357. if (m_nMaxConnections > LIMITED_CONNECTIONS_MAX)
  358. {
  359. ::AfxMessageBox(IDS_CONNECTION_LIMIT);
  360. m_nMaxConnections = LIMITED_CONNECTIONS_MIN;
  361. }
  362. else if (m_nMaxConnections > LIMITED_CONNECTIONS_MIN
  363. && m_nMaxConnections <= LIMITED_CONNECTIONS_MAX)
  364. {
  365. ::AfxMessageBox(IDS_WRN_CONNECTION_LIMIT);
  366. }
  367. }
  368. CString strBinding;
  369. CStringListEx m_strlBindings;
  370. CInstanceProps::BuildBinding(
  371. strBinding,
  372. m_iaIpAddress,
  373. m_nTCPPort,
  374. m_strDomainName
  375. );
  376. m_strlBindings.AddTail(strBinding);
  377. m_ocx_LogProperties.ApplyLogSelection();
  378. BeginWaitCursor();
  379. BEGIN_META_INST_WRITE(CFtpSheet)
  380. STORE_INST_DATA_ON_SHEET(m_nMaxConnections);
  381. STORE_INST_DATA_ON_SHEET(m_nMaxConnections);
  382. STORE_INST_DATA_ON_SHEET(m_nConnectionTimeOut);
  383. STORE_INST_DATA_ON_SHEET(m_dwLogType);
  384. STORE_INST_DATA_ON_SHEET(m_strComment);
  385. STORE_INST_DATA_ON_SHEET(m_strlBindings);
  386. END_META_INST_WRITE(err)
  387. EndWaitCursor();
  388. if (err.Succeeded())
  389. {
  390. CIISMBNode * pNode = (CIISMBNode *)GetSheet()->GetParameter();
  391. ASSERT(pNode != NULL);
  392. pNode->Refresh(FALSE);
  393. }
  394. return err;
  395. }
  396. void
  397. CFtpServicePage::OnRadioLimited()
  398. /*++
  399. Routine Description:
  400. 'limited' radio button handler
  401. Arguments:
  402. None
  403. Return Value:
  404. None
  405. --*/
  406. {
  407. m_fUnlimitedConnections = FALSE;
  408. SetControlStates();
  409. m_edit_MaxConnections.SetSel(0, -1);
  410. m_edit_MaxConnections.SetFocus();
  411. OnItemChanged();
  412. }
  413. void
  414. CFtpServicePage::OnRadioUnlimited()
  415. /*++
  416. Routine Description:
  417. 'unlimited' radio button handler
  418. Arguments:
  419. None
  420. Return Value:
  421. None
  422. --*/
  423. {
  424. m_fUnlimitedConnections = TRUE;
  425. OnItemChanged();
  426. }
  427. void
  428. CFtpServicePage::OnItemChanged()
  429. /*++
  430. Routine Description:
  431. Register a change in control value on this page. Mark the page as dirty.
  432. All change messages map to this function
  433. Arguments:
  434. None
  435. Return Value:
  436. None
  437. --*/
  438. {
  439. SetControlStates();
  440. SetModified(TRUE);
  441. }
  442. void
  443. CFtpServicePage::SetLogState()
  444. /*++
  445. Routine Description:
  446. Set the enabled state of the logging controls depending on
  447. whether logging is currently enabled
  448. Arguments:
  449. None
  450. Return Value:
  451. None
  452. --*/
  453. {
  454. m_static_LogPrompt.EnableWindow(m_fEnableLogging);
  455. m_combo_LogFormats.EnableWindow(m_fEnableLogging);
  456. m_button_LogProperties.EnableWindow(m_fEnableLogging);
  457. }
  458. void
  459. CFtpServicePage::OnCheckEnableLogging()
  460. /*++
  461. Routine Description:
  462. 'Enable logging' checkbox has been toggled. Reset the state
  463. of the dialog
  464. Arguments:
  465. None
  466. Return Value:
  467. None
  468. --*/
  469. {
  470. m_fEnableLogging = !m_fEnableLogging;
  471. SetLogState();
  472. OnItemChanged();
  473. }
  474. void
  475. CFtpServicePage::OnButtonProperties()
  476. /*++
  477. Routine Description:
  478. Pass on "log properties" button click to the ocx.
  479. Arguments:
  480. None
  481. Return Value:
  482. None
  483. --*/
  484. {
  485. AFX_MANAGE_STATE(::AfxGetStaticModuleState());
  486. m_ocx_LogProperties.DoClick();
  487. }
  488. void
  489. CFtpServicePage::OnButtonCurrentSessions()
  490. /*++
  491. Routine Description:
  492. 'Current Sessions' button has been pressed. Bring up the current
  493. sessions dialog
  494. Arguments:
  495. None
  496. Return Value:
  497. None
  498. -*/
  499. {
  500. CComAuthInfo * pAuth = GetSheet()->QueryAuthInfo();
  501. ASSERT(pAuth != NULL);
  502. CUserSessionsDlg dlg(
  503. pAuth->QueryServerName(),
  504. QueryInstance(),
  505. pAuth->QueryUserName(),
  506. pAuth->QueryPassword(),
  507. this);
  508. dlg.DoModal();
  509. }
  510. void
  511. CFtpServicePage::OnDestroy()
  512. /*++
  513. Routine Description:
  514. WM_DESTROY handler. Clean up internal data
  515. Arguments:
  516. None
  517. Return Value:
  518. None
  519. --*/
  520. {
  521. CInetPropertyPage::OnDestroy();
  522. if (m_ocx_LogProperties.m_hWnd)
  523. {
  524. m_ocx_LogProperties.Terminate();
  525. }
  526. }