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.

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