/* File multilink.c Implements the multilink dialog display by the connections status monitor Paul Mayfield 10/17/97 */ #include "rassrv.h" #define MTL_TIMER_ID 1 typedef struct _MULTILINKDATA { HANDLE hConn; RAS_PORT_0 * pPorts; RAS_PORT_0 * pCurPort0; RAS_PORT_1 * pCurPort1; DWORD dwCurPort; DWORD dwPortCount; } MULTILINKDATA; // This dialog procedure responds to messages send to the // mtleral tab. BOOL CALLBACK mtlUiDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); // Fills in the property sheet structure with the information required to display // the multilink tab. DWORD mtlUiGetPropertyPage(LPPROPSHEETPAGE ppage, DWORD dwUserData) { MULTILINKDATA * mld; // Create the multilink data to send mld = (MULTILINKDATA*) malloc (sizeof (MULTILINKDATA)); ZeroMemory(mld, sizeof(MULTILINKDATA)); mld->hConn = (HANDLE)dwUserData; // Initialize ZeroMemory(ppage, sizeof(LPPROPSHEETPAGE)); // Fill in the values ppage->dwSize = sizeof(PROPSHEETPAGE); ppage->hInstance = Globals.hInstDll; ppage->pszTemplate = MAKEINTRESOURCE(IDD_MULTILINKTAB); ppage->pfnDlgProc = mtlUiDialogProc; ppage->pfnCallback = NULL; ppage->dwFlags = 0; ppage->lParam = (LPARAM)mld; return NO_ERROR; } // Error reporting void mtlUiErrorMessageBox(HWND hwnd, DWORD err) { WCHAR buf[1024]; FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,NULL,err,(DWORD)NULL,buf,1024,NULL); MessageBoxW(hwnd, buf, L"Dialup Server Configuration Error", MB_OK | MB_ICONERROR | MB_APPLMODAL); } // Formats an unsigned number with commas, etc. PWCHAR mtlFormatDword(DWORD dwVal) { static WCHAR ret[64]; WCHAR num[64]; int i = 0, tmp, j, k; if (dwVal == 0) { ret[0] = (WCHAR)'0'; ret[1] = (WCHAR)0; return ret; } // Get the value in reverse order while (dwVal) { tmp = dwVal % 10; dwVal /= 10; num[i++] = (WCHAR)('0' + tmp); } num[i] = (WCHAR)0; // Add commas k = 0; for (j = 0; j < i; j++) { if (k%4 == 3) ret[k++] = (WCHAR)','; ret[k++] = num[j]; } ret[k] = 0; k--; // reverse the string for (j=0; j < (k+1)/2; j++) { tmp = ret[j]; ret[j] = ret[k-j]; ret[k-j] = tmp; } return ret; } // Formats a string representing the time that a connection is connected PWCHAR mtlFormatTime(DWORD dwSeconds) { DWORD dwSec, dwHr, dwMin; static WCHAR ret[16]; dwSec = dwSeconds % 60; dwMin = dwSeconds / 60; dwHr = dwSeconds / 3600; wsprintfW(ret, L"%02d:%02d:%02d", dwHr, dwMin, dwSec); return ret; } // Formats a string to display connection speed PWCHAR mtlFormatSpeed(DWORD dwBps) { static WCHAR ret[64]; wsprintfW(ret, L"%s bps", mtlFormatDword(dwBps)); return ret; } // The list view control requires the list of icons it will display // to be provided up front. This function initializes and presents // this list. DWORD mtlUiInitializeListViewIcons(HWND hwndLV) { return NO_ERROR; } // Returns the index of an to display icon based on the type of incoming // connection and whether or not it should be checked. int mtlGetIconIndex(DWORD dwType, BOOL bEnabled) { if (bEnabled) return dwType + 1; return dwType; } // Fills in the user list view with the names of the users stored in the // user database provide. Also, initializes the checked/unchecked status // of each user. DWORD mtlUiFillPortList(HWND hwndLV, MULTILINKDATA * mld) { LV_ITEM lvi; DWORD i, dwErr, dwType; char pszAName[1024]; // Add the images that this list item will display dwErr = mtlUiInitializeListViewIcons(hwndLV); if (dwErr != NO_ERROR) return dwErr; // Initialize the list item ZeroMemory(&lvi, sizeof(LV_ITEM)); lvi.mask = LVIF_TEXT; // lvi.mask = LVIF_TEXT | LVIF_IMAGE; // Looop through all of the users adding their names as we go for (i=0; idwPortCount; i++) { //WideCharToMultiByte(CP_ACP,0,mld->pPorts[i].wszPortName,-1,pszAName,1024,NULL,NULL); lvi.iItem = i; //lvi.pszText = pszAName; lvi.pszText = mld->pPorts[i].wszPortName; //lvi.cchTextMax = strlen(pszAName) + 1; lvi.cchTextMax = wcslen(mld->pPorts[i].wszPortName) + 1; ListView_InsertItem(hwndLV,&lvi); } return NO_ERROR; } // Loads the current port DWORD mtlLoadCurrentPort(MULTILINKDATA * mld) { DWORD dwErr; // Cleanup the old data if (mld->pCurPort0) MprAdminBufferFree(mld->pCurPort0); if (mld->pCurPort1) MprAdminBufferFree(mld->pCurPort1); dwErr = MprAdminPortGetInfo(Globals.hRasServer, 1, mld->pPorts[mld->dwCurPort].hPort, (LPBYTE*)&mld->pCurPort1); dwErr = MprAdminPortGetInfo(Globals.hRasServer, 0, mld->pPorts[mld->dwCurPort].hPort, (LPBYTE*)&mld->pCurPort0); return dwErr; } // Initializes the multilink data DWORD mtlLoadPortData(MULTILINKDATA * mld, DWORD dwCur) { DWORD dwTot, dwErr; // Set the current port and load the data mld->dwCurPort = dwCur; // Cleanup if (mld->pPorts) MprAdminBufferFree(mld->pPorts); // Get the count of ports dwErr = MprAdminPortEnum (Globals.hRasServer, 0, mld->hConn, (LPBYTE*)&mld->pPorts, 1024*1024, &mld->dwPortCount, &dwTot, NULL); if (dwErr != NO_ERROR) return dwErr; if (mld->dwPortCount) { dwErr = mtlLoadCurrentPort(mld); if (dwErr != NO_ERROR) return NO_ERROR; } return NO_ERROR; } // Updates the dialog with the current statistics stored in mld DWORD mtlUpdateStats(HWND hwndDlg, MULTILINKDATA * mld) { WCHAR buf[128]; DWORD dwErr = 0; // Mark the bytes in and out SetWindowTextW(GetDlgItem(hwndDlg, IDC_BYTESIN), mtlFormatDword(mld->pCurPort1->dwBytesRcved)); SetWindowTextW(GetDlgItem(hwndDlg, IDC_BYTESOUT), mtlFormatDword(mld->pCurPort1->dwBytesXmited)); // Mark the compression ratios wsprintfW(buf, L"%d%%", mld->pCurPort1->dwCompressionRatioIn); SetWindowTextW(GetDlgItem(hwndDlg, IDC_COMPIN), buf); wsprintfW(buf, L"%d%%", mld->pCurPort1->dwCompressionRatioOut); SetWindowTextW(GetDlgItem(hwndDlg, IDC_COMPOUT), buf); // Mark the errors dwErr = mld->pCurPort1->dwCrcErr + mld->pCurPort1->dwTimeoutErr + mld->pCurPort1->dwAlignmentErr + mld->pCurPort1->dwHardwareOverrunErr + mld->pCurPort1->dwFramingErr + mld->pCurPort1->dwBufferOverrunErr; wsprintfW(buf, L"%d", dwErr); SetWindowTextW(GetDlgItem(hwndDlg, IDC_ERRORIN), buf); SetWindowTextW(GetDlgItem(hwndDlg, IDC_ERROROUT), L"0"); // Mark the duration SetWindowTextW(GetDlgItem(hwndDlg, IDC_DURATION), mtlFormatTime(mld->pCurPort0->dwConnectDuration)); // Mark the speed SetWindowTextW(GetDlgItem(hwndDlg, IDC_SPEED), mtlFormatSpeed(mld->pCurPort1->dwLineSpeed)); return NO_ERROR; } // Initializes the mtleral tab. By now a handle to the mtleral database // has been placed in the user data of the dialog DWORD mtlUiInitializeDialog(HWND hwndDlg, WPARAM wParam, LPARAM lParam) { DWORD dwErr, dwCount; BOOL bFlag; HANDLE hConn, hMiscDatabase; HWND hwndLV; LV_COLUMN lvc; MULTILINKDATA * mld; LPPROPSHEETPAGE ppage; // Set the Timer SetTimer(hwndDlg, MTL_TIMER_ID, 500, NULL); // Set the data for this dialog ppage = (LPPROPSHEETPAGE)lParam; mld = (MULTILINKDATA*)(ppage->lParam); SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)mld); // Initialize all of the values in the multilink data structure mtlLoadPortData(mld, 0); // Cause the list view to send LV_EXTENSION_??? messages and to do full // row select hwndLV = GetDlgItem(hwndDlg, IDC_PORTLIST); lvxExtend(hwndLV); ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT); // Fill in the list view will all available mtlices mtlUiFillPortList(hwndLV, mld); // Select the first item in the list view if any items exist dwCount = mld->dwPortCount; if (dwCount) ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff); // Add a colum so that we'll display in report view lvc.mask = LVCF_FMT; lvc.fmt = LVCFMT_LEFT; ListView_InsertColumn(hwndLV,0,&lvc); ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER); // Update the statistics mtlUpdateStats(hwndDlg, mld); return NO_ERROR; } // Updates the current port DWORD mtlUpdateCurPort(MULTILINKDATA * mld, DWORD dwNewPort) { mld->dwCurPort = dwNewPort; return mtlLoadCurrentPort(mld); } // Hangsup the current port DWORD mtlHangup(HWND hwndDlg, MULTILINKDATA * mld) { DWORD dwErr; HWND hwndLV = GetDlgItem(hwndDlg, IDC_PORTLIST); if ((dwErr = MprAdminPortDisconnect(Globals.hRasServer, mld->pCurPort0->hPort)) != NO_ERROR) return dwErr; // There are no more ports if mtlLoadPortData returns an error if ((dwErr = mtlLoadPortData(mld, 0)) != NO_ERROR) DestroyWindow(hwndDlg); else { ListView_DeleteAllItems(hwndLV); mtlUiFillPortList(hwndLV, mld); ListView_SetItemState(hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff); mtlUpdateStats(hwndDlg, mld); } return NO_ERROR; } // Cleansup the mtleral tab as it is being destroyed DWORD mtlUiCleanupDialog(HWND hwndDlg, WPARAM wParam, LPARAM lParam) { // Cleanup the data MULTILINKDATA * mld = (MULTILINKDATA *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); if (mld) { if (mld->pCurPort0) MprAdminBufferFree(mld->pCurPort0); if (mld->pCurPort1) MprAdminBufferFree(mld->pCurPort1); if (mld) free(mld); } // Stop the timer KillTimer(hwndDlg, MTL_TIMER_ID); return NO_ERROR; } // This is the dialog procedure that responds to messages sent to the // mtleral tab. BOOL CALLBACK mtlUiDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { NMHDR* pNotifyData; NM_LISTVIEW* pLvNotifyData; LV_KEYDOWN* pLvKeyDown; MULTILINKDATA * mld = (MULTILINKDATA*) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); // Process other messages as normal switch (uMsg) { case WM_INITDIALOG: return mtlUiInitializeDialog(hwndDlg, wParam, lParam); case WM_NOTIFY: pNotifyData = (NMHDR*)lParam; switch (pNotifyData->code) { // The property sheet apply button was pressed case PSN_APPLY: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); return TRUE; // The property sheet cancel was pressed case PSN_RESET: SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); break; // An item is changing state, keep track of any newly // selected item so space bar can toggle him. case LVN_ITEMCHANGING: pLvNotifyData = (NM_LISTVIEW*)lParam; if (pLvNotifyData->uNewState & LVIS_SELECTED) { mtlUpdateCurPort(mld, pLvNotifyData->iItem); mtlUpdateStats(hwndDlg, mld); } break; } break; // Called when the timer expires case WM_TIMER: mtlLoadCurrentPort(mld); mtlUpdateStats(hwndDlg, mld); break; // This is a custom message that we defined to toggle dialin permission // when the mouse is clicked on a user. case LV_EXTENSION_ITEMCLICKED: case LV_EXTENSION_ITEMDBLCLICKED: mtlUpdateCurPort(mld, wParam); mtlUpdateStats(hwndDlg, mld); break; case WM_COMMAND: if (wParam == IDC_HANGUP) mtlHangup(hwndDlg, mld); break; // Cleanup the work done at WM_INITDIALOG case WM_DESTROY: mtlUiCleanupDialog(hwndDlg, wParam, lParam); break; } return FALSE; }