diff --git a/2.x/trunk/plugins/NetworkTools/NetworkTools.rc b/2.x/trunk/plugins/NetworkTools/NetworkTools.rc
index c870a4e24..f54c73dbb 100644
--- a/2.x/trunk/plugins/NetworkTools/NetworkTools.rc
+++ b/2.x/trunk/plugins/NetworkTools/NetworkTools.rc
@@ -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
diff --git a/2.x/trunk/plugins/NetworkTools/main.c b/2.x/trunk/plugins/NetworkTools/main.c
index 022aa9991..d771906d2 100644
--- a/2.x/trunk/plugins/NetworkTools/main.c
+++ b/2.x/trunk/plugins/NetworkTools/main.c
@@ -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" },
diff --git a/2.x/trunk/plugins/NetworkTools/nettools.h b/2.x/trunk/plugins/NetworkTools/nettools.h
index 5c6a53262..dd0d09509 100644
--- a/2.x/trunk/plugins/NetworkTools/nettools.h
+++ b/2.x/trunk/plugins/NetworkTools/nettools.h
@@ -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
diff --git a/2.x/trunk/plugins/NetworkTools/output.c b/2.x/trunk/plugins/NetworkTools/output.c
index baa681b25..795ca90b0 100644
--- a/2.x/trunk/plugins/NetworkTools/output.c
+++ b/2.x/trunk/plugins/NetworkTools/output.c
@@ -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);
+ }
}
\ No newline at end of file
diff --git a/2.x/trunk/plugins/NetworkTools/ping.c b/2.x/trunk/plugins/NetworkTools/ping.c
index ce1972e1c..cb9449ad3 100644
--- a/2.x/trunk/plugins/NetworkTools/ping.c
+++ b/2.x/trunk/plugins/NetworkTools/ping.c
@@ -20,9 +20,6 @@
* along with Process Hacker. If not, see .
*/
-#pragma comment(lib, "IPHLPAPI.lib")
-#pragma comment(lib, "Ws2_32.lib")
-
#include "nettools.h"
#include
@@ -30,139 +27,69 @@
#include
#include
-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;
}
\ No newline at end of file
diff --git a/2.x/trunk/plugins/NetworkTools/resource.h b/2.x/trunk/plugins/NetworkTools/resource.h
index 0e4c7e06e..e43431dca 100644
--- a/2.x/trunk/plugins/NetworkTools/resource.h
+++ b/2.x/trunk/plugins/NetworkTools/resource.h
@@ -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