#include "pch.h" #pragma hdrstop #include "sautil.h" #include "resource.h" #include "fwpages.h" #include #include #define DEFAULT_FIREWALL_LOGFILE_SIZE 4096 #define DEFAULT_FIREWALL_LOGFILE_PATH TEXT("\\pfirewall.log") extern LVXDRAWINFO* SasLvxCallback( HWND hwndLv, DWORD dwItem ); static DWORD g_adwFirewallLoggingHelp[] = { CID_FL_CB_LogDroppedInbound, HID_FL_CB_LogDroppedInbound, CID_FL_CB_LogOutboundConnections, HID_FL_CB_LogOutboundConnections, CID_FL_EB_Filename, HID_FL_EB_Filename, CID_FL_PB_Browse, HID_FL_PB_Browse, CID_FL_EB_Filesize, HID_FL_EB_Filesize, CID_FL_PB_RestoreDefaults, HID_FL_PB_RestoreDefaults, 0, 0 }; static DWORD g_adwICMPHelp[] = { CID_IC_LV_Settings, HID_IC_LV_Settings, CID_IC_ST_Description, HID_IC_ST_Description, 0, 0 }; typedef struct tagICMPEntry { UINT uiStringID; UINT uiDescID; size_t Offset; } ICMPEntry; static ICMPEntry g_ICMPEntries[] = { {SID_ICMP_IECHO, SID_ICMP_IECHO_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowInboundEchoRequest)}, {SID_ICMP_ITIME, SID_ICMP_ITIME_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowInboundTimestampRequest)}, {SID_ICMP_IMASK, SID_ICMP_IMASK_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowInboundMaskRequest)}, {SID_ICMP_IROUT, SID_ICMP_IROUT_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowInboundRouterRequest)}, {SID_ICMP_ODEST, SID_ICMP_ODEST_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowOutboundDestinationUnreachable)}, {SID_ICMP_OQNCH, SID_ICMP_OQNCH_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowOutboundSourceQuench)}, {SID_ICMP_OPRAM, SID_ICMP_OPRAM_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowOutboundParameterProblem)}, {SID_ICMP_OTIME, SID_ICMP_OTIME_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowOutboundTimeExceeded)}, {SID_ICMP_XRDRT, SID_ICMP_XRDRT_DESC, offsetof(HNET_FW_ICMP_SETTINGS, fAllowRedirect)}, {0, 0}, }; HRESULT CFirewallLoggingDialog_GetDefaultLogfilePath(LPTSTR* ppszLogFilePath); HRESULT CFirewallLoggingDialog_RestoreDefaults(HWND hwnd); HRESULT CFirewallLoggingDialog_Apply(CFirewallLoggingDialog* pThis, HWND hWindow); HRESULT CFirewallLoggingDialog_BrowseForLogfileName(HWND hWindow); HRESULT CICMPSettingsDialog_Apply(CICMPSettingsDialog* pThis, HWND hWindow); HRESULT CICMPSettingsDialog_ShowDescriptionText(HWND hwnd, INT nIndex); INT_PTR CALLBACK CFirewallLoggingDialog_StaticDlgProc( HWND hwnd, UINT unMsg, WPARAM wparam, LPARAM lparam ) // Called to handle messages for the 'Firewall Logging' page. // { HRESULT hr = S_OK; switch (unMsg) { case WM_INITDIALOG: { PROPSHEETPAGE* pPropertySheetPage = (PROPSHEETPAGE*) lparam; CFirewallLoggingDialog* pFirewallLoggingDialog = (CFirewallLoggingDialog*) pPropertySheetPage->lParam; HNET_FW_LOGGING_SETTINGS* pSettings = pFirewallLoggingDialog->pSettings; SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) pFirewallLoggingDialog); // Ignore if this fails, we're better off without it than killing the whole page CreateUpDownControl(WS_CHILD | WS_VISIBLE | WS_BORDER | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_NOTHOUSANDS | UDS_ARROWKEYS, 0, 0, 0, 0, hwnd, -1, g_hinstDll, GetDlgItem(hwnd, CID_FL_EB_Filesize), UD_MAXVAL, 0, 0); if(NULL != pSettings) { SetDlgItemText(hwnd, CID_FL_EB_Filename, pSettings->pszwPath); SetDlgItemInt(hwnd, CID_FL_EB_Filesize, (UINT) (pSettings->ulMaxFileSize / 1024), FALSE); // REVIEW safe cast? CheckDlgButton(hwnd, CID_FL_CB_LogOutboundConnections, pSettings->fLogConnections ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, CID_FL_CB_LogDroppedInbound, pSettings->fLogDroppedPackets ? BST_CHECKED : BST_UNCHECKED); } else { CFirewallLoggingDialog_RestoreDefaults(hwnd); } return TRUE; } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp(g_adwFirewallLoggingHelp, hwnd, unMsg, wparam, lparam); break; } case WM_COMMAND: { switch(LOWORD(wparam)) { case CID_FL_PB_Browse: CFirewallLoggingDialog_BrowseForLogfileName(hwnd); break; case CID_FL_PB_RestoreDefaults: CFirewallLoggingDialog_RestoreDefaults(hwnd); break; } break; } case WM_NOTIFY: { switch (((NMHDR*)lparam)->code) { case PSN_KILLACTIVE: { BOOL bTranslated; UINT uiLogFileSize = GetDlgItemInt(hwnd, CID_FL_EB_Filesize, &bTranslated, FALSE); if(TRUE == bTranslated) { if(UD_MAXVAL < uiLogFileSize || 1 > uiLogFileSize) { MsgDlg(hwnd, SID_FwbInvalidSize, NULL); hr = E_UNEXPECTED; } } else { MsgDlg(hwnd, SID_FwbInvalidSize, NULL); hr = E_FAIL; } if(SUCCEEDED(hr)) { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); } else { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID); } return TRUE; } case PSN_APPLY: { CFirewallLoggingDialog* pFirewallLoggingDialog; pFirewallLoggingDialog = (CFirewallLoggingDialog*) GetWindowLongPtr(hwnd, DWLP_USER); hr = CFirewallLoggingDialog_Apply(pFirewallLoggingDialog, hwnd); if(SUCCEEDED(hr)) { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); } else { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID); } return TRUE; } } break; } } return FALSE; } HRESULT CFirewallLoggingDialog_RestoreDefaults(HWND hwnd) { HRESULT hr; LPTSTR pszLogFilePath; hr = CFirewallLoggingDialog_GetDefaultLogfilePath(&pszLogFilePath); if(SUCCEEDED(hr)) { SetDlgItemText(hwnd, CID_FL_EB_Filename, pszLogFilePath); CoTaskMemFree(pszLogFilePath); } SetDlgItemInt(hwnd, CID_FL_EB_Filesize, DEFAULT_FIREWALL_LOGFILE_SIZE, FALSE); CheckDlgButton(hwnd, CID_FL_CB_LogOutboundConnections, BST_UNCHECKED); CheckDlgButton(hwnd, CID_FL_CB_LogDroppedInbound, BST_UNCHECKED); return hr; } HRESULT CFirewallLoggingDialog_Init(CFirewallLoggingDialog* pThis, IHNetCfgMgr* pHomenetConfigManager) { HRESULT hr; hr = pHomenetConfigManager->QueryInterface (IID_IHNetFirewallSettings, (void**)&pThis->pFirewallSettings); if(SUCCEEDED(hr)) { hr = pThis->pFirewallSettings->GetFirewallLoggingSettings (&pThis->pSettings); if(HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND) == hr) { ASSERT(NULL == pThis->pSettings); hr = S_OK; } if(FAILED(hr)) { pThis->pFirewallSettings->Release(); pThis->pFirewallSettings = NULL; } } return hr; } HRESULT CFirewallLoggingDialog_FinalRelease(CFirewallLoggingDialog* pThis) { pThis->pFirewallSettings->Release(); if(NULL != pThis->pSettings) { if(NULL != pThis->pSettings->pszwPath) { CoTaskMemFree(pThis->pSettings->pszwPath); } } return S_OK; } HRESULT CFirewallLoggingDialog_GetDefaultLogfilePath(LPTSTR* ppszLogfilePath) { HRESULT hr = S_OK; LPTSTR pszAppendPath = DEFAULT_FIREWALL_LOGFILE_PATH; LPTSTR pszLogfilePath; UINT uiPathLength, uiLength; ASSERT(NULL != ppszLogfilePath); uiPathLength = GetWindowsDirectory(NULL, 0); if(0 != uiPathLength) { uiPathLength += lstrlen(pszAppendPath) + 1; pszLogfilePath = (LPTSTR) CoTaskMemAlloc((ULONG) (uiPathLength * sizeof(TCHAR))); if(NULL != pszLogfilePath) { // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness // uiLength = GetWindowsDirectory(pszLogfilePath, uiPathLength); if(0 != uiLength) { // REVIEW if the size of the windir somehow changes then we have problems, but this can't happen right? // lstrcpyn( pszLogfilePath + uiLength, TEXT('\\') == pszLogfilePath[uiLength - 1] ? pszAppendPath + 1 : pszAppendPath, uiPathLength - uiLength); *ppszLogfilePath = pszLogfilePath; } else { hr = E_FAIL; } if(FAILED(hr)) { CoTaskMemFree(pszLogfilePath); } } else { hr = E_OUTOFMEMORY; } } else { hr = E_FAIL; } return hr; } HRESULT CFirewallLoggingDialog_Apply(CFirewallLoggingDialog* pThis, HWND hWindow) { HRESULT hr = S_OK; HNET_FW_LOGGING_SETTINGS NewSettings; BOOL bTranslated; UINT uiLogFileSize; UINT uiSizeNeeded; NewSettings.fLogDroppedPackets = BST_CHECKED == IsDlgButtonChecked(hWindow, CID_FL_CB_LogDroppedInbound); NewSettings.fLogConnections = BST_CHECKED == IsDlgButtonChecked(hWindow, CID_FL_CB_LogOutboundConnections); NewSettings.pszwPath = NULL; if(SUCCEEDED(hr)) { uiSizeNeeded = Edit_GetTextLength(GetDlgItem(hWindow, CID_FL_EB_Filename)) + 1; if(0 != uiSizeNeeded) { NewSettings.pszwPath = (LPWSTR) CoTaskMemAlloc((ULONG) (uiSizeNeeded * sizeof(TCHAR))); if(NULL != NewSettings.pszwPath) { uiSizeNeeded = GetDlgItemText(hWindow, CID_FL_EB_Filename, NewSettings.pszwPath, uiSizeNeeded); if(0 == uiSizeNeeded) { hr = E_FAIL; } } else { hr = E_OUTOFMEMORY; } } else { hr = E_UNEXPECTED; // invalid param, empty filename } } if(SUCCEEDED(hr)) { uiLogFileSize = GetDlgItemInt(hWindow, CID_FL_EB_Filesize, &bTranslated, FALSE); if(TRUE == bTranslated) { NewSettings.ulMaxFileSize = 1024 * (ULONG) uiLogFileSize; } else { hr = E_UNEXPECTED; // invalid param } } if(SUCCEEDED(hr)) { BOOL bDirty = TRUE; if(NULL != pThis->pSettings) // we may not have gotten one on GetFirewallLoggingSettings { bDirty = FALSE; bDirty |= NewSettings.fLogDroppedPackets != pThis->pSettings->fLogDroppedPackets; bDirty |= NewSettings.fLogConnections != pThis->pSettings->fLogConnections; bDirty |= NewSettings.ulMaxFileSize != pThis->pSettings->ulMaxFileSize; bDirty |= 0 != lstrcmp(NewSettings.pszwPath, pThis->pSettings->pszwPath); } if(TRUE == bDirty) { hr = pThis->pFirewallSettings->SetFirewallLoggingSettings (&NewSettings); } } if(NULL != NewSettings.pszwPath) { CoTaskMemFree(NewSettings.pszwPath); } return hr; } HRESULT CFirewallLoggingDialog_BrowseForLogfileName(HWND hWindow) { HRESULT hr = S_OK; OPENFILENAME ofn; TCHAR* pszFilterDesc; TCHAR* pszFilter; TCHAR* pszDefExt; TCHAR* pszTitle; TCHAR szBuf[ MAX_PATH + 1 ] = L""; TCHAR szDir[ MAX_PATH + 1] = L""; // Fill in FileOpen dialog parameter buffer. // // if any of these fail just let them be null pszFilterDesc = PszFromId( g_hinstDll, SID_FwbFilterDesc ); pszTitle = PszFromId( g_hinstDll, SID_FwbTitle ); pszDefExt = PszFromId( g_hinstDll, SID_FwbDefExt ); // if this fails we will have a null path, so the open dialog should open at the root if(0 != GetDlgItemText(hWindow, CID_FL_EB_Filename, szDir, sizeof(szDir) / sizeof(TCHAR))) { // lose the file name LPWSTR pszLastSlash = wcsrchr(szDir, L'\\'); if(NULL != pszLastSlash) { *pszLastSlash = L'\0'; } } ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = GetParent( hWindow ); ofn.hInstance = g_hinstDll; ofn.lpstrFilter = pszFilterDesc; ofn.nFilterIndex = 1; ofn.lpstrFile = szBuf; ofn.nMaxFile = MAX_PATH; ofn.lpstrInitialDir = szDir; ofn.lpstrTitle = pszTitle; ofn.lpstrDefExt = pszDefExt; ofn.Flags = 0; if (GetOpenFileName (&ofn)) { SetWindowText( GetDlgItem(hWindow, CID_FL_EB_Filename), ofn.lpstrFile ); } Free0(pszTitle); Free0(pszDefExt); Free0(pszFilterDesc); return S_OK; } INT_PTR CALLBACK CICMPSettingsDialog_StaticDlgProc( HWND hwnd, UINT unMsg, WPARAM wparam, LPARAM lparam ) // Called to handle messages for the 'ICMP' page. // { HRESULT hr; // Give the extended list-control a chance to look at all messages first. // if (ListView_OwnerHandler(hwnd, unMsg, wparam, lparam, SasLvxCallback)) { return TRUE; } switch (unMsg) { case WM_INITDIALOG: { UINT i = 0; UINT uiEntry = 0; LVITEM lvi; HWND hListView; PROPSHEETPAGE* pPropertySheetPage = (PROPSHEETPAGE*) lparam; CICMPSettingsDialog* pICMPSettingsDialog = (CICMPSettingsDialog*) pPropertySheetPage->lParam; HNET_FW_ICMP_SETTINGS* pSettings = pICMPSettingsDialog->pSettings; ASSERT(NULL != pSettings); SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) pICMPSettingsDialog); hListView = GetDlgItem(hwnd, CID_IC_LV_Settings); ASSERT(NULL != hListView); ListView_InstallChecks(hListView, g_hinstDll); ListView_InsertSingleAutoWidthColumn(hListView); while(0 != g_ICMPEntries[uiEntry].uiStringID) { LPTSTR pszText = PszFromId(g_hinstDll, g_ICMPEntries[uiEntry].uiStringID); if(NULL != pszText) { ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = i + 1; // add to end lvi.lParam = (LPARAM) g_ICMPEntries[uiEntry].Offset; lvi.pszText = pszText; lvi.cchTextMax = lstrlen(pszText) + 1; i = ListView_InsertItem(hListView, &lvi); if (i != -1) { ListView_SetCheck(hListView, i, (BOOLEAN)*((BYTE*)pSettings + g_ICMPEntries[uiEntry].Offset)); // REVIEW 64bit safe? } Free(pszText); } uiEntry++; } ListView_SetItemState(hListView, 0, LVIS_SELECTED, LVIS_SELECTED); CICMPSettingsDialog_ShowDescriptionText(hwnd, 0); return TRUE; } case WM_HELP: case WM_CONTEXTMENU: { ContextHelp(g_adwICMPHelp, hwnd, unMsg, wparam, lparam); break; } case WM_COMMAND: { break; } case WM_NOTIFY: { switch (((NMHDR*)lparam)->code) { case PSN_APPLY: { CICMPSettingsDialog* pICMPSettingsDialog; pICMPSettingsDialog = (CICMPSettingsDialog*) GetWindowLongPtr(hwnd, DWLP_USER); hr = CICMPSettingsDialog_Apply(pICMPSettingsDialog, hwnd); if(SUCCEEDED(hr)) { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_NOERROR); } else { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, PSNRET_INVALID); } return TRUE; } case LVXN_SETCHECK: { return TRUE; } case LVN_ITEMCHANGED: { INT nSelectedItem; LPNMLISTVIEW ListViewInfo = (LPNMLISTVIEW) lparam; if(-1 != ListViewInfo->iItem && LVIS_SELECTED & ListViewInfo->uNewState) { CICMPSettingsDialog_ShowDescriptionText(hwnd, ListViewInfo->iItem); } return TRUE; } } break; } } return FALSE; } HRESULT CICMPSettingsDialog_Init(CICMPSettingsDialog* pThis, IHNetConnection* pHomenetConnection) { HRESULT hr; pThis->pConnection = pHomenetConnection; pHomenetConnection->AddRef(); hr = pHomenetConnection->GetIcmpSettings (&pThis->pSettings); if(FAILED(hr)) { pHomenetConnection->Release(); } return hr; } HRESULT CICMPSettingsDialog_FinalRelease(CICMPSettingsDialog* pThis) { ASSERT(pThis->pConnection); pThis->pConnection->Release(); ASSERT(pThis->pSettings); CoTaskMemFree(pThis->pSettings); return S_OK; } HRESULT CICMPSettingsDialog_Apply(CICMPSettingsDialog* pThis, HWND hWindow) { HRESULT hr = S_OK; HNET_FW_ICMP_SETTINGS NewSettings; BOOL bDirty = FALSE; HWND hListView; LVITEM lvi; int nItemCount; hListView = GetDlgItem(hWindow, CID_IC_LV_Settings); ASSERT(NULL != hListView); ZeroMemory(&lvi, sizeof(lvi)); lvi.mask = LVIF_PARAM; nItemCount = ListView_GetItemCount(hListView); while(0 < nItemCount--) { BOOLEAN bChecked = (BOOLEAN) ListView_GetCheck(hListView, nItemCount); // REVIEW can this error? lvi.iItem = nItemCount; if(TRUE == ListView_GetItem(hListView, &lvi)) { (BOOLEAN)*((BYTE*)&NewSettings + lvi.lParam) = bChecked; if(bChecked != (BOOLEAN)*((BYTE*)(pThis->pSettings) + lvi.lParam)) // REVIEW 64bit safe? { bDirty = TRUE; } } } if(bDirty) { hr = pThis->pConnection->SetIcmpSettings (&NewSettings); } return hr; } HRESULT CICMPSettingsDialog_ShowDescriptionText(HWND hwnd, INT nIndex) { LPWSTR pszDescription = PszFromId(g_hinstDll, g_ICMPEntries[nIndex].uiDescID); if(NULL != pszDescription) { SetDlgItemText(hwnd, CID_IC_ST_Description, pszDescription); Free(pszDescription); } return S_OK; }