sublayer properties

progress on new filter dialog
This commit is contained in:
Pavel Yosifovich
2024-08-19 18:00:08 -04:00
parent 8b48b334ff
commit 3e90b0805d
20 changed files with 592 additions and 90 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ class CCalloutDlg :
public:
enum { IDD = IDD_CALLOUT };
explicit CCalloutDlg(WFPEngine& engine, FWPM_CALLOUT* callout);
CCalloutDlg(WFPEngine& engine, FWPM_CALLOUT* callout);
BEGIN_MSG_MAP(CCalloutDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+5 -1
View File
@@ -67,7 +67,11 @@ LRESULT CFilterGeneralPage::OnShowProvider(WORD, WORD, HWND, BOOL&) {
}
LRESULT CFilterGeneralPage::OnShowSublayer(WORD, WORD, HWND, BOOL&) {
return LRESULT();
auto sl = m_Engine.GetSublayerByKey(m_Filter->subLayerKey);
ATLASSERT(sl);
WFPHelper::ShowSublayerProperties(m_Engine, *sl);
return 0;
}
LRESULT CFilterGeneralPage::OnShowCallout(WORD, WORD, HWND, BOOL&) {
-2
View File
@@ -3,10 +3,8 @@
#include "StringHelper.h"
#include <SortHelper.h>
#include "WFPHelper.h"
#include "LayerGeneralPage.h"
#include <WFPEnumerators.h>
#include <ClipboardHelper.h>
#include <ThemeHelper.h>
CLayersView::CLayersView(IMainFrame* frame, WFPEngine& engine) : CGenericListViewBase(frame), m_Engine(engine) {
}
+30 -1
View File
@@ -17,6 +17,8 @@
#include "AppSettings.h"
#include "HierarchyView.h"
#include "NetEventsView.h"
#include "ProviderDlg.h"
#include "NewFilterDlg.h"
const int WINDOW_MENU_POSITION = 4;
@@ -396,7 +398,7 @@ LRESULT CMainFrame::OnToggleDarkMode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*
auto& settings = AppSettings::Get();
settings.DarkMode(!settings.DarkMode());
UISetCheck(ID_OPTIONS_DARKMODE, settings.DarkMode());
if (settings.DarkMode())
ThemeHelper::SetCurrentTheme(s_DarkTheme, m_hWnd);
else
@@ -408,6 +410,33 @@ LRESULT CMainFrame::OnToggleDarkMode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*
return 0;
}
LRESULT CMainFrame::OnNewProvider(WORD, WORD, HWND, BOOL&) {
FWPM_PROVIDER provider{};
CProviderDlg dlg(&provider);
if (dlg.DoModal() == IDOK) {
//
// attempt to add a new provider
//
WFPEngine engine;
bool ok = false;
if (engine.Open()) {
ok = engine.AddProvider(&provider);
}
AtlMessageBox(m_hWnd, ok ? L"Provider added successfully." : L"Failed to add provider.",
IDS_TITLE, ok ? MB_ICONINFORMATION : MB_ICONERROR);
}
return 0;
}
LRESULT CMainFrame::OnNewFilter(WORD, WORD, HWND, BOOL&) {
FWPM_FILTER filter{};
CNewFilterDlg dlg(&filter);
if (dlg.DoModal() == IDOK) {
}
return 0;
}
void CMainFrame::InitDarkTheme() const {
s_DarkTheme.BackColor = s_DarkTheme.SysColors[COLOR_WINDOW] = RGB(32, 32, 32);
s_DarkTheme.TextColor = s_DarkTheme.SysColors[COLOR_WINDOWTEXT] = RGB(248, 248, 248);
+4
View File
@@ -47,6 +47,8 @@ public:
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind)
COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
COMMAND_ID_HANDLER(ID_NEW_FILTER, OnNewFilter)
COMMAND_ID_HANDLER(ID_NEW_PROVIDER, OnNewProvider)
CHAIN_MSG_MAP(CAutoUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(COwnerDrawnMenu<CMainFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
@@ -94,6 +96,8 @@ private:
LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnFind(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnToggleDarkMode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnNewProvider(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnNewFilter(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
WFPEngine m_Engine;
CFont m_MonoFont;
+207
View File
@@ -0,0 +1,207 @@
#include "pch.h"
#include "resource.h"
#include "NewFilterDlg.h"
#include <WFPEngine.h>
#include <WFPEnumerators.h>
#include "StringHelper.h"
#include "WFPHelper.h"
using namespace std::ranges;
using namespace std::views;
using namespace std;
CNewFilterDlg::CNewFilterDlg(FWPM_FILTER* filter) : m_Filter(filter) {
ATLASSERT(filter);
}
bool CNewFilterDlg::IsNewFilter() const {
return m_Filter->filterKey == GUID_NULL;
}
LRESULT CNewFilterDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
SetDialogIcon(IDI_FILTER);
struct {
PCWSTR text;
FWP_ACTION_TYPE type;
} actions[] = {
{ L"Block", FWP_ACTION_BLOCK },
{ L"Permit", FWP_ACTION_PERMIT },
{ L"Callout Terminating", FWP_ACTION_CALLOUT_TERMINATING },
{ L"Callout Inspection", FWP_ACTION_CALLOUT_INSPECTION },
{ L"Callout Unknown", FWP_ACTION_CALLOUT_UNKNOWN },
};
InitCombo(IDC_ACTION, actions, m_Filter->action.type);
WFPEngine engine;
if (engine.Open()) {
{
//
// add providers to combo
//
WFPProviderEnumerator en(engine.Handle());
auto providers = en.Next(256);
struct Data {
CString text;
int type;
};
int selected = -1, i = 0;
auto data = providers | std::views::transform([&](auto& p) {
if (selected < 0 && m_Filter->providerKey && IsNewFilter() && p->providerKey == *m_Filter->providerKey)
selected = i;
i++;
return Data{ p->displayData.name + CString(" (") + StringHelper::GuidToString(p->providerKey) + L")", i - 1 };
}) | to<std::vector>();
data.insert(data.begin(), { L"(None)", -1 });
InitCombo(IDC_PROVIDER, data.data(), (int)data.size(), selected);
}
{
//
// add layers to combo
//
WFPLayerEnumerator en(engine.Handle());
auto layers = en.Next(256);
struct Data {
CString text;
int type;
};
auto data = layers | views::transform([&](auto& l) {
return Data{ WFPHelper::GetLayerName(engine, l->layerKey), (int)l->layerId };
}) | to<vector>();
int layerId = 0;
if (!IsNewFilter())
layerId = engine.GetLayerByKey(m_Filter->layerKey)->layerId;
InitCombo(IDC_LAYER, data.data(), (int)data.size(), layerId);
}
{
//
// add sublayers to combo
//
WFPSubLayerEnumerator en(engine.Handle());
auto layers = en.Next(256);
struct Data {
CString text;
int type;
};
int selected = -1, i = 0;
auto data = layers | views::transform([&](auto& l) {
if (selected < 0 && IsNewFilter() && l->subLayerKey == m_Filter->subLayerKey)
selected = i;
i++;
return Data{ WFPHelper::GetSublayerName(engine, l->subLayerKey) + CString(L" (") + StringHelper::GuidToString(l->subLayerKey) + L")", i - 1 };
}) | to<vector>();
InitCombo(IDC_SUBLAYER, data.data(), (int)data.size(), selected);
}
{
//
// add callouts to combo
//
WFPCalloutEnumerator en(engine.Handle());
auto callouts = en.Next(512);
struct Data {
CString text;
UINT32 type;
};
auto data = callouts | std::views::transform([&](auto& c) {
return Data{
c->displayData.name + CString(L" (") + engine.GetLayerByKey(c->applicableLayer)->displayData.name + L")",
c->calloutId
};
}) | to<std::vector>();
UINT32 id = 0;
if (!IsNewFilter())
id = engine.GetCalloutByKey(m_Filter->action.calloutKey)->calloutId;
InitCombo(IDC_CALLOUT, data.data(), (int)data.size(), id);
}
auto cb = (CComboBox)GetDlgItem(IDC_WEIGHTRANGE);
for(int i = 0; i < 16; i++)
cb.AddString(std::format(L"0x{:X}", i).c_str());
cb.SetCurSel(0);
if (IsNewFilter()) {
CheckDlgButton(IDC_AUTOMATIC, BST_CHECKED);
}
else if (m_Filter->weight.type == FWP_EMPTY) {
CheckDlgButton(IDC_AUTOMATIC, BST_CHECKED);
}
else {
auto weight = *m_Filter->weight.uint64;
if (weight < 16) {
CheckDlgButton(IDC_RANGE, BST_CHECKED);
((CComboBox)GetDlgItem(IDC_WEIGHTRANGE)).SetCurSel((int)weight);
}
else {
CheckDlgButton(IDC_SPECIFIC, BST_CHECKED);
SetDlgItemText(IDC_WEIGHT, std::format(L"0x{:X}", weight).c_str());
}
}
}
return 0;
}
LRESULT CNewFilterDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
EndDialog(wID);
return 0;
}
LRESULT CNewFilterDlg::OnGenerateKey(WORD, WORD wID, HWND, BOOL&) {
GUID guid;
::CoCreateGuid(&guid);
WCHAR sguid[64];
::StringFromGUID2(guid, sguid, _countof(sguid));
SetDlgItemText(IDC_KEY, sguid);
return 0;
}
LRESULT CNewFilterDlg::OnLayerProperties(WORD, WORD wID, HWND, BOOL&) {
auto cb = (CComboBox)GetDlgItem(IDC_LAYER);
auto selected = cb.GetCurSel();
auto id = (UINT16)cb.GetItemData(selected);
WFPEngine engine;
engine.Open();
WFPHelper::ShowLayerProperties(engine, *engine.GetLayerById(id));
return 0;
}
LRESULT CNewFilterDlg::OnSublayerProperties(WORD, WORD wID, HWND, BOOL&) {
auto cb = (CComboBox)GetDlgItem(IDC_SUBLAYER);
auto selected = cb.GetCurSel();
CString text;
cb.GetLBText(selected, text);
auto guid = StringHelper::ExtractGuid(text);
WFPEngine engine;
engine.Open();
WFPHelper::ShowSublayerProperties(engine, *engine.GetSublayerByKey(guid));
return 0;
}
LRESULT CNewFilterDlg::OnProviderProperties(WORD, WORD wID, HWND, BOOL&) {
auto cb = (CComboBox)GetDlgItem(IDC_PROVIDER);
auto selected = cb.GetCurSel();
if (selected == 0)
return 0;
CString text;
cb.GetLBText(selected, text);
auto guid = StringHelper::ExtractGuid(text);
WFPEngine engine;
engine.Open();
WFPHelper::ShowProviderProperties(engine, *engine.GetProviderByKey(guid));
return 0;
}
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <DialogHelper.h>
class CNewFilterDlg :
public CDialogImpl<CNewFilterDlg>,
public CDialogHelper<CNewFilterDlg> {
public:
enum { IDD = IDD_NEWFILTER };
explicit CNewFilterDlg(FWPM_FILTER* filter);
bool IsNewFilter() const;
BEGIN_MSG_MAP(CNewFilterDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
COMMAND_ID_HANDLER(IDC_GENERATE, OnGenerateKey)
COMMAND_ID_HANDLER(IDC_LAYER_PROP, OnLayerProperties)
COMMAND_ID_HANDLER(IDC_SUBLAYER_PROP, OnSublayerProperties)
COMMAND_ID_HANDLER(IDC_PROVIDER_PROP, OnProviderProperties)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
private:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnGenerateKey(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnLayerProperties(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSublayerProperties(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnProviderProperties(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
FWPM_FILTER* m_Filter;
};
+58 -18
View File
@@ -8,31 +8,71 @@ CProviderDlg::CProviderDlg(FWPM_PROVIDER* provider) : m_Provider(provider) {
LRESULT CProviderDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
SetDialogIcon((m_Provider->flags & FWPM_PROVIDER_FLAG_PERSISTENT) ? IDI_PROVIDER_PERSISTENT : IDI_PROVIDER);
SetDlgItemText(IDC_KEY, StringHelper::GuidToString(m_Provider->providerKey));
auto name = StringHelper::ParseMUIString(m_Provider->displayData.name);
SetDlgItemText(IDC_NAME, name);
if (!name.IsEmpty() && name[0] != L'@')
SetWindowText(L"Provider: " + name);
SetDlgItemText(IDC_DESC, StringHelper::ParseMUIString(m_Provider->displayData.description));
SetDlgItemText(IDC_SERVICENAME, m_Provider->serviceName);
if (m_Provider->providerKey != GUID_NULL) {
SetDlgItemText(IDC_KEY, StringHelper::GuidToString(m_Provider->providerKey));
auto name = StringHelper::ParseMUIString(m_Provider->displayData.name);
SetDlgItemText(IDC_NAME, name);
if (!name.IsEmpty() && name[0] != L'@')
SetWindowText(L"Provider: " + name);
SetDlgItemText(IDC_DESC, StringHelper::ParseMUIString(m_Provider->displayData.description));
SetDlgItemText(IDC_SERVICENAME, m_Provider->serviceName);
if (m_Provider->flags & FWPM_PROVIDER_FLAG_PERSISTENT)
CheckDlgButton(IDC_PERSISTENT, BST_CHECKED);
if (m_Provider->flags & FWPM_PROVIDER_FLAG_DISABLED)
CheckDlgButton(IDC_DISABLED, BST_CHECKED);
if (m_Provider->flags & FWPM_PROVIDER_FLAG_PERSISTENT)
CheckDlgButton(IDC_PERSISTENT, BST_CHECKED);
if (m_Provider->flags & FWPM_PROVIDER_FLAG_DISABLED)
CheckDlgButton(IDC_DISABLED, BST_CHECKED);
if (m_Provider->providerData.size) {
SetDlgItemText(IDC_DATASIZE, std::format(L"Provider data size: {} bytes", m_Provider->providerData.size).c_str());
SetDlgItemText(IDC_PROVIDERDATA, StringHelper::FormatBinary(m_Provider->providerData.data, m_Provider->providerData.size));
if (m_Provider->providerData.size) {
SetDlgItemText(IDC_DATASIZE, std::format(L"Provider data size: {} bytes", m_Provider->providerData.size).c_str());
SetDlgItemText(IDC_PROVIDERDATA, StringHelper::FormatBinary(m_Provider->providerData.data, m_Provider->providerData.size));
}
else {
GetDlgItem(IDC_PROVIDERDATA).ShowWindow(SW_HIDE);
}
}
else {
GetDlgItem(IDC_PROVIDERDATA).ShowWindow(SW_HIDE);
UINT ids[] = { IDC_KEY, IDC_NAME, IDC_DESC, IDC_SERVICENAME };
for (auto id : ids) {
((CEdit)GetDlgItem(id)).SetReadOnly(FALSE);
}
GetDlgItem(IDC_PERSISTENT).EnableWindow();
GetDlgItem(IDC_DISABLED).EnableWindow();
GetDlgItem(IDC_GENERATE).ShowWindow(SW_SHOW);
GetDlgItem(IDOK).SetWindowTextW(L"Add");
}
return 0;
}
LRESULT CProviderDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
EndDialog(wID);
LRESULT CProviderDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) {
if (m_Provider->providerKey == GUID_NULL) {
CString key;
GetDlgItem(IDC_KEY).GetWindowText(key);
::CLSIDFromString(key, &m_Provider->providerKey);
GetDlgItemText(IDC_NAME, m_Name);
if (!m_Name.IsEmpty())
m_Provider->displayData.name = (PWSTR)(PCWSTR)m_Name;
GetDlgItemText(IDC_DESC, m_Desc);
if (!m_Desc.IsEmpty())
m_Provider->displayData.description = (PWSTR)(PCWSTR)m_Desc;
GetDlgItemText(IDC_SERVICENAME, m_Service);
if (!m_Service.IsEmpty())
m_Provider->serviceName = (PWSTR)(PCWSTR)m_Service;
if (IsDlgButtonChecked(IDC_PERSISTENT) == BST_CHECKED)
m_Provider->flags |= FWPM_PROVIDER_FLAG_PERSISTENT;
if (IsDlgButtonChecked(IDC_DISABLED) == BST_CHECKED)
m_Provider->flags |= FWPM_PROVIDER_FLAG_DISABLED;
}
EndDialog(id);
return 0;
}
LRESULT CProviderDlg::OnGenerateKey(WORD, WORD wID, HWND, BOOL&) {
GUID guid;
::CoCreateGuid(&guid);
WCHAR sguid[64];
::StringFromGUID2(guid, sguid, _countof(sguid));
SetDlgItemText(IDC_KEY, sguid);
return 0;
}
+3
View File
@@ -14,6 +14,7 @@ public:
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
COMMAND_ID_HANDLER(IDC_GENERATE, OnGenerateKey)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
@@ -24,6 +25,8 @@ public:
private:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnGenerateKey(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
FWPM_PROVIDER* m_Provider;
CString m_Name, m_Desc, m_Service;
};
+14
View File
@@ -521,6 +521,20 @@ PCWSTR StringHelper::AddressFamilyToString(FWP_AF af) {
return L"(Unknown)";
}
GUID StringHelper::ExtractGuid(CString const& text) {
auto index = text.Find('{');
if (index < 0)
return GUID_NULL;
auto index2 = text.Find('}', index + 1);
if (index2 < 0)
return GUID_NULL;
GUID guid;
::CLSIDFromString(text.Mid(index, index2 - index), &guid);
return guid;
}
PCWSTR StringHelper::WFPFilterActionTypeToString(FWP_ACTION_TYPE type) {
switch (type) {
case FWP_ACTION_BLOCK: return L"Block";
+1
View File
@@ -25,6 +25,7 @@ struct StringHelper abstract final {
static CString FormatIpv6Address(BYTE const* address);
static PCWSTR IpProtocolToString(UINT8 protocol);
static PCWSTR AddressFamilyToString(FWP_AF af);
static GUID ExtractGuid(CString const& text);
template<typename TFlags, typename TValue>
static CString FlagsToString(TValue value, TFlags const& data) {
+32
View File
@@ -0,0 +1,32 @@
#include "pch.h"
#include "resource.h"
#include "SubLayerDlg.h"
#include "WFPHelper.h"
#include <WFPEngine.h>
#include "StringHelper.h"
CSubLayerDlg::CSubLayerDlg(WFPEngine& engine, FWPM_SUBLAYER* sublayer) : m_Engine(engine), m_Sublayer(sublayer) {
}
LRESULT CSubLayerDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) {
SetDlgItemText(IDC_KEY, StringHelper::GuidToString(m_Sublayer->subLayerKey));
SetDlgItemText(IDC_NAME, StringHelper::ParseMUIString(m_Sublayer->displayData.name));
SetDlgItemText(IDC_DESC, m_Sublayer->displayData.description);
SetDlgItemInt(IDC_WEIGHT, m_Sublayer->weight);
if (m_Sublayer->providerKey) {
SetDlgItemText(IDC_PROVIDER, WFPHelper::GetProviderName(m_Engine, *m_Sublayer->providerKey));
}
else {
GetDlgItem(IDC_PROVIDER_PROP).EnableWindow(FALSE);
}
CheckDlgButton(IDC_PERSISTENT, (m_Sublayer->flags & FWPM_SUBLAYER_FLAG_PERSISTENT) ? BST_CHECKED : BST_UNCHECKED);
return 0;
}
LRESULT CSubLayerDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) {
EndDialog(wID);
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <DialogHelper.h>
class WFPEngine;
class CSubLayerDlg :
public CDialogImpl<CSubLayerDlg>,
public CDialogHelper<CSubLayerDlg> {
public:
enum { IDD = IDD_SUBLAYER };
CSubLayerDlg(WFPEngine& engine, FWPM_SUBLAYER* sublayer);
BEGIN_MSG_MAP(CSubLayerDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnCloseCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
// LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
// LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
// LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
private:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
WFPEngine& m_Engine;
FWPM_SUBLAYER* m_Sublayer;
};
+71 -15
View File
@@ -315,23 +315,42 @@ BEGIN
CONTROL "",IDC_TABS,"SysTabControl32",0x0,7,7,295,142
END
IDD_NEWFILTER DIALOGEX 0, 0, 445, 267
IDD_NEWFILTER DIALOGEX 0, 0, 421, 248
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "New Filter"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,164,246,50,14
PUSHBUTTON "Cancel",IDCANCEL,230,246,50,14
LTEXT "Key:",IDC_STATIC,7,10,16,8
EDITTEXT IDC_KEY,51,8,234,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Name:",IDC_STATIC,7,31,22,8
EDITTEXT IDC_NAME,51,29,359,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Description:",IDC_STATIC,7,52,39,8
EDITTEXT IDC_DESC,51,50,359,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
EDITTEXT IDC_KEY,47,8,234,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
PUSHBUTTON "Generate",IDC_GENERATE,290,7,50,14
PUSHBUTTON "Copy From...",IDC_COPYFROM,347,7,64,14
LTEXT "Name:",IDC_STATIC,7,31,22,8
EDITTEXT IDC_NAME,47,29,359,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Description:",IDC_STATIC,7,51,39,8
EDITTEXT IDC_DESC,47,50,359,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Provider:",IDC_STATIC,7,76,30,8
COMBOBOX IDC_PROVIDER,51,73,279,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Copy From...",IDC_COPYFROM,353,7,64,14
COMBOBOX IDC_PROVIDER,48,73,332,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Layer:",IDC_STATIC,7,98,22,8
COMBOBOX IDC_LAYER,48,97,332,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Sublayer:",IDC_STATIC,7,123,32,8
COMBOBOX IDC_SUBLAYER,48,121,332,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Weight:",IDC_STATIC,7,145,26,8
CONTROL "Automatic",IDC_AUTOMATIC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,53,145,48,10
CONTROL "Specific:",IDC_SPECIFIC,"Button",BS_AUTORADIOBUTTON,111,146,43,10
EDITTEXT IDC_WEIGHT,156,145,154,12,ES_AUTOHSCROLL | NOT WS_BORDER,WS_EX_STATICEDGE
CONTROL "Range:",IDC_RANGE,"Button",BS_AUTORADIOBUTTON,331,146,39,10
COMBOBOX IDC_WEIGHTRANGE,373,144,37,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
LTEXT "Action:",IDC_STATIC,7,169,24,8
COMBOBOX IDC_ACTION,47,168,87,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
LTEXT "Callout:",IDC_STATIC,7,190,26,8
COMBOBOX IDC_CALLOUT,47,188,333,75,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Conditions...",IDC_CONDITIONS,343,165,71,14
DEFPUSHBUTTON "OK",IDOK,152,227,50,14
PUSHBUTTON "Cancel",IDCANCEL,218,227,50,14
PUSHBUTTON "...",IDC_SUBLAYER_PROP,384,121,30,14
PUSHBUTTON "...",IDC_LAYER_PROP,384,97,30,14
PUSHBUTTON "...",IDC_PROVIDER_PROP,384,72,30,14
PUSHBUTTON "...",IDC_CALLOUT_PROP,384,187,30,14
END
IDD_PROVIDER DIALOGEX 0, 0, 389, 184
@@ -339,19 +358,21 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CLIPCHILDREN | WS
CAPTION "Provider"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,169,163,50,14
DEFPUSHBUTTON "OK",IDOK,136,163,50,14
LTEXT "Key:",IDC_STATIC,31,11,16,8
EDITTEXT IDC_KEY,52,10,248,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Name:",IDC_STATIC,25,31,22,8
EDITTEXT IDC_NAME,52,30,327,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Description:",IDC_STATIC,8,52,39,8
EDITTEXT IDC_DESC,52,51,327,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
CHECKBOX "Persistent",IDC_PERSISTENT,274,73,48,10
CHECKBOX "Disabled",IDC_DISABLED,339,73,43,10
CONTROL "Persistent",IDC_PERSISTENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,274,73,48,10
CONTROL "Disabled",IDC_DISABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,339,73,43,10
LTEXT "Service:",IDC_STATIC,20,73,27,8
EDITTEXT IDC_SERVICENAME,52,72,162,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Provider Data:",IDC_DATASIZE,9,93,48,8
EDITTEXT IDC_PROVIDERDATA,7,107,375,37,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
PUSHBUTTON "Generate",IDC_GENERATE,319,9,50,14,NOT WS_VISIBLE
DEFPUSHBUTTON "Cancel",IDCANCEL,202,163,50,14
END
IDD_CALLOUT DIALOGEX 0, 0, 393, 205
@@ -381,6 +402,28 @@ BEGIN
EDITTEXT IDC_PROVIDERDATA,7,140,375,30,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
END
IDD_SUBLAYER DIALOGEX 0, 0, 385, 185
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Sublayer"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Close",IDCANCEL,167,164,50,14
LTEXT "Key:",IDC_STATIC,31,8,16,8
EDITTEXT IDC_KEY,51,7,248,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Name:",IDC_STATIC,25,28,22,8
EDITTEXT IDC_NAME,51,27,327,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Description:",IDC_STATIC,8,49,39,8
EDITTEXT IDC_DESC,51,48,327,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Provider:",IDC_STATIC,16,68,30,8
EDITTEXT IDC_PROVIDER,51,67,262,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
PUSHBUTTON "Provider...",IDC_PROVIDER_PROP,323,66,55,14
CHECKBOX "Persistent",IDC_PERSISTENT,50,88,48,10
LTEXT "Weight:",IDC_STATIC,113,89,26,8
EDITTEXT IDC_WEIGHT,148,87,40,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
LTEXT "Provider Data:",IDC_DATASIZE,21,106,48,8
EDITTEXT IDC_PROVIDERDATA,17,118,347,30,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER,WS_EX_STATICEDGE
END
/////////////////////////////////////////////////////////////////////////////
//
@@ -441,9 +484,9 @@ BEGIN
IDD_NEWFILTER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 438
RIGHTMARGIN, 414
TOPMARGIN, 6
BOTTOMMARGIN, 260
BOTTOMMARGIN, 241
END
IDD_PROVIDER, DIALOG
@@ -461,6 +504,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 198
END
IDD_SUBLAYER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 378
TOPMARGIN, 7
BOTTOMMARGIN, 178
END
END
#endif // APSTUDIO_INVOKED
@@ -586,6 +637,11 @@ BEGIN
0
END
IDD_SUBLAYER AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
+9 -5
View File
@@ -180,7 +180,7 @@
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\WTLHelper\WTLHelper;..\WFPCore</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableModules>false</EnableModules>
</ClCompile>
<Link>
@@ -215,7 +215,7 @@
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\WTLHelper\WTLHelper;..\WFPCore</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableModules>false</EnableModules>
</ClCompile>
<Link>
@@ -254,7 +254,7 @@
<PreprocessorDefinitions>WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\WTLHelper\WTLHelper;..\WFPCore</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableModules>false</EnableModules>
</ClCompile>
<Link>
@@ -292,7 +292,7 @@
<PreprocessorDefinitions>_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\WTLHelper\WTLHelper;..\WFPCore</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableModules>false</EnableModules>
</ClCompile>
<Link>
@@ -330,7 +330,7 @@
<PreprocessorDefinitions>_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<AdditionalIncludeDirectories>..\WTLHelper\WTLHelper;..\WFPCore</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard>stdcpplatest</LanguageStandard>
<EnableModules>false</EnableModules>
</ClCompile>
<Link>
@@ -371,6 +371,7 @@
<ClCompile Include="LayersView.cpp" />
<ClCompile Include="MainFrm.cpp" />
<ClCompile Include="NetEventsView.cpp" />
<ClCompile Include="NewFilterDlg.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@@ -385,6 +386,7 @@
<ClCompile Include="ProvidersView.cpp" />
<ClCompile Include="SessionsView.cpp" />
<ClCompile Include="StringHelper.cpp" />
<ClCompile Include="SubLayerDlg.cpp" />
<ClCompile Include="SublayersView.cpp" />
<ClCompile Include="WFPExplorer.cpp" />
<ClCompile Include="WFPHelper.cpp" />
@@ -405,6 +407,7 @@
<ClInclude Include="LayersView.h" />
<ClInclude Include="MainFrm.h" />
<ClInclude Include="NetEventsView.h" />
<ClInclude Include="NewFilterDlg.h" />
<ClInclude Include="ProcessHelper.h" />
<ClInclude Include="ProviderContextView.h" />
<ClInclude Include="ProviderDlg.h" />
@@ -413,6 +416,7 @@
<ClInclude Include="pch.h" />
<ClInclude Include="SessionsView.h" />
<ClInclude Include="StringHelper.h" />
<ClInclude Include="SubLayerDlg.h" />
<ClInclude Include="SublayersView.h" />
<ClInclude Include="WFPHelper.h" />
</ItemGroup>
+12
View File
@@ -99,6 +99,12 @@
<ClCompile Include="CalloutDlg.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="NewFilterDlg.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
<ClCompile Include="SubLayerDlg.cpp">
<Filter>Dialogs</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@@ -176,6 +182,12 @@
<ClInclude Include="CalloutDlg.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="NewFilterDlg.h">
<Filter>Dialogs</Filter>
</ClInclude>
<ClInclude Include="SubLayerDlg.h">
<Filter>Dialogs</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WFPExplorer.rc">
+5 -1
View File
@@ -1,6 +1,7 @@
#include "pch.h"
#include "WFPHelper.h"
#include <WFPEngine.h>
#include <SortHelper.h>
#include "StringHelper.h"
#include "LayerGeneralPage.h"
#include "LayerFieldsPage.h"
@@ -9,7 +10,7 @@
#include "LayersView.h"
#include "ProviderDlg.h"
#include "CalloutDlg.h"
#include <SortHelper.h>
#include "SubLayerDlg.h"
CString WFPHelper::GetProviderName(WFPEngine const& engine, GUID const& key) {
auto provider = engine.GetProviderByKey(key);
@@ -89,6 +90,9 @@ int WFPHelper::ShowFilterProperties(WFPEngine& engine, FWPM_FILTER* filter) {
}
int WFPHelper::ShowSublayerProperties(WFPEngine& engine, FWPM_SUBLAYER* sublayer) {
CSubLayerDlg dlg(engine, sublayer);
dlg.DoModal();
return 0;
}
+10 -3
View File
@@ -47,8 +47,8 @@
#define IDD_PROVIDER 243
#define IDD_CALLOUT 245
#define IDI_CHECK 247
#define IDI_ICON2 248
#define IDI_RADIO 248
#define IDD_SUBLAYER 249
#define IDC_VERSION 1000
#define IDC_COPYRIGHT 1001
#define IDC_KEY 1001
@@ -65,10 +65,13 @@
#define IDC_CALLOUT_OR_FILTER 1009
#define IDC_LIST 1009
#define IDC_FILTERS 1009
#define IDC_ACTION 1009
#define IDC_ID 1010
#define IDC_CALLOUT 1010
#define IDC_WEIGHT 1011
#define IDC_CALLOUTS 1011
#define IDC_EFFECTIVEWEIGHT 1012
#define IDC_WEIGHTRANGE 1012
#define IDC_SUBLAYER 1013
#define IDC_SUBLAYER_PROP 1014
#define IDC_CALLOUT_PROP 1015
@@ -86,6 +89,10 @@
#define IDC_PROVIDERDATA 1027
#define IDC_SYSLINK1 1028
#define IDC_LINK 1028
#define IDC_AUTOMATIC 1030
#define IDC_SPECIFIC 1031
#define IDC_CONDITIONS 1032
#define IDC_RANGE 1033
#define ID_WINDOW_CLOSE 32772
#define ID_WINDOW_CLOSE_ALL 32773
#define ID_OPTIONS_ALWAYSONTOP 32775
@@ -114,9 +121,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 249
#define _APS_NEXT_RESOURCE_VALUE 251
#define _APS_NEXT_COMMAND_VALUE 32799
#define _APS_NEXT_CONTROL_VALUE 1029
#define _APS_NEXT_CONTROL_VALUE 1036
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+58 -42
View File
@@ -8,6 +8,10 @@
#pragma comment(lib, "Fwpuclnt.lib")
#pragma comment(lib, "Shlwapi.lib")
wchar_t const* StringOrDefault(PCWSTR s, PCWSTR def = L"") {
return s ? s : def;
}
std::wstring GuidToString(GUID const& guid) {
WCHAR sguid[64];
return ::StringFromGUID2(guid, sguid, _countof(sguid)) ? sguid : L"";
@@ -16,61 +20,73 @@ std::wstring GuidToString(GUID const& guid) {
void DisplaySessions(WFPEngine const& engine) {
WFPSessionEnumerator enumerator(engine.Handle());
auto sessions = enumerator.Next(256);
printf("Total sessions: %u\n", (UINT32)sessions.size());
int n = printf("%-39s %-6s %-28s %6s %-28s %s\n",
"Key", "PID", "User name", "Flags", "Name", "Description");
printf("%s\n", std::string(n, '-').c_str());
for (auto const& session : sessions) {
printf("%ws %6u %-28ws %6X %-28ws %ws\n",
printf("%ws %6u %-28ws %6X %-28ws (%ws)\n",
GuidToString(session->sessionKey).c_str(),
session->processId,
session->username,
session->flags,
session->displayData.name,
session->displayData.description);
StringOrDefault(session->displayData.description));
}
printf("Total sessions: %u\n", (UINT32)sessions.size());
}
void DisplayFilters(WFPEngine& engine) {
WFPFilterEnumerator enumerator(engine.Handle());
auto filters = enumerator.Next(8192);
printf("Total filters: %u\n", (UINT32)filters.size());
auto filters = enumerator.Next(16384);
for (auto f : filters) {
printf("%ws %ws %-20ws %-20ws\n",
printf("%ws (Layer: %-20ws) %-20ws %ws\n",
GuidToString(f->filterKey).c_str(),
GuidToString(f->layerKey).c_str(),
engine.GetLayerByKey(f->layerKey)->displayData.name,
f->displayData.name,
f->displayData.description);
StringOrDefault(f->displayData.description));
}
printf("Total filters: %u\n", (UINT32)filters.size());
}
void DisplayCallouts(WFPEngine& engine) {
WFPCalloutEnumerator enumerator(engine.Handle());
auto callouts = enumerator.Next(1024);
printf("Total callouts: %u\n", (UINT32)callouts.size());
for (auto c : callouts) {
printf("%ws %ws %-20ws %-20ws\n",
printf("%ws %ws %-20ws (%ws)\n",
GuidToString(c->calloutKey).c_str(),
c->providerKey ? GuidToString(*c->providerKey).c_str() : L"",
c->displayData.name,
c->displayData.description);
StringOrDefault(c->displayData.description));
}
printf("Total callouts: %u\n", (UINT32)callouts.size());
}
void DisplayProviders(WFPEngine& engine) {
WFPProviderEnumerator enumerator(engine.Handle());
auto providers = enumerator.Next(256);
printf("Total providers: %u\n", (UINT32)providers.size());
for (auto p : providers) {
printf("%ws %-20ws (%ws)\n",
GuidToString(p->providerKey).c_str(),
p->displayData.name,
StringOrDefault(p->displayData.description));
}
}
void DisplayLayers(WFPEngine& engine) {
WFPLayerEnumerator enumerator(engine.Handle());
auto layers = enumerator.Next(1024);
printf("Total layers: %u\n", (UINT32)layers.size());
for (auto layer : layers) {
printf("%ws %5u %ws %2d fields %-20ws %-20ws\n",
printf("%ws %5u %ws %2d fields %-20ws (%ws)\n",
GuidToString(layer->layerKey).c_str(),
layer->layerId,
GuidToString(layer->defaultSubLayerKey).c_str(),
layer->numFields,
layer->displayData.name,
layer->displayData.description);
StringOrDefault(layer->displayData.description));
}
printf("Total layers: %u\n", (UINT32)layers.size());
}
bool IsRunningElevated() {
@@ -89,15 +105,16 @@ bool IsRunningElevated() {
}
int main(int argc, const char* argv[]) {
if (argc < 2) {
printf("Usage: wfpc <s[essions] | c[allouts] | f[ilters] | p[roviders] | l[ayers]>\n");
if (!IsRunningElevated()) {
printf("Please run with admin rights.\n");
return 1;
}
if (argc < 3) {
printf("Usage: wfpc <list | create> <s[essions] | c[allouts] | f[ilters] | p[roviders] | l[ayers]>\n");
return 0;
}
if (!IsRunningElevated()) {
printf("Please run with admin rights.\n");
return 0;
}
WFPEngine engine;
if (!engine.Open()) {
@@ -105,33 +122,32 @@ int main(int argc, const char* argv[]) {
return 1;
}
WFPConnectionEnumerator enumerator(engine.Handle());
auto conns = enumerator.Next(256);
if (_stricmp(argv[1], "list") == 0) {
switch (argv[2][0]) {
case 's': case 'S':
DisplaySessions(engine);
break;
switch (argv[1][0]) {
case 's': case 'S':
DisplaySessions(engine);
break;
case 'p': case 'P':
DisplayProviders(engine);
break;
case 'p': case 'P':
//DisplayProviders(engine);
break;
case 'l': case 'L':
DisplayLayers(engine);
break;
case 'l': case 'L':
DisplayLayers(engine);
break;
case 'f': case 'F':
DisplayFilters(engine);
break;
case 'f': case 'F':
DisplayFilters(engine);
break;
case 'c': case 'C':
DisplayCallouts(engine);
break;
case 'c': case 'C':
DisplayCallouts(engine);
break;
default:
printf("Unknown option.\n");
break;
default:
printf("Unknown option.\n");
break;
}
}
return 0;