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.

429 lines
13 KiB

  1. /*
  2. File multilink.c
  3. Implements the multilink dialog display by the connections
  4. status monitor
  5. Paul Mayfield 10/17/97
  6. */
  7. #include "rassrv.h"
  8. #define MTL_TIMER_ID 1
  9. typedef struct _MULTILINKDATA {
  10. HANDLE hConn;
  11. RAS_PORT_0 * pPorts;
  12. RAS_PORT_0 * pCurPort0;
  13. RAS_PORT_1 * pCurPort1;
  14. DWORD dwCurPort;
  15. DWORD dwPortCount;
  16. } MULTILINKDATA;
  17. // This dialog procedure responds to messages send to the
  18. // mtleral tab.
  19. BOOL CALLBACK mtlUiDialogProc(HWND hwndDlg,
  20. UINT uMsg,
  21. WPARAM wParam,
  22. LPARAM lParam);
  23. // Fills in the property sheet structure with the information required to display
  24. // the multilink tab.
  25. DWORD mtlUiGetPropertyPage(LPPROPSHEETPAGE ppage, DWORD dwUserData) {
  26. MULTILINKDATA * mld;
  27. // Create the multilink data to send
  28. mld = (MULTILINKDATA*) malloc (sizeof (MULTILINKDATA));
  29. ZeroMemory(mld, sizeof(MULTILINKDATA));
  30. mld->hConn = (HANDLE)dwUserData;
  31. // Initialize
  32. ZeroMemory(ppage, sizeof(LPPROPSHEETPAGE));
  33. // Fill in the values
  34. ppage->dwSize = sizeof(PROPSHEETPAGE);
  35. ppage->hInstance = Globals.hInstDll;
  36. ppage->pszTemplate = MAKEINTRESOURCE(IDD_MULTILINKTAB);
  37. ppage->pfnDlgProc = mtlUiDialogProc;
  38. ppage->pfnCallback = NULL;
  39. ppage->dwFlags = 0;
  40. ppage->lParam = (LPARAM)mld;
  41. return NO_ERROR;
  42. }
  43. // Error reporting
  44. void mtlUiErrorMessageBox(HWND hwnd, DWORD err) {
  45. WCHAR buf[1024];
  46. FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,NULL,err,(DWORD)NULL,buf,1024,NULL);
  47. MessageBoxW(hwnd,
  48. buf,
  49. L"Dialup Server Configuration Error",
  50. MB_OK | MB_ICONERROR | MB_APPLMODAL);
  51. }
  52. // Formats an unsigned number with commas, etc.
  53. PWCHAR mtlFormatDword(DWORD dwVal) {
  54. static WCHAR ret[64];
  55. WCHAR num[64];
  56. int i = 0, tmp, j, k;
  57. if (dwVal == 0) {
  58. ret[0] = (WCHAR)'0';
  59. ret[1] = (WCHAR)0;
  60. return ret;
  61. }
  62. // Get the value in reverse order
  63. while (dwVal) {
  64. tmp = dwVal % 10;
  65. dwVal /= 10;
  66. num[i++] = (WCHAR)('0' + tmp);
  67. }
  68. num[i] = (WCHAR)0;
  69. // Add commas
  70. k = 0;
  71. for (j = 0; j < i; j++) {
  72. if (k%4 == 3)
  73. ret[k++] = (WCHAR)',';
  74. ret[k++] = num[j];
  75. }
  76. ret[k] = 0;
  77. k--;
  78. // reverse the string
  79. for (j=0; j < (k+1)/2; j++) {
  80. tmp = ret[j];
  81. ret[j] = ret[k-j];
  82. ret[k-j] = tmp;
  83. }
  84. return ret;
  85. }
  86. // Formats a string representing the time that a connection is connected
  87. PWCHAR mtlFormatTime(DWORD dwSeconds) {
  88. DWORD dwSec, dwHr, dwMin;
  89. static WCHAR ret[16];
  90. dwSec = dwSeconds % 60;
  91. dwMin = dwSeconds / 60;
  92. dwHr = dwSeconds / 3600;
  93. wsprintfW(ret, L"%02d:%02d:%02d", dwHr, dwMin, dwSec);
  94. return ret;
  95. }
  96. // Formats a string to display connection speed
  97. PWCHAR mtlFormatSpeed(DWORD dwBps) {
  98. static WCHAR ret[64];
  99. wsprintfW(ret, L"%s bps", mtlFormatDword(dwBps));
  100. return ret;
  101. }
  102. // The list view control requires the list of icons it will display
  103. // to be provided up front. This function initializes and presents
  104. // this list.
  105. DWORD mtlUiInitializeListViewIcons(HWND hwndLV) {
  106. return NO_ERROR;
  107. }
  108. // Returns the index of an to display icon based on the type of incoming
  109. // connection and whether or not it should be checked.
  110. int mtlGetIconIndex(DWORD dwType, BOOL bEnabled) {
  111. if (bEnabled)
  112. return dwType + 1;
  113. return dwType;
  114. }
  115. // Fills in the user list view with the names of the users stored in the
  116. // user database provide. Also, initializes the checked/unchecked status
  117. // of each user.
  118. DWORD mtlUiFillPortList(HWND hwndLV, MULTILINKDATA * mld) {
  119. LV_ITEM lvi;
  120. DWORD i, dwErr, dwType;
  121. char pszAName[1024];
  122. // Add the images that this list item will display
  123. dwErr = mtlUiInitializeListViewIcons(hwndLV);
  124. if (dwErr != NO_ERROR)
  125. return dwErr;
  126. // Initialize the list item
  127. ZeroMemory(&lvi, sizeof(LV_ITEM));
  128. lvi.mask = LVIF_TEXT;
  129. // lvi.mask = LVIF_TEXT | LVIF_IMAGE;
  130. // Looop through all of the users adding their names as we go
  131. for (i=0; i<mld->dwPortCount; i++) {
  132. //WideCharToMultiByte(CP_ACP,0,mld->pPorts[i].wszPortName,-1,pszAName,1024,NULL,NULL);
  133. lvi.iItem = i;
  134. //lvi.pszText = pszAName;
  135. lvi.pszText = mld->pPorts[i].wszPortName;
  136. //lvi.cchTextMax = strlen(pszAName) + 1;
  137. lvi.cchTextMax = wcslen(mld->pPorts[i].wszPortName) + 1;
  138. ListView_InsertItem(hwndLV,&lvi);
  139. }
  140. return NO_ERROR;
  141. }
  142. // Loads the current port
  143. DWORD mtlLoadCurrentPort(MULTILINKDATA * mld) {
  144. DWORD dwErr;
  145. // Cleanup the old data
  146. if (mld->pCurPort0)
  147. MprAdminBufferFree(mld->pCurPort0);
  148. if (mld->pCurPort1)
  149. MprAdminBufferFree(mld->pCurPort1);
  150. dwErr = MprAdminPortGetInfo(Globals.hRasServer,
  151. 1,
  152. mld->pPorts[mld->dwCurPort].hPort,
  153. (LPBYTE*)&mld->pCurPort1);
  154. dwErr = MprAdminPortGetInfo(Globals.hRasServer,
  155. 0,
  156. mld->pPorts[mld->dwCurPort].hPort,
  157. (LPBYTE*)&mld->pCurPort0);
  158. return dwErr;
  159. }
  160. // Initializes the multilink data
  161. DWORD mtlLoadPortData(MULTILINKDATA * mld, DWORD dwCur) {
  162. DWORD dwTot, dwErr;
  163. // Set the current port and load the data
  164. mld->dwCurPort = dwCur;
  165. // Cleanup
  166. if (mld->pPorts)
  167. MprAdminBufferFree(mld->pPorts);
  168. // Get the count of ports
  169. dwErr = MprAdminPortEnum (Globals.hRasServer,
  170. 0,
  171. mld->hConn,
  172. (LPBYTE*)&mld->pPorts,
  173. 1024*1024,
  174. &mld->dwPortCount,
  175. &dwTot,
  176. NULL);
  177. if (dwErr != NO_ERROR)
  178. return dwErr;
  179. if (mld->dwPortCount) {
  180. dwErr = mtlLoadCurrentPort(mld);
  181. if (dwErr != NO_ERROR)
  182. return NO_ERROR;
  183. }
  184. return NO_ERROR;
  185. }
  186. // Updates the dialog with the current statistics stored in mld
  187. DWORD mtlUpdateStats(HWND hwndDlg, MULTILINKDATA * mld) {
  188. WCHAR buf[128];
  189. DWORD dwErr = 0;
  190. // Mark the bytes in and out
  191. SetWindowTextW(GetDlgItem(hwndDlg, IDC_BYTESIN), mtlFormatDword(mld->pCurPort1->dwBytesRcved));
  192. SetWindowTextW(GetDlgItem(hwndDlg, IDC_BYTESOUT), mtlFormatDword(mld->pCurPort1->dwBytesXmited));
  193. // Mark the compression ratios
  194. wsprintfW(buf, L"%d%%", mld->pCurPort1->dwCompressionRatioIn);
  195. SetWindowTextW(GetDlgItem(hwndDlg, IDC_COMPIN), buf);
  196. wsprintfW(buf, L"%d%%", mld->pCurPort1->dwCompressionRatioOut);
  197. SetWindowTextW(GetDlgItem(hwndDlg, IDC_COMPOUT), buf);
  198. // Mark the errors
  199. dwErr = mld->pCurPort1->dwCrcErr +
  200. mld->pCurPort1->dwTimeoutErr +
  201. mld->pCurPort1->dwAlignmentErr +
  202. mld->pCurPort1->dwHardwareOverrunErr +
  203. mld->pCurPort1->dwFramingErr +
  204. mld->pCurPort1->dwBufferOverrunErr;
  205. wsprintfW(buf, L"%d", dwErr);
  206. SetWindowTextW(GetDlgItem(hwndDlg, IDC_ERRORIN), buf);
  207. SetWindowTextW(GetDlgItem(hwndDlg, IDC_ERROROUT), L"0");
  208. // Mark the duration
  209. SetWindowTextW(GetDlgItem(hwndDlg, IDC_DURATION),
  210. mtlFormatTime(mld->pCurPort0->dwConnectDuration));
  211. // Mark the speed
  212. SetWindowTextW(GetDlgItem(hwndDlg, IDC_SPEED),
  213. mtlFormatSpeed(mld->pCurPort1->dwLineSpeed));
  214. return NO_ERROR;
  215. }
  216. // Initializes the mtleral tab. By now a handle to the mtleral database
  217. // has been placed in the user data of the dialog
  218. DWORD mtlUiInitializeDialog(HWND hwndDlg, WPARAM wParam, LPARAM lParam) {
  219. DWORD dwErr, dwCount;
  220. BOOL bFlag;
  221. HANDLE hConn, hMiscDatabase;
  222. HWND hwndLV;
  223. LV_COLUMN lvc;
  224. MULTILINKDATA * mld;
  225. LPPROPSHEETPAGE ppage;
  226. // Set the Timer
  227. SetTimer(hwndDlg, MTL_TIMER_ID, 500, NULL);
  228. // Set the data for this dialog
  229. ppage = (LPPROPSHEETPAGE)lParam;
  230. mld = (MULTILINKDATA*)(ppage->lParam);
  231. SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)mld);
  232. // Initialize all of the values in the multilink data structure
  233. mtlLoadPortData(mld, 0);
  234. // Cause the list view to send LV_EXTENSION_??? messages and to do full
  235. // row select
  236. hwndLV = GetDlgItem(hwndDlg, IDC_PORTLIST);
  237. lvxExtend(hwndLV);
  238. ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
  239. // Fill in the list view will all available mtlices
  240. mtlUiFillPortList(hwndLV, mld);
  241. // Select the first item in the list view if any items exist
  242. dwCount = mld->dwPortCount;
  243. if (dwCount)
  244. ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff);
  245. // Add a colum so that we'll display in report view
  246. lvc.mask = LVCF_FMT;
  247. lvc.fmt = LVCFMT_LEFT;
  248. ListView_InsertColumn(hwndLV,0,&lvc);
  249. ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER);
  250. // Update the statistics
  251. mtlUpdateStats(hwndDlg, mld);
  252. return NO_ERROR;
  253. }
  254. // Updates the current port
  255. DWORD mtlUpdateCurPort(MULTILINKDATA * mld, DWORD dwNewPort) {
  256. mld->dwCurPort = dwNewPort;
  257. return mtlLoadCurrentPort(mld);
  258. }
  259. // Hangsup the current port
  260. DWORD mtlHangup(HWND hwndDlg, MULTILINKDATA * mld) {
  261. DWORD dwErr;
  262. HWND hwndLV = GetDlgItem(hwndDlg, IDC_PORTLIST);
  263. if ((dwErr = MprAdminPortDisconnect(Globals.hRasServer, mld->pCurPort0->hPort)) != NO_ERROR)
  264. return dwErr;
  265. // There are no more ports if mtlLoadPortData returns an error
  266. if ((dwErr = mtlLoadPortData(mld, 0)) != NO_ERROR)
  267. DestroyWindow(hwndDlg);
  268. else {
  269. ListView_DeleteAllItems(hwndLV);
  270. mtlUiFillPortList(hwndLV, mld);
  271. ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff);
  272. mtlUpdateStats(hwndDlg, mld);
  273. }
  274. return NO_ERROR;
  275. }
  276. // Cleansup the mtleral tab as it is being destroyed
  277. DWORD mtlUiCleanupDialog(HWND hwndDlg, WPARAM wParam, LPARAM lParam) {
  278. // Cleanup the data
  279. MULTILINKDATA * mld = (MULTILINKDATA *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  280. if (mld) {
  281. if (mld->pCurPort0)
  282. MprAdminBufferFree(mld->pCurPort0);
  283. if (mld->pCurPort1)
  284. MprAdminBufferFree(mld->pCurPort1);
  285. if (mld)
  286. free(mld);
  287. }
  288. // Stop the timer
  289. KillTimer(hwndDlg, MTL_TIMER_ID);
  290. return NO_ERROR;
  291. }
  292. // This is the dialog procedure that responds to messages sent to the
  293. // mtleral tab.
  294. BOOL CALLBACK mtlUiDialogProc(HWND hwndDlg,
  295. UINT uMsg,
  296. WPARAM wParam,
  297. LPARAM lParam) {
  298. NMHDR* pNotifyData;
  299. NM_LISTVIEW* pLvNotifyData;
  300. LV_KEYDOWN* pLvKeyDown;
  301. MULTILINKDATA * mld = (MULTILINKDATA*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  302. // Process other messages as normal
  303. switch (uMsg) {
  304. case WM_INITDIALOG:
  305. return mtlUiInitializeDialog(hwndDlg, wParam, lParam);
  306. case WM_NOTIFY:
  307. pNotifyData = (NMHDR*)lParam;
  308. switch (pNotifyData->code) {
  309. // The property sheet apply button was pressed
  310. case PSN_APPLY:
  311. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  312. return TRUE;
  313. // The property sheet cancel was pressed
  314. case PSN_RESET:
  315. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  316. break;
  317. // An item is changing state, keep track of any newly
  318. // selected item so space bar can toggle him.
  319. case LVN_ITEMCHANGING:
  320. pLvNotifyData = (NM_LISTVIEW*)lParam;
  321. if (pLvNotifyData->uNewState & LVIS_SELECTED) {
  322. mtlUpdateCurPort(mld, pLvNotifyData->iItem);
  323. mtlUpdateStats(hwndDlg, mld);
  324. }
  325. break;
  326. }
  327. break;
  328. // Called when the timer expires
  329. case WM_TIMER:
  330. mtlLoadCurrentPort(mld);
  331. mtlUpdateStats(hwndDlg, mld);
  332. break;
  333. // This is a custom message that we defined to toggle dialin permission
  334. // when the mouse is clicked on a user.
  335. case LV_EXTENSION_ITEMCLICKED:
  336. case LV_EXTENSION_ITEMDBLCLICKED:
  337. mtlUpdateCurPort(mld, wParam);
  338. mtlUpdateStats(hwndDlg, mld);
  339. break;
  340. case WM_COMMAND:
  341. if (wParam == IDC_HANGUP)
  342. mtlHangup(hwndDlg, mld);
  343. break;
  344. // Cleanup the work done at WM_INITDIALOG
  345. case WM_DESTROY:
  346. mtlUiCleanupDialog(hwndDlg, wParam, lParam);
  347. break;
  348. }
  349. return FALSE;
  350. }