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.

699 lines
17 KiB

  1. //============================================================================
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: portdlg.cpp
  5. //
  6. // History:
  7. // 09/22/96 Abolade Gbadegesin Created.
  8. //
  9. // Implementation of the port-status dialog.
  10. //============================================================================
  11. #include "stdafx.h"
  12. #include "dialog.h"
  13. #include "rtrutilp.h"
  14. extern "C" {
  15. #include "ras.h"
  16. }
  17. #include "portdlg.h"
  18. #include "rtrstr.h"
  19. #include "iface.h"
  20. #include "ports.h"
  21. #include "raserror.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. //----------------------------------------------------------------------------
  28. // Class: CPortDlg
  29. //
  30. //----------------------------------------------------------------------------
  31. //----------------------------------------------------------------------------
  32. // Function: CPortDlg::CPortDlg
  33. //
  34. // Constructor: initialize the base-class and the dialog's data.
  35. //----------------------------------------------------------------------------
  36. CPortDlg::CPortDlg(
  37. LPCTSTR pszServer,
  38. HANDLE hServer,
  39. HANDLE hPort,
  40. ITFSNode* pPortsNode,
  41. CWnd* pParent
  42. ) : CBaseDialog (IDD_DDM_PORT, pParent),
  43. m_stServer(pszServer)
  44. {
  45. m_hServer = hServer;
  46. m_hPort = hPort;
  47. m_spPortsNode.Set(pPortsNode);
  48. m_bChanged = FALSE;
  49. }
  50. //----------------------------------------------------------------------------
  51. // Function: CPortDlg::DoDataExchange
  52. //
  53. // DDX handler.
  54. //----------------------------------------------------------------------------
  55. VOID
  56. CPortDlg::DoDataExchange(
  57. CDataExchange* pDX
  58. ) {
  59. CBaseDialog::DoDataExchange(pDX);
  60. DDX_Control(pDX, IDC_DP_COMBO_PORTLIST, m_comboPorts);
  61. }
  62. BEGIN_MESSAGE_MAP(CPortDlg, CBaseDialog)
  63. ON_COMMAND(IDC_DP_BTN_RESET, OnReset)
  64. ON_COMMAND(IDC_DP_BTN_HANGUP, OnHangUp)
  65. ON_COMMAND(IDC_DP_BTN_REFRESH, OnRefresh)
  66. ON_CBN_SELENDOK(IDC_DP_COMBO_PORTLIST, OnSelendokPortList)
  67. END_MESSAGE_MAP()
  68. BOOL
  69. CPortDlg::OnInitDialog(
  70. ) {
  71. CBaseDialog::OnInitDialog();
  72. RefreshItem(m_hPort);
  73. return FALSE;
  74. }
  75. BOOL
  76. CPortDlg::RefreshItem(
  77. HANDLE hPort,
  78. BOOL bDisconnected
  79. ) {
  80. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  81. DWORD dwErr, dwTotal;
  82. DWORD rp0Count, rc0Count;
  83. BYTE* rp0Table, *rc0Table;
  84. BOOL bChanged = FALSE;
  85. DWORD rasmanCount = 0, dwSize;
  86. BYTE * pRasmanPorts = NULL;
  87. HANDLE hRasHandle = INVALID_HANDLE_VALUE;
  88. rp0Table = rc0Table = 0;
  89. do {
  90. //
  91. // Retrieve an array of ports
  92. // to be used to fill the combo-box
  93. //
  94. dwErr = ::MprAdminPortEnum(
  95. m_hServer,
  96. // (RAS_SERVER_HANDLE)m_pRootNode->QueryDdmHandle(),
  97. 0,
  98. INVALID_HANDLE_VALUE,
  99. (BYTE**)&rp0Table,
  100. (DWORD)-1,
  101. &rp0Count,
  102. &dwTotal,
  103. NULL
  104. );
  105. if (dwErr != NO_ERROR) { break; }
  106. // if the caller signals explicitely that the port was disconnected
  107. // alter at this point the structure returned my MprAdminPortEnum.
  108. // This is done because ::MprAdminPortDisconnect() is disconnecting synchronously
  109. // the port, but does not update the internal data synchronously!
  110. if (bDisconnected)
  111. {
  112. INT i;
  113. RAS_PORT_0* prp0;
  114. for (i = 0, prp0 = (RAS_PORT_0*)rp0Table; i < (INT)rp0Count; i++, prp0++)
  115. {
  116. if (prp0->hPort == hPort)
  117. {
  118. prp0->dwPortCondition = RAS_PORT_DISCONNECTED;
  119. prp0->hConnection = INVALID_HANDLE_VALUE;
  120. break;
  121. }
  122. }
  123. }
  124. //
  125. // Retrieve an array of connections
  126. //
  127. dwErr = ::MprAdminConnectionEnum(
  128. // (RAS_SERVER_HANDLE)m_pRootNode->QueryDdmHandle(),
  129. m_hServer,
  130. 0,
  131. (BYTE**)&rc0Table,
  132. (DWORD)-1,
  133. &rc0Count,
  134. &dwTotal,
  135. NULL
  136. );
  137. if (dwErr != NO_ERROR) { break; }
  138. //
  139. // Do the refresh of the display,
  140. // selecting the item specified by the caller.
  141. //
  142. bChanged = Refresh(rp0Table,
  143. rp0Count,
  144. rc0Table,
  145. rc0Count,
  146. hRasHandle,
  147. pRasmanPorts,
  148. rasmanCount,
  149. hPort);
  150. dwErr = NO_ERROR;
  151. } while (FALSE);
  152. delete pRasmanPorts;
  153. if (hRasHandle != INVALID_HANDLE_VALUE)
  154. RasRpcDisconnectServer(hRasHandle);
  155. if (rc0Table) { ::MprAdminBufferFree(rc0Table); }
  156. if (rp0Table) { ::MprAdminBufferFree(rp0Table); }
  157. if (dwErr != NO_ERROR) {
  158. TCHAR szText[1024];
  159. FormatSystemError(HRESULT_FROM_WIN32(dwErr),
  160. szText, DimensionOf(szText),
  161. IDS_ERR_INITDLGERROR, FSEFLAG_ANYMESSAGE);
  162. AfxMessageBox(szText);
  163. EndDialog(IDCANCEL);
  164. }
  165. return bChanged;
  166. }
  167. VOID
  168. CPortDlg::OnHangUp(
  169. ) {
  170. INT iSel;
  171. HANDLE hPort;
  172. DWORD dwErr;
  173. iSel = m_comboPorts.GetCurSel();
  174. if (iSel == CB_ERR) { return; }
  175. hPort = (HANDLE)m_comboPorts.GetItemData(iSel);
  176. dwErr = ::MprAdminPortDisconnect(
  177. // (RAS_SERVER_HANDLE)m_pRootNode->QueryDdmHandle(),
  178. m_hServer,
  179. hPort
  180. );
  181. m_bChanged |= RefreshItem(hPort, dwErr == NO_ERROR);
  182. }
  183. VOID
  184. CPortDlg::OnReset(
  185. ) {
  186. INT iSel;
  187. HANDLE hPort;
  188. iSel = m_comboPorts.GetCurSel();
  189. if (iSel == CB_ERR) { return; }
  190. hPort = (HANDLE)m_comboPorts.GetItemData(iSel);
  191. ::MprAdminPortClearStats(
  192. // (RAS_SERVER_HANDLE)m_pRootNode->QueryDdmHandle(),
  193. m_hServer,
  194. hPort
  195. );
  196. m_bChanged |= RefreshItem(INVALID_HANDLE_VALUE);
  197. }
  198. VOID
  199. CPortDlg::OnSelendokPortList(
  200. ) {
  201. m_bChanged |= RefreshItem(INVALID_HANDLE_VALUE);
  202. }
  203. VOID
  204. CPortDlg::OnRefresh(
  205. ) {
  206. m_bChanged |= RefreshItem(INVALID_HANDLE_VALUE);
  207. }
  208. BOOL
  209. CPortDlg::PortHasChanged(
  210. ITFSNode *pPortsNode,
  211. RAS_PORT_0 *pRP0)
  212. {
  213. SPITFSNodeEnum spEnum;
  214. SPITFSNode spChildNode;
  215. pPortsNode->GetEnum(&spEnum);
  216. for (;spEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release())
  217. {
  218. InterfaceNodeData * pChildData;
  219. pChildData = GET_INTERFACENODEDATA(spChildNode);
  220. Assert(pChildData);
  221. if (pChildData->m_rgData[PORTS_SI_PORT].m_ulData ==
  222. (ULONG_PTR) pRP0->hPort)
  223. {
  224. BOOL bChanged;
  225. bChanged = ((DWORD)pRP0->dwPortCondition != pChildData->m_rgData[PORTS_SI_STATUS].m_dwData);
  226. m_bChanged |= bChanged;
  227. return bChanged;
  228. }
  229. }
  230. return FALSE;
  231. }
  232. BOOL
  233. CPortDlg::Refresh(
  234. BYTE* rp0Table,
  235. DWORD rp0Count,
  236. BYTE* rc0Table,
  237. DWORD rc0Count,
  238. HANDLE hRasHandle,
  239. BYTE * pRasmanPorts,
  240. DWORD rasmanCount,
  241. VOID* pParam
  242. ) {
  243. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  244. DWORD dwErr = ERROR_SUCCESS;
  245. CString sItem;
  246. RAS_PORT_0* prp0;
  247. RAS_PORT_1* prp1;
  248. RAS_CONNECTION_0* prc0;
  249. RAS_CONNECTION_1* prc1;
  250. INT i, j, iSel, count;
  251. HANDLE hPort, hPortSel = NULL, *pPortTable;
  252. TCHAR szName[256];
  253. TCHAR szNumber[32];
  254. BOOL bChanged = FALSE;
  255. RasmanPortMap portMap;
  256. hPortSel = (HANDLE)pParam;
  257. //
  258. // Fill an array of port-handles with the ports which are already
  259. // in the combobox.
  260. //
  261. count = m_comboPorts.GetCount();
  262. if (count) {
  263. pPortTable = new HANDLE[count];
  264. }
  265. for (i = 0; i < count; i++) {
  266. pPortTable[i] = (HANDLE)m_comboPorts.GetItemData(i);
  267. }
  268. // Windows NT Bug : 338611
  269. // To make this faster, we need to create a hash table of
  270. // the RasPortEnum data. Note: this class relies on the
  271. // pbPorts being valid when calling any functions in the class.
  272. // ------------------------------------------------------------
  273. portMap.Init(hRasHandle, (RASMAN_PORT *) pRasmanPorts, rasmanCount);
  274. //
  275. // Refresh the combobox with port-names;
  276. // We do this in two passes, first adding the names of ports
  277. // which aren't already in the combobox,
  278. // and then removing the names of ports which aren't
  279. // in the table of ports ('rp0Table').
  280. //
  281. for (i = 0, prp0 = (RAS_PORT_0*)rp0Table; i < (INT)rp0Count; i++, prp0++) {
  282. //
  283. // See if port 'i' is already in the combobox.
  284. //
  285. for (j = 0; j < count; j++) {
  286. if (pPortTable[j] == prp0->hPort) { break; }
  287. }
  288. if (j < count) { continue; }
  289. // Check to see that this port isn't dialout active,
  290. // if so, we can ignore it
  291. // ------------------------------------------------------------
  292. if ( portMap.FIsDialoutActive(prp0->wszPortName) )
  293. {
  294. continue;
  295. }
  296. //
  297. // Port 'i' isn't already in the combobox, so add it.
  298. //
  299. FormatRasPortName((BYTE *) prp0, szName, DimensionOf(szName));
  300. sItem = szName;
  301. iSel = m_comboPorts.AddString(sItem);
  302. if (iSel >= 0) {
  303. m_comboPorts.SetItemData(iSel, (LONG_PTR)prp0->hPort);
  304. if (prp0->hPort == hPortSel) { m_comboPorts.SetCurSel(iSel); }
  305. bChanged = TRUE;
  306. }
  307. }
  308. if (count) { delete [] pPortTable; }
  309. //
  310. // Second stage: remove all ports which aren't in 'rp0Table'.
  311. // This is only necessary if there were any ports in the combobox before.
  312. //
  313. if (count > 0) {
  314. count = m_comboPorts.GetCount();
  315. for (i = 0; i < count; i++) {
  316. hPort = (HANDLE)m_comboPorts.GetItemData(i);
  317. //
  318. // See if the port is in 'rp0Table'.
  319. //
  320. for (j = 0, prp0 = (RAS_PORT_0*)rp0Table; j < (INT)rp0Count;
  321. j++, prp0++) {
  322. if (prp0->hPort == hPort) { break; }
  323. }
  324. if (j < (INT)rp0Count) {
  325. if (prp0->hPort == hPortSel) { m_comboPorts.SetCurSel(i); }
  326. continue;
  327. }
  328. //
  329. // The port wasn't found in 'rp0Table',
  330. // so remove it from the combobox,
  331. // and adjust the enumeration indices.
  332. //
  333. m_comboPorts.DeleteString(i);
  334. --i; --count;
  335. bChanged = TRUE;
  336. }
  337. }
  338. // Clear out the address fields
  339. SetDlgItemText(IDC_DP_TEXT_IPADDRESS, c_szEmpty);
  340. SetDlgItemText(IDC_DP_TEXT_IPXADDRESS, c_szEmpty);
  341. SetDlgItemText(IDC_DP_TEXT_NBFADDRESS, c_szEmpty);
  342. SetDlgItemText(IDC_DP_TEXT_ATLKADDRESS, c_szEmpty);
  343. // Clear out the line bps field
  344. SetDlgItemText(IDC_DP_TEXT_LINEBPS, c_szEmpty);
  345. SetDlgItemText(IDC_DP_TEXT_DURATION, c_szEmpty);
  346. SetDlgItemText(IDC_DP_TEXT_BYTESIN, c_szEmpty);
  347. SetDlgItemText(IDC_DP_TEXT_BYTESOUT, c_szEmpty);
  348. SetDlgItemText(IDC_DP_TEXT_TIMEOUT, c_szEmpty);
  349. SetDlgItemText(IDC_DP_TEXT_ALIGNMENT, c_szEmpty);
  350. SetDlgItemText(IDC_DP_TEXT_FRAMING, c_szEmpty);
  351. SetDlgItemText(IDC_DP_TEXT_HWOVERRUN, c_szEmpty);
  352. SetDlgItemText(IDC_DP_TEXT_BUFOVERRUN, c_szEmpty);
  353. SetDlgItemText(IDC_DP_TEXT_CRC, c_szEmpty);
  354. //
  355. // If there is no selection select the first item
  356. //
  357. if ((iSel = m_comboPorts.GetCurSel()) == CB_ERR) {
  358. iSel = m_comboPorts.SetCurSel(0);
  359. }
  360. if (iSel == CB_ERR) { return bChanged; }
  361. //
  362. // Update the display with information for the selected item
  363. //
  364. hPort = (HANDLE)m_comboPorts.GetItemData(iSel);
  365. for (i = 0, prp0 = (RAS_PORT_0*)rp0Table; i < (INT)rp0Count;
  366. i++, prp0++) {
  367. if (prp0->hPort == hPort) { break; }
  368. }
  369. if (i >= (INT)rp0Count) { return bChanged; }
  370. // if the ports are the same, check if the currently selected port did not change!
  371. if (!bChanged)
  372. {
  373. // check if the data returned here matches with the one handled by the console.
  374. // if it doesn't, set bChanged to TRUE, saying that something has changed.
  375. // subsequently, the caller will know to initiate a global refresh.
  376. bChanged = PortHasChanged(m_spPortsNode, prp0);
  377. }
  378. //
  379. // First update the RAS_PORT_0-based information
  380. //
  381. FormatDuration(prp0->dwConnectDuration, sItem, UNIT_SECONDS);
  382. SetDlgItemText(IDC_DP_TEXT_DURATION, sItem);
  383. //
  384. // Now if the port is connected, find its RAS_CONNECTION_0
  385. //
  386. prc0 = NULL;
  387. if (prp0->hConnection != INVALID_HANDLE_VALUE) {
  388. for (i = 0, prc0 = (RAS_CONNECTION_0*)rc0Table; i < (INT)rc0Count;
  389. i++, prc0++) {
  390. if (prc0->hConnection == prp0->hConnection) { break; }
  391. }
  392. if (i >= (INT)rc0Count) { prc0 = NULL; }
  393. }
  394. sItem = PortConditionToCString(prp0->dwPortCondition);
  395. if (!prc0) {
  396. //
  397. // The port is not connected; show only the port condition.
  398. //
  399. SetDlgItemText(IDC_DP_EDIT_CONDITION, sItem);
  400. if (GetFocus() == GetDlgItem(IDC_DP_BTN_HANGUP))
  401. {
  402. GetDlgItem(IDC_DP_BTN_RESET)->SetFocus();
  403. }
  404. GetDlgItem(IDC_DP_BTN_HANGUP)->EnableWindow(FALSE);
  405. }
  406. else {
  407. CString sCondition;
  408. //
  409. // Show condition as "Port condition (Connection)".
  410. //
  411. sCondition.Format(TEXT("%s (%ls)"), sItem, prc0->wszInterfaceName);
  412. SetDlgItemText(IDC_DP_EDIT_CONDITION, sCondition);
  413. GetDlgItem(IDC_DP_BTN_HANGUP)->EnableWindow(TRUE);
  414. }
  415. do {
  416. //
  417. // Set the information in the dialog text-controls
  418. //
  419. // Windows NT Bug : 139866
  420. // if we are not authenticated, do not show this information
  421. if (prp0->dwPortCondition == RAS_PORT_AUTHENTICATED)
  422. {
  423. //
  424. // Now retrieve the RAS_PORT_1 information for this port.
  425. //
  426. dwErr = ::MprAdminPortGetInfo(
  427. m_hServer,
  428. 1,
  429. prp0->hPort,
  430. (BYTE**)&prp1
  431. );
  432. if (dwErr != NO_ERROR) { break; }
  433. FormatNumber(prp1->dwLineSpeed, szNumber, DimensionOf(szNumber), FALSE);
  434. SetDlgItemText(IDC_DP_TEXT_LINEBPS, szNumber);
  435. FormatNumber(prp1->dwBytesRcved, szNumber, DimensionOf(szNumber), FALSE);
  436. SetDlgItemText(IDC_DP_TEXT_BYTESIN, szNumber);
  437. FormatNumber(prp1->dwBytesXmited, szNumber, DimensionOf(szNumber), FALSE);
  438. SetDlgItemText(IDC_DP_TEXT_BYTESOUT, szNumber);
  439. FormatNumber(prp1->dwCrcErr, szNumber, DimensionOf(szNumber), FALSE);
  440. SetDlgItemText(IDC_DP_TEXT_CRC, szNumber);
  441. FormatNumber(prp1->dwTimeoutErr, szNumber, DimensionOf(szNumber), FALSE);
  442. SetDlgItemText(IDC_DP_TEXT_TIMEOUT, szNumber);
  443. FormatNumber(prp1->dwAlignmentErr, szNumber, DimensionOf(szNumber), FALSE);
  444. SetDlgItemText(IDC_DP_TEXT_ALIGNMENT, szNumber);
  445. FormatNumber(prp1->dwFramingErr, szNumber, DimensionOf(szNumber), FALSE);
  446. SetDlgItemText(IDC_DP_TEXT_FRAMING, szNumber);
  447. FormatNumber(prp1->dwHardwareOverrunErr, szNumber, DimensionOf(szNumber), FALSE);
  448. SetDlgItemText(IDC_DP_TEXT_HWOVERRUN, szNumber);
  449. FormatNumber(prp1->dwBufferOverrunErr, szNumber, DimensionOf(szNumber), FALSE);
  450. SetDlgItemText(IDC_DP_TEXT_BUFOVERRUN, szNumber);
  451. ::MprAdminBufferFree(prp1);
  452. }
  453. //
  454. // Finally, if the port is connected, retreive RAS_CONNECTION_1 info
  455. // and use it to fill the network-registration controls.
  456. //
  457. if (prp0->dwPortCondition != RAS_PORT_AUTHENTICATED)
  458. break;
  459. // if (prp0->hConnection == INVALID_HANDLE_VALUE) { break; }
  460. dwErr = ::MprAdminConnectionGetInfo(
  461. // (RAS_SERVER_HANDLE)m_pRootNode->QueryDdmHandle(),
  462. m_hServer,
  463. 1,
  464. prp0->hConnection,
  465. (BYTE**)&prc1
  466. );
  467. if (dwErr != NO_ERROR || !prc1) { break; }
  468. //
  469. // Fill in the network registration info for projected networks.
  470. //
  471. if (prc1->PppInfo.ip.dwError == NO_ERROR) {
  472. SetDlgItemTextW(IDC_DP_TEXT_IPADDRESS, prc1->PppInfo.ip.wszRemoteAddress);
  473. }
  474. if (prc1->PppInfo.ipx.dwError == NO_ERROR) {
  475. SetDlgItemTextW(IDC_DP_TEXT_IPXADDRESS, prc1->PppInfo.ipx.wszAddress);
  476. }
  477. if (prc1->PppInfo.nbf.dwError == NO_ERROR) {
  478. SetDlgItemTextW(IDC_DP_TEXT_NBFADDRESS, prc1->PppInfo.nbf.wszWksta);
  479. }
  480. if (prc1->PppInfo.at.dwError == NO_ERROR)
  481. {
  482. SetDlgItemTextW(IDC_DP_TEXT_ATLKADDRESS,
  483. prc1->PppInfo.at.wszAddress);
  484. }
  485. ::MprAdminBufferFree(prc1);
  486. } while (FALSE);
  487. if (dwErr != NO_ERROR) {
  488. TCHAR szText[1024];
  489. FormatSystemError(HRESULT_FROM_WIN32(dwErr),
  490. szText, DimensionOf(szText),
  491. IDS_ERR_INITDLGERROR, FSEFLAG_ANYMESSAGE);
  492. AfxMessageBox(szText);
  493. EndDialog(IDCANCEL);
  494. }
  495. return bChanged;
  496. }