NetworkTools: Added ping history graph

git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5443 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
dmex
2013-09-21 14:09:32 +00:00
parent 9df48b656b
commit c46ebdb533
6 changed files with 558 additions and 295 deletions
@@ -111,6 +111,21 @@ BEGIN
LTEXT "Timeout:",IDC_STATIC,67,22,29,8
END
IDD_PINGDIALOG DIALOGEX 0, 0, 351, 187
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,295,166,50,14
CONTROL "Custom1",IDC_CUSTOM1,"PhGraph",WS_BORDER,7,27,337,90
LTEXT "Pinging X with 32 bytes of data:",IDC_MAINTEXT,7,7,337,16
GROUPBOX "Ping statistics",IDC_STATIC3,7,119,109,60
LTEXT "Lost: 0",IDC_STATIC5,13,166,73,8
LTEXT "Minimum: 0ms",IDC_STATIC6,13,142,73,8
LTEXT "Maximum: 0ms",IDC_STATIC7,13,154,73,8
LTEXT "Average: 0ms",IDC_STATIC8,13,130,73,8
END
/////////////////////////////////////////////////////////////////////////////
//
@@ -135,6 +150,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
IDD_PINGDIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 344
TOPMARGIN, 7
BOTTOMMARGIN, 180
END
END
#endif // APSTUDIO_INVOKED
+3 -1
View File
@@ -115,7 +115,9 @@ LOGICAL DllMain(
PH_SETTING_CREATE settings[] =
{
{ IntegerPairSettingType, L"ProcessHacker.NetTools.NetToolsWindowPosition", L"0,0" },
{ IntegerPairSettingType, L"ProcessHacker.NetTools.NetToolsWindowSize", L"600,365" },
{ IntegerPairSettingType, L"ProcessHacker.NetTools.NetToolsWindowSize", L"600,365" },
{ IntegerPairSettingType, L"ProcessHacker.NetTools.NetToolsPingWindowPosition", L"0,0" },
{ IntegerPairSettingType, L"ProcessHacker.NetTools.NetToolsPingWindowSize", L"600,365" },
{ IntegerSettingType, L"ProcessHacker.NetTools.MaxPingCount", L"4" },
{ IntegerSettingType, L"ProcessHacker.NetTools.MaxPingTimeout", L"5" },
{ IntegerSettingType, L"ProcessHacker.NetTools.EnableHostnameLookup", L"1" },
+15 -1
View File
@@ -52,15 +52,29 @@ typedef struct _NETWORK_OUTPUT_CONTEXT
PH_LAYOUT_MANAGER LayoutManager;
HWND WindowHandle;
BOOLEAN UseOldColors;
PH_QUEUED_LOCK TextBufferLock;
HANDLE ThreadHandle;
HANDLE PipeReadHandle;
HANDLE ProcessHandle;
WCHAR addressString[65];
PH_STRING_BUILDER ReceivedString;
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
ULONG CurrentPingMs;
ULONG PingMinMs;
ULONG PingMaxMs;
ULONG PingAvgMs;
ULONG PingSentCount;
ULONG PingRecvCount;
ULONG PingLossCount;
PH_CIRCULAR_BUFFER_ULONG PingHistory;
PH_GRAPH_STATE PingGraphState;
} NETWORK_OUTPUT_CONTEXT, *PNETWORK_OUTPUT_CONTEXT;
NTSTATUS PhNetworkPingDialogThreadStart(
__in PVOID Parameter
);
VOID PerformNetworkAction(
__in ULONG Action,
__in PPH_NETWORK_ITEM NetworkItem
+93 -116
View File
@@ -25,90 +25,7 @@
static RECT MinimumSize = { -1, -1, -1, -1 };
static NTSTATUS PhNetworkOutputDialogThreadStart(
__in PVOID Parameter
)
{
BOOL result;
MSG message;
PH_AUTO_POOL autoPool;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
PhInitializeAutoPool(&autoPool);
context->WindowHandle = CreateDialogParam(
(HINSTANCE)PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_OUTPUT),
PhMainWndHandle,
NetworkOutputDlgProc,
(LPARAM)Parameter
);
ShowWindow(context->WindowHandle, SW_SHOW);
SetForegroundWindow(context->WindowHandle);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(context->WindowHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
DestroyWindow(context->WindowHandle);
PhFree(context);
return STATUS_SUCCESS;
}
static HFONT InitializeFont(
__in HWND hwndDlg
)
{
LOGFONT logFont = { 0 };
HFONT fontHandle = NULL;
logFont.lfHeight = 14;
logFont.lfWeight = FW_NORMAL;//FW_MEDIUM;
logFont.lfQuality = CLEARTYPE_QUALITY | ANTIALIASED_QUALITY;
// GDI uses the first font that matches the above attributes.
fontHandle = CreateFontIndirect(&logFont);
if (fontHandle)
{
SendMessage(hwndDlg, WM_SETFONT, (WPARAM)fontHandle, FALSE);
return fontHandle;
}
return NULL;
}
VOID PerformNetworkAction(
__in ULONG Action,
__in PPH_NETWORK_ITEM NetworkItem
)
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)PhAllocate(
sizeof(NETWORK_OUTPUT_CONTEXT)
);
memset(context, 0, sizeof(NETWORK_OUTPUT_CONTEXT));
context->Action = Action;
context->NetworkItem = NetworkItem;
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)PhNetworkOutputDialogThreadStart, (PVOID)context))
NtClose(dialogThread);
}
INT_PTR CALLBACK NetworkOutputDlgProc(
static INT_PTR CALLBACK NetworkOutputDlgProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
@@ -129,19 +46,6 @@ INT_PTR CALLBACK NetworkOutputDlgProc(
if (uMsg == WM_NCDESTROY)
{
PhSaveWindowPlacementToSetting(L"ProcessHacker.NetTools.NetToolsWindowPosition", L"ProcessHacker.NetTools.NetToolsWindowSize", hwndDlg);
if (context->ProcessHandle)
{
NtClose(context->ProcessHandle);
context->ProcessHandle = NULL;
}
if (context->ThreadHandle)
{
NtClose(context->ThreadHandle);
context->ThreadHandle = NULL;
}
PhDeleteStringBuilder(&context->ReceivedString);
RemoveProp(hwndDlg, L"Context");
}
@@ -157,9 +61,7 @@ INT_PTR CALLBACK NetworkOutputDlgProc(
PH_RECTANGLE windowRectangle;
HANDLE dialogThread = INVALID_HANDLE_VALUE;
PhInitializeQueuedLock(&context->TextBufferLock);
PhInitializeStringBuilder(&context->ReceivedString, PAGE_SIZE);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_NETOUTPUTEDIT), NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_NETRETRY), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
@@ -203,12 +105,6 @@ INT_PTR CALLBACK NetworkOutputDlgProc(
switch (context->Action)
{
case NETWORK_ACTION_PING:
{
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)NetworkPingThreadStart, (PVOID)context))
NtClose(dialogThread);
}
break;
case NETWORK_ACTION_TRACEROUTE:
{
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)NetworkTracertThreadStart, (PVOID)context))
@@ -229,17 +125,7 @@ INT_PTR CALLBACK NetworkOutputDlgProc(
switch (LOWORD(wParam))
{
case IDC_NETRETRY:
{
HANDLE dialogThread = NULL;
Button_Enable(GetDlgItem(hwndDlg, IDC_NETRETRY), FALSE);
if (context->Action == NETWORK_ACTION_PING)
{
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)NetworkPingThreadStart, (PVOID)context))
NtClose(dialogThread);
}
}
Button_Enable(GetDlgItem(hwndDlg, IDC_NETRETRY), FALSE);
break;
case IDCANCEL:
case IDOK:
@@ -409,4 +295,95 @@ INT_PTR CALLBACK NetworkOutputDlgProc(
}
return FALSE;
}
static NTSTATUS PhNetworkOutputDialogThreadStart(
__in PVOID Parameter
)
{
BOOL result;
MSG message;
PH_AUTO_POOL autoPool;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
PhInitializeAutoPool(&autoPool);
context->WindowHandle = CreateDialogParam(
(HINSTANCE)PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_OUTPUT),
PhMainWndHandle,
NetworkOutputDlgProc,
(LPARAM)Parameter
);
ShowWindow(context->WindowHandle, SW_SHOW);
SetForegroundWindow(context->WindowHandle);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(context->WindowHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
DestroyWindow(context->WindowHandle);
PhFree(context);
return STATUS_SUCCESS;
}
static HFONT InitializeFont(
__in HWND hwndDlg
)
{
LOGFONT logFont = { 0 };
HFONT fontHandle = NULL;
logFont.lfHeight = 14;
logFont.lfWeight = FW_NORMAL;//FW_MEDIUM;
logFont.lfQuality = CLEARTYPE_QUALITY | ANTIALIASED_QUALITY;
// GDI uses the first font that matches the above attributes.
fontHandle = CreateFontIndirect(&logFont);
if (fontHandle)
{
SendMessage(hwndDlg, WM_SETFONT, (WPARAM)fontHandle, FALSE);
return fontHandle;
}
return NULL;
}
VOID PerformNetworkAction(
__in ULONG Action,
__in PPH_NETWORK_ITEM NetworkItem
)
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)PhAllocate(
sizeof(NETWORK_OUTPUT_CONTEXT)
);
memset(context, 0, sizeof(NETWORK_OUTPUT_CONTEXT));
context->Action = Action;
context->NetworkItem = NetworkItem;
if (context->Action == NETWORK_ACTION_PING)
{
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)PhNetworkPingDialogThreadStart, (PVOID)context))
NtClose(dialogThread);
}
else
{
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)PhNetworkOutputDialogThreadStart, (PVOID)context))
NtClose(dialogThread);
}
}
+414 -173
View File
@@ -20,9 +20,6 @@
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma comment(lib, "IPHLPAPI.lib")
#pragma comment(lib, "Ws2_32.lib")
#include "nettools.h"
#include <winsock2.h>
@@ -30,139 +27,69 @@
#include <iphlpapi.h>
#include <icmpapi.h>
ULONG64 PhGetAverage(
__in PULONG64 Buffer,
__in ULONG BufferSize,
__in ULONG BufferPosition,
__in ULONG BufferCount,
__in ULONG NumberToConsider
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
#define WM_PING_UPDATE (WM_APP + 151)
static RECT NormalGraphTextMargin = { 5, 5, 5, 5 };
static RECT NormalGraphTextPadding = { 3, 3, 3, 3 };
static HFONT InitializeFont(
__in HWND hwndDlg
)
{
ULONG64 sum;
ULONG i;
ULONG count;
LOGFONT logFont = { 0 };
HFONT fontHandle = NULL;
sum = 0;
i = BufferPosition;
logFont.lfHeight = 20;
logFont.lfWeight = FW_MEDIUM;
logFont.lfQuality = CLEARTYPE_QUALITY | ANTIALIASED_QUALITY;
if (NumberToConsider > BufferCount)
NumberToConsider = BufferCount;
wcscpy_s(logFont.lfFaceName, _countof(logFont.lfFaceName),
WindowsVersion > WINDOWS_XP ? L"Segoe UI" : L"MS Shell Dlg 2"
);
if (NumberToConsider == 0)
return 0;
fontHandle = CreateFontIndirect(&logFont);
count = NumberToConsider;
do
if (fontHandle)
{
sum += Buffer[i];
i++;
SendMessage(hwndDlg, WM_SETFONT, (WPARAM)fontHandle, FALSE);
return fontHandle;
}
if (i == BufferSize)
i = 0;
} while (--count != 0);
return sum / NumberToConsider;
return NULL;
}
NTSTATUS NetworkPingThreadStart(
static NTSTATUS PhPingNetworkPingThreadStart(
__in PVOID Parameter
)
{
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
ULONG i = 0;
WSADATA wsaData = { 0 };
PPH_ANSI_STRING addrString;
SOCKADDR_IN sock_in;
HANDLE icmpHandle = INVALID_HANDLE_VALUE;
PVOID icmpReplyBuffer = NULL;
{
ULONG icmpReplyLength = 0;
ULONG icmpPingReplyCount = 0;
ULONG pingFirstMs = 0;
ULONG pingSecondMs = 0;
ULONG pingTotalMs = 0;
ULONG pingReplyCount = 0;
ULONG pingLossCount = 0;
ULONG pingSpeed = 0;
ULONG icmpReplyCount = 0;
PVOID icmpReplyBuffer = NULL;
PICMP_ECHO_REPLY icmpReplyStruct = NULL;
HANDLE icmpHandle = INVALID_HANDLE_VALUE;
IP_OPTION_INFORMATION pingOptions = { 0 };
WCHAR hostname[NI_MAXHOST];
WCHAR servInfo[NI_MAXSERV];
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
BOOLEAN isLookupEnabled = !!PhGetIntegerSetting(L"ProcessHacker.NetTools.EnableHostnameLookup");
ULONG maxPingCount = max(PhGetIntegerSetting(L"ProcessHacker.NetTools.MaxPingCount"), 1);
ULONG maxPingTimeout = max(PhGetIntegerSetting(L"ProcessHacker.NetTools.MaxPingTimeout"), 1);
ULONG maxPingCount = __max(PhGetIntegerSetting(L"ProcessHacker.NetTools.MaxPingCount"), 1);
ULONG maxPingTimeout = __max(PhGetIntegerSetting(L"ProcessHacker.NetTools.MaxPingTimeout"), 1);
Static_SetText(context->WindowHandle,
PhFormatString(L"Pinging %s...", context->addressString)->Buffer);
addrString = PhCreateAnsiStringFromUnicode(context->addressString);
WSAStartup(WINSOCK_VERSION, &wsaData);
// This value indicates that the packet should not be fragmented.
//pingOptions.Flags = IP_FLAG_DF;
// Set the TTL field if we are doing a traceroute step.
pingOptions.Ttl = 128;
if (context->NetworkItem->RemoteEndpoint.Address.Type == PH_IPV4_NETWORK_TYPE)
__try
{
pingOptions.Flags = IP_FLAG_DF;
pingOptions.Ttl = 128;
icmpHandle = IcmpCreateFile();
sock_in.sin_family = AF_INET;
sock_in.sin_addr.s_addr = inet_addr(addrString->Buffer);
sock_in.sin_port = (USHORT)context->NetworkItem->RemoteEndpoint.Port;
}
else
{
icmpHandle = Icmp6CreateFile();
sock_in.sin_family = AF_INET6;
}
//Pinging 74.125.31.125 with 32 bytes of data:
//Reply from 74.125.31.125: bytes=32 time=207ms TTL=37
//Reply from 74.125.31.125: bytes=32 time=202ms TTL=38
//Reply from 74.125.31.125: bytes=32 time=206ms TTL=37
//Reply from 74.125.31.125: bytes=32 time=204ms TTL=38
if (isLookupEnabled && GetNameInfo(
(const PSOCKADDR)&sock_in, sizeof(SOCKADDR_IN),
hostname, _countof(hostname),
servInfo, _countof(servInfo),
0
) == 0)
{
PPH_STRING buffer = PhFormatString(
L"Pinging %s:%s [%s] with 32 bytes of data...\r\n\r\n",
context->addressString,
servInfo,
hostname
);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
}
else
{
PPH_STRING buffer = PhFormatString(
L"Pinging %s with 32 bytes of data...\r\n\r\n",
context->addressString
);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
}
// Loop through the 3 sets of pings
for (i = 0; i < maxPingCount; i++)
{
icmpReplyLength = sizeof(ICMP_ECHO_REPLY);
icmpReplyBuffer = PhAllocate(icmpReplyLength);
memset(icmpReplyBuffer, 0, icmpReplyLength);
// First ping with no data
if ((icmpPingReplyCount = IcmpSendEcho(
context->PingSentCount++;
icmpReplyCount = IcmpSendEcho(
icmpHandle,
context->NetworkItem->RemoteEndpoint.Address.InAddr.S_un.S_addr,
NULL, 0,
@@ -170,86 +97,400 @@ NTSTATUS NetworkPingThreadStart(
icmpReplyBuffer,
icmpReplyLength,
maxPingTimeout * 1000
)) == 0)
{
if (WSAGetLastError() != IP_REQ_TIMED_OUT)
{
PPH_STRING buffer = PhFormatString(L"IcmpSendEcho failed: %d\r\n", WSAGetLastError());
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
continue;
}
}
);
icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer;
if (icmpReplyCount > 0 && icmpReplyStruct)
{
//Ping statistics for %s:
// Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
//Approximate round trip times in milli-seconds:
// Minimum = 202ms, Maximum = 207ms, Average = 204ms
if (icmpReplyStruct)
{
// Reply from different address??
// if (icmpReplyStruct->Address == context->Address.InAddr.S_un.S_addr)
// if (icmpReplyStruct->DataSize < max_size
//if (!icmpReplyStruct->RoundTripTime) PPH_STRING buffer = PhFormatString(L"<1 ms ");
pingFirstMs = icmpReplyStruct->RoundTripTime;
//if (icmpReplyStruct->Address == context->Address.InAddr.S_un.S_addr)
//if (icmpReplyStruct->DataSize < max_size)
//if (icmpReplyStruct->RoundTripTime < 1)
switch (icmpReplyStruct->Status)
InterlockedIncrement(&context->PingRecvCount);
if (icmpReplyStruct->Status != IP_SUCCESS)
{
case IP_SUCCESS:
InterlockedIncrement(&context->PingLossCount);
}
context->CurrentPingMs = icmpReplyStruct->RoundTripTime;
if (context->CurrentPingMs < context->PingMinMs)
context->PingMinMs = context->CurrentPingMs;
if (context->CurrentPingMs > context->PingMaxMs)
context->PingMaxMs = context->CurrentPingMs;
PhAddItemCircularBuffer_ULONG(&context->PingHistory, context->CurrentPingMs);
}
else
{
InterlockedIncrement(&context->PingLossCount);
PhAddItemCircularBuffer_ULONG(&context->PingHistory, 0);
}
}
__finally
{
if (icmpReplyBuffer)
{
PhFree(icmpReplyBuffer);
}
if (icmpHandle)
{
IcmpCloseHandle(icmpHandle);
}
}
return STATUS_SUCCESS;
}
static VOID NTAPI NetworkPingUpdateHandler(
__in_opt PVOID Parameter,
__in_opt PVOID Context
)
{
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Context;
HANDLE dialogThread = INVALID_HANDLE_VALUE;
// Queue up the next ping...
// This needs to be done to prevent slow-links from blocking the interval update.
if (dialogThread = PhCreateThread(0, (PUSER_THREAD_START_ROUTINE)PhPingNetworkPingThreadStart, (PVOID)context))
NtClose(dialogThread);
PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0);
}
static INT_PTR CALLBACK NetworkPingWndProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
__in LPARAM lParam
)
{
PNETWORK_OUTPUT_CONTEXT context;
if (uMsg == WM_INITDIALOG)
{
context = (PNETWORK_OUTPUT_CONTEXT)lParam;
SetProp(hwndDlg, L"Context", (HANDLE)context);
}
else
{
context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context");
if (uMsg == WM_NCDESTROY)
{
PhSaveWindowPlacementToSetting(
L"ProcessHacker.NetTools.NetToolsPingWindowPosition",
L"ProcessHacker.NetTools.NetToolsPingWindowSize",
hwndDlg
);
RemoveProp(hwndDlg, L"Context");
}
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PH_RECTANGLE windowRectangle;
// Convert IP Address to string format.
if (context->NetworkItem->RemoteEndpoint.Address.Type == PH_IPV4_NETWORK_TYPE)
{
RtlIpv4AddressToString(
&context->NetworkItem->RemoteEndpoint.Address.InAddr,
context->addressString
);
}
else
{
RtlIpv6AddressToString(
&context->NetworkItem->RemoteEndpoint.Address.In6Addr,
context->addressString
);
}
SetWindowText(hwndDlg, PhaFormatString(L"Ping (%s)", context->addressString)->Buffer);
SetWindowText(GetDlgItem(hwndDlg, IDC_MAINTEXT), PhaFormatString(L"Pinging %s with 32 bytes of data:", context->addressString)->Buffer);
InitializeFont(GetDlgItem(hwndDlg, IDC_MAINTEXT));
PhInitializeGraphState(&context->PingGraphState);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhInitializeCircularBuffer_ULONG(&context->PingHistory, PhGetIntegerSetting(L"SampleCount"));
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_CUSTOM1), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_TOP | PH_ANCHOR_BOTTOM);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_STATIC3), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_STATIC5), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_STATIC6), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_STATIC7), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_STATIC8), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
Graph_SetTooltip(GetDlgItem(hwndDlg, IDC_CUSTOM1), TRUE);
context->UseOldColors = !!PhGetIntegerSetting(L"GraphColorMode");
windowRectangle.Position = PhGetIntegerPairSetting(L"ProcessHacker.NetTools.NetToolsPingWindowPosition");
windowRectangle.Size = PhGetIntegerPairSetting(L"ProcessHacker.NetTools.NetToolsPingWindowSize");
// Load window settings.
if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0)
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
else
{
PhLoadWindowPlacementFromSetting(
L"ProcessHacker.NetTools.NetToolsPingWindowPosition",
L"ProcessHacker.NetTools.NetToolsPingWindowSize",
hwndDlg
);
}
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackProcessesUpdated),
NetworkPingUpdateHandler,
context,
&context->ProcessesUpdatedRegistration
);
}
return TRUE;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
PostQuitMessage(0);
break;
}
}
break;
case WM_DESTROY:
{
PhUnregisterCallback(
PhGetGeneralCallback(GeneralCallbackProcessesUpdated),
&context->ProcessesUpdatedRegistration
);
PhDeleteLayoutManager(&context->LayoutManager);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_SIZING:
PhResizingMinimumSize((PRECT)lParam, wParam, 100, 100);
break;
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
{
HDC hDC = (HDC)wParam;
HWND hwndChild = (HWND)lParam;
// Check for our static label and change the color.
if (GetDlgCtrlID(hwndChild) == IDC_MAINTEXT)
{
SetTextColor(hDC, RGB(19, 112, 171));
}
// Set a transparent background for the control backcolor.
SetBkMode(hDC, TRANSPARENT);
// set window background color.
return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
}
break;
case WM_PING_UPDATE:
{
context->PingGraphState.Valid = FALSE;
context->PingGraphState.TooltipIndex = -1;
Graph_MoveGrid(GetDlgItem(hwndDlg, IDC_CUSTOM1), 1);
Graph_Draw(GetDlgItem(hwndDlg, IDC_CUSTOM1));
Graph_UpdateTooltip(GetDlgItem(hwndDlg, IDC_CUSTOM1));
InvalidateRect(GetDlgItem(hwndDlg, IDC_CUSTOM1), NULL, FALSE);
//SetDlgItemText(hwndDlg, IDC_STATIC2, PhaFormatString(
// L"Sent: %I64u", context->PingSentCount)->Buffer);
SetDlgItemText(hwndDlg, IDC_STATIC5, PhaFormatString(
L"Loss: %I64u (0%% loss)", context->PingLossCount)->Buffer);
SetDlgItemText(hwndDlg, IDC_STATIC6, PhaFormatString(
L"Minimum: %I64ums", context->PingMinMs)->Buffer);
SetDlgItemText(hwndDlg, IDC_STATIC7, PhaFormatString(
L"Maximum: %I64ums", context->PingMaxMs)->Buffer);
SetDlgItemText(hwndDlg, IDC_STATIC8, PhaFormatString(
L"Average: %I64ums", context->PingAvgMs)->Buffer);
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case GCN_GETDRAWINFO:
{
PPH_STRING buffer = PhFormatString(
L"Reply from %s: Time=%dms TTL=%u\r\n",
context->addressString,
icmpReplyStruct->RoundTripTime,
icmpReplyStruct->Options.Ttl
);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
//drawInfo->Flags = ~PH_GRAPH_USE_GRID;
if (context->UseOldColors)
{
drawInfo->BackColor = RGB(0x00, 0x00, 0x00);
drawInfo->LineColor1 = PhGetIntegerSetting(L"ColorCpuKernel");
drawInfo->LineBackColor1 = PhHalveColorBrightness(drawInfo->LineColor1);
drawInfo->LineColor2 = PhGetIntegerSetting(L"ColorCpuUser");
drawInfo->LineBackColor2 = PhHalveColorBrightness(drawInfo->LineColor2);
drawInfo->GridColor = RGB(0x00, 0x57, 0x00);
drawInfo->TextColor = RGB(0x00, 0xff, 0x00);
drawInfo->TextBoxColor = RGB(0x00, 0x22, 0x00);
}
else
{
drawInfo->BackColor = RGB(0xef, 0xef, 0xef);
drawInfo->LineColor1 = PhHalveColorBrightness(PhGetIntegerSetting(L"ColorCpuKernel"));
drawInfo->LineBackColor1 = PhMakeColorBrighter(drawInfo->LineColor1, 125);
drawInfo->LineColor2 = PhHalveColorBrightness(PhGetIntegerSetting(L"ColorCpuUser"));
drawInfo->LineBackColor2 = PhMakeColorBrighter(drawInfo->LineColor2, 125);
drawInfo->GridColor = RGB(0xc7, 0xc7, 0xc7);
drawInfo->TextColor = RGB(0x00, 0x00, 0x00);
drawInfo->TextBoxColor = RGB(0xe7, 0xe7, 0xe7);
}
if (header->hwndFrom == GetDlgItem(hwndDlg, IDC_CUSTOM1))
{
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(GetDlgItem(hwndDlg, IDC_CUSTOM1));
PhSwapReference2(&context->PingGraphState.TooltipText,
PhFormatString(L"Ping: %I64ums", context->CurrentPingMs)
);
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &context->PingGraphState.TooltipText->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
PhGraphStateGetDrawInfo(
&context->PingGraphState,
getDrawInfo,
context->PingHistory.Count
);
if (!context->PingGraphState.Valid)
{
ULONG i = 0;
for (i = 0; i < drawInfo->LineDataCount; i++)
{
context->PingGraphState.Data1[i] =
(FLOAT)PhGetItemCircularBuffer_ULONG(&context->PingHistory, i);
}
// Scale the data.
PhxfDivideSingle2U(
context->PingGraphState.Data1,
(FLOAT)context->PingMaxMs + 5,
drawInfo->LineDataCount
);
context->PingGraphState.Valid = TRUE;
}
}
}
break;
default: // case IP_REQ_TIMED_OUT:
case GCN_GETTOOLTIPTEXT:
{
PPH_STRING buffer = PhFormatString(L"Reply from %s: Timed out...\r\n" , context->addressString);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam;
pingLossCount++;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (header->hwndFrom == GetDlgItem(hwndDlg, IDC_CUSTOM1))
{
if (context->PingGraphState.TooltipIndex != getTooltipText->Index)
{
ULONG usage = PhGetItemCircularBuffer_ULONG(
&context->PingHistory,
getTooltipText->Index
);
PhSwapReference2(&context->PingGraphState.TooltipText, PhFormatString(L"Ping: %I64ums", usage));
}
getTooltipText->Text = context->PingGraphState.TooltipText->sr;
}
}
}
break;
case GCN_MOUSEEVENT:
{
PPH_GRAPH_MOUSEEVENT mouseEvent = (PPH_GRAPH_MOUSEEVENT)lParam;
if (mouseEvent->Message == WM_LBUTTONDBLCLK)
{
if (header->hwndFrom == GetDlgItem(hwndDlg, IDC_CUSTOM1))
{
PhShowInformation(hwndDlg, L"Double clicked!");
}
}
}
break;
}
}
pingTotalMs += (pingSecondMs - pingFirstMs);
pingSecondMs = pingFirstMs;
pingReplyCount++;
break;
}
return FALSE;
}
NTSTATUS PhNetworkPingDialogThreadStart(
__in PVOID Parameter
)
{
BOOL result;
MSG message;
PH_AUTO_POOL autoPool;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
PhInitializeAutoPool(&autoPool);
context->WindowHandle = CreateDialogParam(
(HINSTANCE)PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_PINGDIALOG),
PhMainWndHandle,
NetworkPingWndProc,
(LPARAM)Parameter
);
ShowWindow(context->WindowHandle, SW_SHOW);
SetForegroundWindow(context->WindowHandle);
while (result = GetMessage(&message, NULL, 0, 0))
{
//Ping statistics for %s:
// Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
//Approximate round trip times in milli-seconds:
// Minimum = 202ms, Maximum = 207ms, Average = 204ms
PPH_STRING buffer = PhFormatString(
L"\r\nPing statistics for %s:\r\n"
L" Packets: Sent = %d, Received = %d, Lost = %d (%.0f%% loss)\r\n",
context->addressString,
maxPingCount,
pingReplyCount,
pingLossCount,
(FLOAT)(pingLossCount / maxPingCount) * 100.0f
);
PPH_STRING buffer2 = PhFormatString(
L"Approximate round trip times in milliseconds:\r\n"
L" Minimum = 0ms, Maximum = 0ms, Average = 0ms\r\n\r\n"
);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer, 0);
SendMessage(context->WindowHandle, NTM_RECEIVEDPING, (WPARAM)buffer2, 0);
if (result == -1)
break;
if (!IsDialogMessage(context->WindowHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
if (icmpReplyBuffer)
{
PhFree(icmpReplyBuffer);
icmpReplyBuffer = NULL;
}
IcmpCloseHandle(icmpHandle);
WSACleanup();
Button_Enable(GetDlgItem(context->WindowHandle, IDC_NETRETRY), TRUE);
PhDeleteAutoPool(&autoPool);
DestroyWindow(context->WindowHandle);
PhFree(context);
return STATUS_SUCCESS;
}
+10 -4
View File
@@ -5,6 +5,7 @@
#define ID_TOOLS_PING 101
#define IDD_OUTPUT 101
#define ID_TOOLS_TRACEROUTE 102
#define IDD_PINGDIALOG 102
#define ID_TOOLS_WHOIS 103
#define IDD_OPTIONS 109
#define IDC_NETRESOLVECHECK 1001
@@ -12,16 +13,21 @@
#define IDC_MAXPINGTEXT 1007
#define IDC_MAXTIMEOUTTEXT 1008
#define IDC_NETOUTPUTEDIT 1008
#define IDC_COMBOBOXEX1 1009
#define IDC_COMBOCMD 1009
#define IDC_CUSTOM1 1010
#define IDC_STATIC3 1012
#define IDC_STATIC5 1014
#define IDC_STATIC6 1015
#define IDC_STATIC7 1016
#define IDC_STATIC8 1017
#define IDC_MAINTEXT 1018
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1010
#define _APS_NEXT_CONTROL_VALUE 1019
#define _APS_NEXT_SYMED_VALUE 104
#endif
#endif