go my file uploader

This commit is contained in:
AirDog46
2025-05-13 19:45:22 +03:00
commit c5fab8aa94
708 changed files with 343216 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
1.6
* Added PathPing support
1.5
* Improved ping graph scaling
1.4
* Fixed whois scrolling issue
* Fixed ping threading issues
* Fixed various memory leaks
1.3
* Added plugin options for ping/tracert/whois
* Added native pint/tracert/whois support
* Updated UI
1.2
* Fixed encoding bug
1.1
* Fixed handle leak
1.0
* Initial release

View File

@@ -0,0 +1,196 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (Australia) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,6,0,0
PRODUCTVERSION 1,6,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "0c0904b0"
BEGIN
VALUE "CompanyName", "dmex"
VALUE "FileDescription", "Network Tools plugin for Process Hacker"
VALUE "FileVersion", "1.6"
VALUE "InternalName", "NetworkTools"
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
VALUE "OriginalFilename", "NetworkTools.dll"
VALUE "ProductName", "Network Tools plugin for Process Hacker"
VALUE "ProductVersion", "1.6"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0xc09, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_OUTPUT DIALOGEX 0, 0, 319, 183
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Network Tools"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
EDITTEXT IDC_NETOUTPUTEDIT,7,7,305,152,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | NOT WS_BORDER | WS_VSCROLL,WS_EX_CLIENTEDGE
CONTROL "<a>More information</a>",IDC_MORE_INFO,"SysLink",NOT WS_VISIBLE | WS_TABSTOP,7,163,77,12
PUSHBUTTON "Close",IDOK,263,162,50,14
END
IDD_OPTIONS DIALOGEX 0, 0, 215, 79
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Options"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Timeout (milliseconds):",IDC_STATIC,9,7,73,8
EDITTEXT IDC_MAXTIMEOUTTEXT,7,17,79,14,ES_AUTOHSCROLL | ES_NUMBER
DEFPUSHBUTTON "OK",IDOK,104,58,50,14
PUSHBUTTON "Cancel",IDCANCEL,158,58,50,14
END
IDD_PINGDIALOG DIALOGEX 0, 0, 269, 131
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Pinging X with X bytes of data:",IDC_MAINTEXT,7,7,255,16
LTEXT "PingGraphLayout",IDC_PING_LAYOUT,7,26,255,27,NOT WS_VISIBLE | WS_BORDER
GROUPBOX "Ping statistics",IDC_ICMP_PANEL,7,56,254,52,0,WS_EX_TRANSPARENT
LTEXT "Average: 0ms",IDC_ICMP_AVG,13,69,73,8
LTEXT "Pings sent: 0",IDC_PINGS_SENT,92,69,88,8
LTEXT "Bad hashes: 0",IDC_BAD_HASH,186,69,72,8
LTEXT "Minimum: 0ms",IDC_ICMP_MIN,13,81,73,8
LTEXT "Pings lost: 0 (0%)",IDC_PINGS_LOST,92,81,88,8
LTEXT "Anon replies: 0",IDC_ANON_ADDR,186,81,72,8
LTEXT "Maximum: 0ms",IDC_ICMP_MAX,13,93,73,8
DEFPUSHBUTTON "Close",IDOK,212,110,50,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_OUTPUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 312
TOPMARGIN, 7
BOTTOMMARGIN, 176
END
IDD_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 208
TOPMARGIN, 7
BOTTOMMARGIN, 72
END
IDD_PINGDIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 262
TOPMARGIN, 7
BOTTOMMARGIN, 124
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_OUTPUT AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_OPTIONS AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // English (Australia) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B5E0DA09-EA01-4D5A-A9D6-5B22DB0C306E}</ProjectGuid>
<RootNamespace>NetworkTools</RootNamespace>
<Keyword>Win32Proj</Keyword>
<ProjectName>NetworkTools</ProjectName>
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\Plugins.props" />
</ImportGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release64</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Release32</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64;C:\Users\AirDog46\Downloads\processhacker-2.39-src\bin\Debug64</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<AdditionalDependencies>iphlpapi.lib;winhttp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;winhttp.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<AdditionalDependencies>iphlpapi.lib;winhttp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;winhttp.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Link>
<AdditionalDependencies>iphlpapi.lib;winhttp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;winhttp.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<AdditionalDependencies>iphlpapi.lib;winhttp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>iphlpapi.dll;winhttp.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="options.c" />
<ClCompile Include="output.c" />
<ClCompile Include="ping.c" />
<ClCompile Include="tracert.c" />
<ClCompile Include="whois.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="nettools.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="NetworkTools.rc" />
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="output.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ping.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="options.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tracert.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="whois.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="nettools.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="NetworkTools.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="CHANGELOG.txt" />
</ItemGroup>
</Project>

164
plugins/NetworkTools/main.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* Process Hacker Network Tools -
* main program
*
* Copyright (C) 2010-2011 wj32
* Copyright (C) 2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
PPH_PLUGIN PluginInstance;
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
PH_CALLBACK_REGISTRATION NetworkMenuInitializingCallbackRegistration;
VOID NTAPI ShowOptionsCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
DialogBox(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_OPTIONS),
(HWND)Parameter,
OptionsDlgProc
);
}
VOID NTAPI MenuItemCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_ITEM menuItem = (PPH_PLUGIN_MENU_ITEM)Parameter;
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)menuItem->Context;
switch (menuItem->Id)
{
case NETWORK_ACTION_PING:
PerformNetworkAction(NETWORK_ACTION_PING, networkItem);
break;
case NETWORK_ACTION_TRACEROUTE:
PerformNetworkAction(NETWORK_ACTION_TRACEROUTE, networkItem);
break;
case NETWORK_ACTION_WHOIS:
PerformNetworkAction(NETWORK_ACTION_WHOIS, networkItem);
break;
case NETWORK_ACTION_PATHPING:
PerformNetworkAction(NETWORK_ACTION_PATHPING, networkItem);
break;
}
}
VOID NTAPI NetworkMenuInitializingCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PPH_PLUGIN_MENU_INFORMATION menuInfo = (PPH_PLUGIN_MENU_INFORMATION)Parameter;
PPH_NETWORK_ITEM networkItem;
PPH_EMENU_ITEM toolsMenu;
PPH_EMENU_ITEM closeMenuItem;
if (menuInfo->u.Network.NumberOfNetworkItems == 1)
networkItem = menuInfo->u.Network.NetworkItems[0];
else
networkItem = NULL;
// Create the Tools menu.
toolsMenu = PhPluginCreateEMenuItem(PluginInstance, 0, 0, L"Tools", NULL);
PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_PING, L"Ping", networkItem), -1);
PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_TRACEROUTE, L"Traceroute", networkItem), -1);
PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_WHOIS, L"Whois", networkItem), -1);
PhInsertEMenuItem(toolsMenu, PhPluginCreateEMenuItem(PluginInstance, 0, NETWORK_ACTION_PATHPING, L"PathPing", networkItem), -1);
// Insert the Tools menu into the network menu.
closeMenuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Close", 0);
PhInsertEMenuItem(menuInfo->Menu, toolsMenu, closeMenuItem ? PhIndexOfEMenuItem(menuInfo->Menu, closeMenuItem) : 1);
toolsMenu->Flags |= PH_EMENU_DISABLED;
if (networkItem)
{
if (!PhIsNullIpAddress(&networkItem->RemoteEndpoint.Address))
{
toolsMenu->Flags &= ~PH_EMENU_DISABLED;
}
}
}
LOGICAL DllMain(
_In_ HINSTANCE Instance,
_In_ ULONG Reason,
_Reserved_ PVOID Reserved
)
{
switch (Reason)
{
case DLL_PROCESS_ATTACH:
{
PPH_PLUGIN_INFORMATION info;
PH_SETTING_CREATE settings[] =
{
{ IntegerPairSettingType, SETTING_NAME_TRACERT_WINDOW_POSITION, L"0,0" },
{ ScalableIntegerPairSettingType, SETTING_NAME_TRACERT_WINDOW_SIZE, L"@96|600,365" },
{ IntegerPairSettingType, SETTING_NAME_PING_WINDOW_POSITION, L"0,0" },
{ ScalableIntegerPairSettingType, SETTING_NAME_PING_WINDOW_SIZE, L"@96|420,250" },
{ IntegerSettingType, SETTING_NAME_PING_TIMEOUT, L"3e8" } // 1000 timeout.
};
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
if (!PluginInstance)
return FALSE;
info->DisplayName = L"Network Tools";
info->Author = L"dmex, wj32";
info->Description = L"Provides ping, traceroute and whois for network connections.";
info->Url = L"https://wj32.org/processhacker/forums/viewtopic.php?t=1117";
info->HasOptions = TRUE;
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions),
ShowOptionsCallback,
NULL,
&PluginShowOptionsCallbackRegistration
);
PhRegisterCallback(
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
MenuItemCallback,
NULL,
&PluginMenuItemCallbackRegistration
);
PhRegisterCallback(
PhGetGeneralCallback(GeneralCallbackNetworkMenuInitializing),
NetworkMenuInitializingCallback,
NULL,
&NetworkMenuInitializingCallbackRegistration
);
PhAddSettings(settings, ARRAYSIZE(settings));
}
break;
}
return TRUE;
}

View File

@@ -0,0 +1,145 @@
/*
* Process Hacker ToolStatus -
* toolstatus header
*
* Copyright (C) 2010-2013 wj32
* Copyright (C) 2012-2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NETTOOLS_H
#define NETTOOLS_H
#define CINTERFACE
#define COBJMACROS
#include <windowsx.h>
#include <phdk.h>
#include <phappresource.h>
#include <workqueue.h>
#include <windowsx.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include "resource.h"
#define PLUGIN_NAME L"ProcessHacker.NetworkTools"
#define SETTING_NAME_TRACERT_WINDOW_POSITION (PLUGIN_NAME L".WindowPosition")
#define SETTING_NAME_TRACERT_WINDOW_SIZE (PLUGIN_NAME L".WindowSize")
#define SETTING_NAME_PING_WINDOW_POSITION (PLUGIN_NAME L".PingWindowPosition")
#define SETTING_NAME_PING_WINDOW_SIZE (PLUGIN_NAME L".PingWindowSize")
#define SETTING_NAME_PING_TIMEOUT (PLUGIN_NAME L".PingMaxTimeout")
// ICMP Packet Length: (msdn: IcmpSendEcho2/Icmp6SendEcho2)
// The buffer must be large enough to hold at least one ICMP_ECHO_REPLY or ICMPV6_ECHO_REPLY structure
// + the number of bytes of data specified in the RequestSize parameter.
// This buffer should also be large enough to also hold 8 more bytes of data (the size of an ICMP error message)
// + space for an IO_STATUS_BLOCK structure.
#define ICMP_BUFFER_SIZE(EchoReplyLength, Buffer) (ULONG)(((EchoReplyLength) + (Buffer)->Length) + 8 + sizeof(IO_STATUS_BLOCK))
extern PPH_PLUGIN PluginInstance;
typedef enum _PH_NETWORK_ACTION
{
NETWORK_ACTION_PING,
NETWORK_ACTION_TRACEROUTE,
NETWORK_ACTION_WHOIS,
NETWORK_ACTION_FINISH,
NETWORK_ACTION_PATHPING
} PH_NETWORK_ACTION;
// output
#define NTM_RECEIVEDTRACE (WM_APP + NETWORK_ACTION_TRACEROUTE)
#define NTM_RECEIVEDWHOIS (WM_APP + NETWORK_ACTION_WHOIS)
#define NTM_RECEIVEDFINISH (WM_APP + NETWORK_ACTION_FINISH)
typedef struct _NETWORK_OUTPUT_CONTEXT
{
PH_NETWORK_ACTION Action;
PH_LAYOUT_MANAGER LayoutManager;
PH_WORK_QUEUE PingWorkQueue;
PH_GRAPH_STATE PingGraphState;
PH_CIRCULAR_BUFFER_ULONG PingHistory;
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
HWND WindowHandle;
HWND ParentHandle;
HWND StatusHandle;
HWND PingGraphHandle;
HWND OutputHandle;
HANDLE PipeReadHandle;
HANDLE ProcessHandle;
HFONT FontHandle;
HICON IconHandle;
ULONG CurrentPingMs;
ULONG MaxPingTimeout;
ULONG HashFailCount;
ULONG UnknownAddrCount;
ULONG PingMinMs;
ULONG PingMaxMs;
ULONG PingSentCount;
ULONG PingRecvCount;
ULONG PingLossCount;
PPH_NETWORK_ITEM NetworkItem;
PH_IP_ADDRESS IpAddress;
WCHAR IpAddressString[INET6_ADDRSTRLEN];
} NETWORK_OUTPUT_CONTEXT, *PNETWORK_OUTPUT_CONTEXT;
NTSTATUS PhNetworkPingDialogThreadStart(
_In_ PVOID Parameter
);
VOID PerformNetworkAction(
_In_ PH_NETWORK_ACTION Action,
_In_ PPH_NETWORK_ITEM NetworkItem
);
NTSTATUS NetworkPingThreadStart(
_In_ PVOID Parameter
);
NTSTATUS NetworkTracertThreadStart(
_In_ PVOID Parameter
);
NTSTATUS NetworkWhoisThreadStart(
_In_ PVOID Parameter
);
VOID NTAPI ShowOptionsCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
INT_PTR CALLBACK NetworkOutputDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK OptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
#endif

View File

@@ -0,0 +1,62 @@
/*
* Process Hacker Network Tools -
* options dialog
*
* Copyright (C) 2010-2013 wj32
* Copyright (C) 2012-2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
INT_PTR CALLBACK OptionsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
SetDlgItemInt(hwndDlg, IDC_MAXTIMEOUTTEXT, PhGetIntegerSetting(SETTING_NAME_PING_TIMEOUT), FALSE);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);
break;
case IDOK:
{
ULONG maxPingTimeout = GetDlgItemInt(hwndDlg, IDC_MAXTIMEOUTTEXT, NULL, FALSE);
PhSetIntegerSetting(SETTING_NAME_PING_TIMEOUT, maxPingTimeout);
EndDialog(hwndDlg, IDOK);
}
break;
}
}
break;
}
return FALSE;
}

View File

@@ -0,0 +1,423 @@
/*
* Process Hacker Network Tools -
* output dialog
*
* Copyright (C) 2010-2015 wj32
* Copyright (C) 2012-2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
static RECT MinimumSize = { -1, -1, -1, -1 };
INT_PTR CALLBACK NetworkOutputDlgProc(
_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_DESTROY)
{
PhSaveWindowPlacementToSetting(SETTING_NAME_TRACERT_WINDOW_POSITION, SETTING_NAME_TRACERT_WINDOW_SIZE, hwndDlg);
PhDeleteLayoutManager(&context->LayoutManager);
if (context->ProcessHandle)
{
// Terminate the child process.
PhTerminateProcess(context->ProcessHandle, STATUS_SUCCESS);
// Close the child process handle.
NtClose(context->ProcessHandle);
}
// Close the pipe handle.
if (context->PipeReadHandle)
NtClose(context->PipeReadHandle);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
PostQuitMessage(0);
}
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PH_RECTANGLE windowRectangle;
context->WindowHandle = hwndDlg;
context->OutputHandle = GetDlgItem(hwndDlg, IDC_NETOUTPUTEDIT);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, context->OutputHandle, NULL, PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_MORE_INFO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_TRACERT_WINDOW_POSITION);
windowRectangle.Size = PhGetScalableIntegerPairSetting(SETTING_NAME_TRACERT_WINDOW_SIZE, TRUE).Pair;
if (MinimumSize.left == -1)
{
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = 190;
rect.bottom = 120;
MapDialogRect(hwndDlg, &rect);
MinimumSize = rect;
MinimumSize.left = 0;
}
// Check for first-run default position.
if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0)
{
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
}
else
{
PhLoadWindowPlacementFromSetting(SETTING_NAME_TRACERT_WINDOW_POSITION, SETTING_NAME_TRACERT_WINDOW_SIZE, hwndDlg);
}
if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE)
{
RtlIpv4AddressToString(&context->IpAddress.InAddr, context->IpAddressString);
}
else
{
RtlIpv6AddressToString(&context->IpAddress.In6Addr, context->IpAddressString);
}
switch (context->Action)
{
case NETWORK_ACTION_TRACEROUTE:
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
Static_SetText(context->WindowHandle,
PhaFormatString(L"Tracing route to %s...", context->IpAddressString)->Buffer
);
if (dialogThread = PhCreateThread(0, NetworkTracertThreadStart, (PVOID)context))
NtClose(dialogThread);
}
break;
case NETWORK_ACTION_WHOIS:
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
Static_SetText(context->WindowHandle,
PhaFormatString(L"Whois %s...", context->IpAddressString)->Buffer
);
ShowWindow(GetDlgItem(hwndDlg, IDC_MORE_INFO), SW_SHOW);
if (dialogThread = PhCreateThread(0, NetworkWhoisThreadStart, (PVOID)context))
NtClose(dialogThread);
}
break;
case NETWORK_ACTION_PATHPING:
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
Static_SetText(context->WindowHandle,
PhaFormatString(L"Pathing route to %s...", context->IpAddressString)->Buffer
);
if (dialogThread = PhCreateThread(0, NetworkTracertThreadStart, (PVOID)context))
NtClose(dialogThread);
}
break;
}
}
break;
case WM_COMMAND:
{
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDCANCEL:
case IDOK:
DestroyWindow(hwndDlg);
break;
}
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_SIZING:
PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
break;
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
{
HDC hDC = (HDC)wParam;
HWND hwndChild = (HWND)lParam;
// Check if old graph colors are enabled.
if (!PhGetIntegerSetting(L"GraphColorMode"))
break;
// Check for our edit control and change the color.
if (hwndChild == context->OutputHandle)
{
// Set a transparent background for the control backcolor.
//SetBkMode(hDC, TRANSPARENT);
// Set the Edit control background.
SetBkColor(hDC, RGB(0x0, 0x0, 0x0));
// Set text color as the Green PH graph text color.
SetTextColor(hDC, RGB(124, 252, 0));
// Set a black control backcolor.
return (INT_PTR)GetStockBrush(BLACK_BRUSH);
}
}
break;
case WM_NOTIFY:
{
switch (((LPNMHDR)lParam)->code)
{
case NM_CLICK:
case NM_RETURN:
{
PNMLINK syslink = (PNMLINK)lParam;
if (syslink->hdr.idFrom == IDC_MORE_INFO)
{
PhShellExecute(
PhMainWndHandle,
PhaConcatStrings2(L"http://wq.apnic.net/apnic-bin/whois.pl?searchtext=", context->IpAddressString)->Buffer,
NULL
);
}
}
break;
}
}
break;
case NTM_RECEIVEDTRACE:
{
OEM_STRING inputString;
UNICODE_STRING convertedString;
PH_STRING_BUILDER receivedString;
if (wParam != 0)
{
inputString.Buffer = (PCHAR)lParam;
inputString.Length = (USHORT)wParam;
if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE)))
{
PPH_STRING windowText = NULL;
PhInitializeStringBuilder(&receivedString, PAGE_SIZE);
// Get the current output text.
windowText = PhGetWindowText(context->OutputHandle);
// Append the current output text to the New string.
if (!PhIsNullOrEmptyString(windowText))
PhAppendStringBuilder(&receivedString, &windowText->sr);
PhAppendFormatStringBuilder(&receivedString, L"%s", convertedString.Buffer);
// Remove leading newlines.
if (receivedString.String->Length >= 2 * 2 &&
receivedString.String->Buffer[0] == '\r' &&
receivedString.String->Buffer[1] == '\n')
{
PhRemoveStringBuilder(&receivedString, 0, 2);
}
SetWindowText(context->OutputHandle, receivedString.String->Buffer);
SendMessage(
context->OutputHandle,
EM_SETSEL,
receivedString.String->Length / 2 - 1,
receivedString.String->Length / 2 - 1
);
SendMessage(context->OutputHandle, WM_VSCROLL, SB_BOTTOM, 0);
PhDereferenceObject(windowText);
PhDeleteStringBuilder(&receivedString);
RtlFreeUnicodeString(&convertedString);
}
}
}
break;
case NTM_RECEIVEDWHOIS:
{
OEM_STRING inputString;
UNICODE_STRING convertedString;
PH_STRING_BUILDER receivedString;
if (lParam != 0)
{
inputString.Buffer = (PCHAR)lParam;
inputString.Length = (USHORT)wParam;
if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE)))
{
USHORT i;
PhInitializeStringBuilder(&receivedString, PAGE_SIZE);
// Convert carriage returns.
for (i = 0; i < convertedString.Length; i++)
{
if (convertedString.Buffer[i] == '\n')
{
PhAppendStringBuilder2(&receivedString, L"\r\n");
}
else
{
PhAppendCharStringBuilder(&receivedString, convertedString.Buffer[i]);
}
}
// Remove leading newlines.
if (receivedString.String->Length >= 2 * 2 &&
receivedString.String->Buffer[0] == '\r' &&
receivedString.String->Buffer[1] == '\n')
{
PhRemoveStringBuilder(&receivedString, 0, 2);
}
SetWindowText(context->OutputHandle, receivedString.String->Buffer);
SendMessage(
context->OutputHandle,
EM_SETSEL,
receivedString.String->Length / 2 - 1,
receivedString.String->Length / 2 - 1
);
SendMessage(context->OutputHandle, WM_VSCROLL, SB_TOP, 0);
PhDeleteStringBuilder(&receivedString);
RtlFreeUnicodeString(&convertedString);
}
PhFree((PVOID)lParam);
}
}
break;
case NTM_RECEIVEDFINISH:
{
PPH_STRING windowText = PhGetWindowText(context->WindowHandle);
if (windowText)
{
Static_SetText(
context->WindowHandle,
PhaFormatString(L"%s Finished.", windowText->Buffer)->Buffer
);
PhDereferenceObject(windowText);
}
}
break;
}
return FALSE;
}
NTSTATUS PhNetworkOutputDialogThreadStart(
_In_ PVOID Parameter
)
{
BOOL result;
MSG message;
HWND windowHandle;
PH_AUTO_POOL autoPool;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
PhInitializeAutoPool(&autoPool);
windowHandle = CreateDialogParam(
(HINSTANCE)PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_OUTPUT),
PhMainWndHandle,
NetworkOutputDlgProc,
(LPARAM)Parameter
);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(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);
return STATUS_SUCCESS;
}
VOID PerformNetworkAction(
_In_ PH_NETWORK_ACTION Action,
_In_ PPH_NETWORK_ITEM NetworkItem
)
{
HANDLE dialogThread = INVALID_HANDLE_VALUE;
PNETWORK_OUTPUT_CONTEXT context;
context = (PNETWORK_OUTPUT_CONTEXT)PhAllocate(sizeof(NETWORK_OUTPUT_CONTEXT));
memset(context, 0, sizeof(NETWORK_OUTPUT_CONTEXT));
context->Action = Action;
context->NetworkItem = NetworkItem;
context->IpAddress = NetworkItem->RemoteEndpoint.Address;
if (context->Action == NETWORK_ACTION_PING)
{
if (dialogThread = PhCreateThread(0, PhNetworkPingDialogThreadStart, (PVOID)context))
NtClose(dialogThread);
}
else
{
if (dialogThread = PhCreateThread(0, PhNetworkOutputDialogThreadStart, (PVOID)context))
NtClose(dialogThread);
}
}

757
plugins/NetworkTools/ping.c Normal file
View File

@@ -0,0 +1,757 @@
/*
* Process Hacker Network Tools -
* Ping dialog
*
* Copyright (C) 2015 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
#define WM_PING_UPDATE (WM_APP + 151)
static RECT NormalGraphTextMargin = { 5, 5, 5, 5 };
static RECT NormalGraphTextPadding = { 3, 3, 3, 3 };
HFONT InitializeFont(
_In_ HWND hwnd
)
{
LOGFONT logFont;
// Create the font handle
if (SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &logFont, 0))
{
HDC hdc;
if (hdc = GetDC(hwnd))
{
HFONT fontHandle = CreateFont(
-MulDiv(-15, GetDeviceCaps(hdc, LOGPIXELSY), 72),
0,
0,
0,
FW_MEDIUM,
FALSE,
FALSE,
FALSE,
ANSI_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
CLEARTYPE_QUALITY | ANTIALIASED_QUALITY,
DEFAULT_PITCH,
logFont.lfFaceName
);
SendMessage(hwnd, WM_SETFONT, (WPARAM)fontHandle, TRUE);
ReleaseDC(hwnd, hdc);
return fontHandle;
}
}
return NULL;
}
VOID NetworkPingUpdateGraph(
_In_ PNETWORK_OUTPUT_CONTEXT Context
)
{
Context->PingGraphState.Valid = FALSE;
Context->PingGraphState.TooltipIndex = -1;
Graph_MoveGrid(Context->PingGraphHandle, 1);
Graph_Draw(Context->PingGraphHandle);
Graph_UpdateTooltip(Context->PingGraphHandle);
InvalidateRect(Context->PingGraphHandle, NULL, FALSE);
}
/**
* Creates a Ansi string using format specifiers.
*
* \param Format The format-control string.
* \param ArgPtr A pointer to the list of arguments.
*/
PPH_BYTES FormatAnsiString_V(
_In_ _Printf_format_string_ PSTR Format,
_In_ va_list ArgPtr
)
{
PPH_BYTES string;
int length;
length = _vscprintf(Format, ArgPtr);
if (length == -1)
return NULL;
string = PhCreateBytesEx(NULL, length * sizeof(CHAR));
_vsnprintf(
string->Buffer,
length,
Format, ArgPtr
);
return string;
}
/**
* Creates a Ansi string using format specifiers.
*
* \param Format The format-control string.
*/
PPH_BYTES FormatAnsiString(
_In_ _Printf_format_string_ PSTR Format,
...
)
{
va_list argptr;
va_start(argptr, Format);
return FormatAnsiString_V(Format, argptr);
}
NTSTATUS NetworkPingThreadStart(
_In_ PVOID Parameter
)
{
HANDLE icmpHandle = INVALID_HANDLE_VALUE;
ULONG icmpCurrentPingMs = 0;
ULONG icmpCurrentPingTtl = 0;
ULONG icmpReplyCount = 0;
ULONG icmpReplyLength = 0;
PVOID icmpReplyBuffer = NULL;
PPH_STRING phVersion = NULL;
PPH_BYTES icmpEchoBuffer = NULL;
IP_OPTION_INFORMATION pingOptions =
{
255, // Time To Live
0, // Type Of Service
IP_FLAG_DF, // IP header flags
0 // Size of options data
};
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
__try
{
// Query PH version.
if ((phVersion = PhGetPhVersion()) == NULL)
__leave;
// Create ICMP echo buffer.
if ((icmpEchoBuffer = FormatAnsiString("processhacker_%S_0x0D06F00D_x1", phVersion->Buffer)) == NULL)
__leave;
if (context->IpAddress.Type == PH_IPV6_NETWORK_TYPE)
{
SOCKADDR_IN6 icmp6LocalAddr = { 0 };
SOCKADDR_IN6 icmp6RemoteAddr = { 0 };
PICMPV6_ECHO_REPLY icmp6ReplyStruct = NULL;
// Create ICMPv6 handle.
if ((icmpHandle = Icmp6CreateFile()) == INVALID_HANDLE_VALUE)
__leave;
// Set Local IPv6-ANY address.
icmp6LocalAddr.sin6_addr = in6addr_any;
icmp6LocalAddr.sin6_family = AF_INET6;
// Set Remote IPv6 address.
icmp6RemoteAddr.sin6_addr = context->IpAddress.In6Addr;
icmp6RemoteAddr.sin6_port = _byteswap_ushort((USHORT)context->NetworkItem->RemoteEndpoint.Port);
// Allocate ICMPv6 message.
icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMPV6_ECHO_REPLY), icmpEchoBuffer);
icmpReplyBuffer = PhAllocate(icmpReplyLength);
memset(icmpReplyBuffer, 0, icmpReplyLength);
InterlockedIncrement(&context->PingSentCount);
// Send ICMPv6 ping...
icmpReplyCount = Icmp6SendEcho2(
icmpHandle,
NULL,
NULL,
NULL,
&icmp6LocalAddr,
&icmp6RemoteAddr,
icmpEchoBuffer->Buffer,
(USHORT)icmpEchoBuffer->Length,
&pingOptions,
icmpReplyBuffer,
icmpReplyLength,
context->MaxPingTimeout
);
icmp6ReplyStruct = (PICMPV6_ECHO_REPLY)icmpReplyBuffer;
if (icmpReplyCount > 0 && icmp6ReplyStruct)
{
BOOLEAN icmpPacketSignature = FALSE;
if (icmp6ReplyStruct->Status != IP_SUCCESS)
{
InterlockedIncrement(&context->PingLossCount);
}
if (_memicmp(
icmp6ReplyStruct->Address.sin6_addr,
context->IpAddress.In6Addr.u.Word,
sizeof(icmp6ReplyStruct->Address.sin6_addr)
) != 0)
{
InterlockedIncrement(&context->UnknownAddrCount);
}
//if (icmp6ReplyStruct->DataSize == icmpEchoBuffer->MaximumLength)
//{
// icmpPacketSignature = (_memicmp(
// icmpEchoBuffer->Buffer,
// icmp6ReplyStruct->Data,
// icmp6ReplyStruct->DataSize
// ) == 0);
//}
//if (icmpPacketSignature != TRUE)
//{
// InterlockedIncrement(&context->HashFailCount);
//}
icmpCurrentPingMs = icmp6ReplyStruct->RoundTripTime;
//icmpCurrentPingTtl = icmp6ReplyStruct->Options.Ttl;
}
else
{
InterlockedIncrement(&context->PingLossCount);
}
}
else
{
IPAddr icmpLocalAddr = 0;
IPAddr icmpRemoteAddr = 0;
PICMP_ECHO_REPLY icmpReplyStruct = NULL;
// Create ICMPv4 handle.
if ((icmpHandle = IcmpCreateFile()) == INVALID_HANDLE_VALUE)
__leave;
// Set Local IPv4-ANY address.
icmpLocalAddr = in4addr_any.s_addr;
// Set Remote IPv4 address.
icmpRemoteAddr = context->IpAddress.InAddr.s_addr;
// Allocate ICMPv4 message.
icmpReplyLength = ICMP_BUFFER_SIZE(sizeof(ICMP_ECHO_REPLY), icmpEchoBuffer);
icmpReplyBuffer = PhAllocate(icmpReplyLength);
memset(icmpReplyBuffer, 0, icmpReplyLength);
InterlockedIncrement(&context->PingSentCount);
// Send ICMPv4 ping...
//if (WindowsVersion > WINDOWS_VISTA)
//{
// // Vista SP1 and up we can specify the source address:
// icmpReplyCount = IcmpSendEcho2Ex(
// icmpHandle,
// NULL,
// NULL,
// NULL,
// icmpLocalAddr,
// icmpRemoteAddr,
// icmpEchoBuffer->Buffer,
// icmpEchoBuffer->MaximumLength,
// &pingOptions,
// icmpReplyBuffer,
// icmpReplyLength,
// context->MaxPingTimeout
// );
//}
icmpReplyCount = IcmpSendEcho2(
icmpHandle,
NULL,
NULL,
NULL,
icmpRemoteAddr,
icmpEchoBuffer->Buffer,
(USHORT)icmpEchoBuffer->Length,
&pingOptions,
icmpReplyBuffer,
icmpReplyLength,
context->MaxPingTimeout
);
icmpReplyStruct = (PICMP_ECHO_REPLY)icmpReplyBuffer;
if (icmpReplyStruct && icmpReplyCount > 0)
{
BOOLEAN icmpPacketSignature = FALSE;
if (icmpReplyStruct->Status != IP_SUCCESS)
{
InterlockedIncrement(&context->PingLossCount);
}
if (icmpReplyStruct->Address != context->IpAddress.InAddr.s_addr)
{
InterlockedIncrement(&context->UnknownAddrCount);
}
if (icmpReplyStruct->DataSize == icmpEchoBuffer->Length)
{
icmpPacketSignature = (_memicmp(
icmpEchoBuffer->Buffer,
icmpReplyStruct->Data,
icmpReplyStruct->DataSize
) == 0);
}
icmpCurrentPingMs = icmpReplyStruct->RoundTripTime;
icmpCurrentPingTtl = icmpReplyStruct->Options.Ttl;
if (!icmpPacketSignature)
{
InterlockedIncrement(&context->HashFailCount);
}
}
else
{
InterlockedIncrement(&context->PingLossCount);
}
}
InterlockedIncrement(&context->PingRecvCount);
if (context->PingMinMs == 0 || icmpCurrentPingMs < context->PingMinMs)
context->PingMinMs = icmpCurrentPingMs;
if (icmpCurrentPingMs > context->PingMaxMs)
context->PingMaxMs = icmpCurrentPingMs;
context->CurrentPingMs = icmpCurrentPingMs;
PhAddItemCircularBuffer_ULONG(&context->PingHistory, icmpCurrentPingMs);
}
__finally
{
if (phVersion)
{
PhDereferenceObject(phVersion);
}
if (icmpEchoBuffer)
{
PhDereferenceObject(icmpEchoBuffer);
}
if (icmpHandle != INVALID_HANDLE_VALUE)
{
IcmpCloseHandle(icmpHandle);
}
if (icmpReplyBuffer)
{
PhFree(icmpReplyBuffer);
}
}
PostMessage(context->WindowHandle, WM_PING_UPDATE, 0, 0);
return STATUS_SUCCESS;
}
VOID NTAPI NetworkPingUpdateHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Context;
// Queue up the next ping into our work queue...
PhQueueItemWorkQueue(
&context->PingWorkQueue,
NetworkPingThreadStart,
(PVOID)context
);
}
INT_PTR CALLBACK NetworkPingWndProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PNETWORK_OUTPUT_CONTEXT context = NULL;
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 (context == NULL)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
PH_RECTANGLE windowRectangle;
PPH_LAYOUT_ITEM panelItem;
// We have already set the group boxes to have WS_EX_TRANSPARENT to fix
// the drawing issue that arises when using WS_CLIPCHILDREN. However
// in removing the flicker from the graphs the group boxes will now flicker.
// It's a good tradeoff since no one stares at the group boxes.
PhSetWindowStyle(hwndDlg, WS_CLIPCHILDREN, WS_CLIPCHILDREN);
context->WindowHandle = hwndDlg;
context->ParentHandle = GetParent(hwndDlg);
context->StatusHandle = GetDlgItem(hwndDlg, IDC_MAINTEXT);
context->MaxPingTimeout = PhGetIntegerSetting(SETTING_NAME_PING_TIMEOUT);
windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_PING_WINDOW_POSITION);
windowRectangle.Size = PhGetScalableIntegerPairSetting(SETTING_NAME_PING_WINDOW_SIZE, TRUE).Pair;
// Create the font handle.
context->FontHandle = InitializeFont(context->StatusHandle);
// Create the graph control.
context->PingGraphHandle = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
hwndDlg,
NULL,
NULL,
NULL
);
Graph_SetTooltip(context->PingGraphHandle, TRUE);
// Load the Process Hacker icon.
context->IconHandle = (HICON)LoadImage(
NtCurrentPeb()->ImageBaseAddress,
MAKEINTRESOURCE(PHAPP_IDI_PROCESSHACKER),
IMAGE_ICON,
GetSystemMetrics(SM_CXICON),
GetSystemMetrics(SM_CYICON),
LR_SHARED
);
// Set window icon.
if (context->IconHandle)
SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)context->IconHandle);
// Initialize the WorkQueue with a maximum of 20 threads (fix pinging slow-links with a high interval update).
PhInitializeWorkQueue(&context->PingWorkQueue, 0, 20, 5000);
PhInitializeGraphState(&context->PingGraphState);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhInitializeCircularBuffer_ULONG(&context->PingHistory, PhGetIntegerSetting(L"SampleCount"));
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_PANEL), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_AVG), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MIN), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ICMP_MAX), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_SENT), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PINGS_LOST), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BAD_HASH), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_ANON_ADDR), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT);
panelItem = PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_PING_LAYOUT), NULL, PH_ANCHOR_ALL);
PhAddLayoutItemEx(&context->LayoutManager, context->PingGraphHandle, NULL, PH_ANCHOR_ALL, panelItem->Margin);
// Load window settings.
if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0)
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
else
{
PhLoadWindowPlacementFromSetting(SETTING_NAME_PING_WINDOW_POSITION, SETTING_NAME_PING_WINDOW_SIZE, hwndDlg);
}
// Initialize window layout.
PhLayoutManagerLayout(&context->LayoutManager);
// Convert IP Address to string format.
if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE)
{
RtlIpv4AddressToString(&context->IpAddress.InAddr, context->IpAddressString);
}
else
{
RtlIpv6AddressToString(&context->IpAddress.In6Addr, context->IpAddressString);
}
SetWindowText(hwndDlg, PhaFormatString(L"Ping %s", context->IpAddressString)->Buffer);
SetWindowText(context->StatusHandle, PhaFormatString(L"Pinging %s with 32 bytes of data:", context->IpAddressString)->Buffer);
PhRegisterCallback(
&PhProcessesUpdatedEvent,
NetworkPingUpdateHandler,
context,
&context->ProcessesUpdatedRegistration
);
}
return TRUE;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
DestroyWindow(hwndDlg);
break;
}
}
break;
case WM_DESTROY:
{
PhUnregisterCallback(
&PhProcessesUpdatedEvent,
&context->ProcessesUpdatedRegistration
);
PhSaveWindowPlacementToSetting(
SETTING_NAME_PING_WINDOW_POSITION,
SETTING_NAME_PING_WINDOW_SIZE,
hwndDlg
);
if (context->PingGraphHandle)
DestroyWindow(context->PingGraphHandle);
if (context->IconHandle)
DestroyIcon(context->IconHandle);
if (context->FontHandle)
DeleteObject(context->FontHandle);
PhDeleteWorkQueue(&context->PingWorkQueue);
PhDeleteGraphState(&context->PingGraphState);
PhDeleteLayoutManager(&context->LayoutManager);
RemoveProp(hwndDlg, L"Context");
PhFree(context);
PostQuitMessage(0);
}
break;
case WM_SIZE:
PhLayoutManagerLayout(&context->LayoutManager);
break;
case WM_SIZING:
PhResizingMinimumSize((PRECT)lParam, wParam, 420, 250);
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:
{
ULONG i = 0;
ULONG maxGraphHeight = 0;
ULONG pingAvgValue = 0;
NetworkPingUpdateGraph(context);
for (i = 0; i < context->PingHistory.Count; i++)
{
maxGraphHeight = maxGraphHeight + PhGetItemCircularBuffer_ULONG(&context->PingHistory, i);
pingAvgValue = maxGraphHeight / context->PingHistory.Count;
}
SetDlgItemText(hwndDlg, IDC_ICMP_AVG, PhaFormatString(
L"Average: %lums", pingAvgValue)->Buffer);
SetDlgItemText(hwndDlg, IDC_ICMP_MIN, PhaFormatString(
L"Minimum: %lums", context->PingMinMs)->Buffer);
SetDlgItemText(hwndDlg, IDC_ICMP_MAX, PhaFormatString(
L"Maximum: %lums", context->PingMaxMs)->Buffer);
SetDlgItemText(hwndDlg, IDC_PINGS_SENT, PhaFormatString(
L"Pings sent: %lu", context->PingSentCount)->Buffer);
SetDlgItemText(hwndDlg, IDC_PINGS_LOST, PhaFormatString(
L"Pings lost: %lu (%.0f%%)", context->PingLossCount,
((FLOAT)context->PingLossCount / context->PingSentCount * 100)
)->Buffer);
SetDlgItemText(hwndDlg, IDC_BAD_HASH, PhaFormatString(
L"Bad hashes: %lu", context->HashFailCount)->Buffer);
SetDlgItemText(hwndDlg, IDC_ANON_ADDR, PhaFormatString(
L"Anon replies: %lu", context->UnknownAddrCount)->Buffer);
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
if (header->hwndFrom == context->PingGraphHandle)
{
if (PhGetIntegerSetting(L"GraphShowText"))
{
HDC hdc = Graph_GetBufferedContext(context->PingGraphHandle);
PhMoveReference(&context->PingGraphState.Text,
PhFormatString(L"Ping: %lums", context->CurrentPingMs)
);
SelectObject(hdc, PhApplicationFont);
PhSetGraphText(hdc, drawInfo, &context->PingGraphState.Text->sr,
&NormalGraphTextMargin, &NormalGraphTextPadding, PH_ALIGN_TOP | PH_ALIGN_LEFT);
}
else
{
drawInfo->Text.Buffer = NULL;
}
drawInfo->Flags = PH_GRAPH_USE_GRID_X | PH_GRAPH_USE_GRID_Y;
PhSiSetColorsGraphDrawInfo(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
PhGraphStateGetDrawInfo(&context->PingGraphState, getDrawInfo, context->PingHistory.Count);
if (!context->PingGraphState.Valid)
{
ULONG i;
FLOAT max = 0;
for (i = 0; i < drawInfo->LineDataCount; i++)
{
FLOAT data1;
context->PingGraphState.Data1[i] = data1 = (FLOAT)PhGetItemCircularBuffer_ULONG(&context->PingHistory, i);
if (max < data1)
max = data1;
}
// Minimum scaling of timeout (1000ms default).
if (max < (FLOAT)context->MaxPingTimeout)
max = (FLOAT)context->MaxPingTimeout;
// Scale the data.
PhDivideSinglesBySingle(
context->PingGraphState.Data1,
max,
drawInfo->LineDataCount
);
context->PingGraphState.Valid = TRUE;
}
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)lParam;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
if (header->hwndFrom == context->PingGraphHandle)
{
if (context->PingGraphState.TooltipIndex != getTooltipText->Index)
{
ULONG pingMs = PhGetItemCircularBuffer_ULONG(&context->PingHistory, getTooltipText->Index);
PhMoveReference(&context->PingGraphState.TooltipText,
PhFormatString(L"Ping: %lums", pingMs)
);
}
getTooltipText->Text = context->PingGraphState.TooltipText->sr;
}
}
}
break;
}
}
break;
}
return FALSE;
}
NTSTATUS PhNetworkPingDialogThreadStart(
_In_ PVOID Parameter
)
{
BOOL result;
MSG message;
HWND windowHandle;
PH_AUTO_POOL autoPool;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
PhInitializeAutoPool(&autoPool);
windowHandle = CreateDialogParam(
(HINSTANCE)PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_PINGDIALOG),
PhMainWndHandle,
NetworkPingWndProc,
(LPARAM)Parameter
);
ShowWindow(windowHandle, SW_SHOW);
SetForegroundWindow(windowHandle);
while (result = GetMessage(&message, NULL, 0, 0))
{
if (result == -1)
break;
if (!IsDialogMessage(windowHandle, &message))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
PhDrainAutoPool(&autoPool);
}
PhDeleteAutoPool(&autoPool);
return STATUS_SUCCESS;
}

View File

@@ -0,0 +1,31 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by NetworkTools.rc
//
#define IDD_OUTPUT 101
#define IDD_PINGDIALOG 102
#define IDD_OPTIONS 103
#define IDC_MAXTIMEOUTTEXT 1008
#define IDC_NETOUTPUTEDIT 1009
#define IDC_ICMP_PANEL 1011
#define IDC_PINGS_LOST 1012
#define IDC_ICMP_MIN 1013
#define IDC_ICMP_MAX 1014
#define IDC_ICMP_AVG 1015
#define IDC_MAINTEXT 1016
#define IDC_ANON_ADDR 1017
#define IDC_MORE_INFO 1019
#define IDC_PINGS_SENT 1020
#define IDC_PING_LAYOUT 1021
#define IDC_BAD_HASH 1022
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1022
#define _APS_NEXT_SYMED_VALUE 104
#endif
#endif

View File

@@ -0,0 +1,158 @@
/*
* Process Hacker Network Tools -
* Tracert dialog
*
* Copyright (C) 2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
NTSTATUS StdOutNetworkTracertThreadStart(
_In_ PVOID Parameter
)
{
NTSTATUS status;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
IO_STATUS_BLOCK isb;
UCHAR buffer[PAGE_SIZE];
while (TRUE)
{
status = NtReadFile(
context->PipeReadHandle,
NULL,
NULL,
NULL,
&isb,
buffer,
sizeof(buffer),
NULL,
NULL
);
if (!NT_SUCCESS(status))
break;
SendMessage(context->WindowHandle, NTM_RECEIVEDTRACE, (WPARAM)isb.Information, (LPARAM)buffer);
}
SendMessage(context->WindowHandle, NTM_RECEIVEDFINISH, 0, 0);
return STATUS_SUCCESS;
}
NTSTATUS NetworkTracertThreadStart(
_In_ PVOID Parameter
)
{
HANDLE pipeWriteHandle = INVALID_HANDLE_VALUE;
PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter;
if (CreatePipe(&context->PipeReadHandle, &pipeWriteHandle, NULL, 0))
{
HANDLE threadHandle = NULL;
STARTUPINFO startupInfo = { sizeof(startupInfo) };
OBJECT_HANDLE_FLAG_INFORMATION flagInfo;
PPH_STRING command = NULL;
startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startupInfo.hStdOutput = pipeWriteHandle;
startupInfo.hStdError = pipeWriteHandle;
startupInfo.wShowWindow = SW_HIDE;
switch (context->Action)
{
case NETWORK_ACTION_TRACEROUTE:
{
if (PhGetIntegerSetting(L"EnableNetworkResolve"))
{
command = PhFormatString(
L"%s\\system32\\tracert.exe %s",
USER_SHARED_DATA->NtSystemRoot,
context->IpAddressString
);
}
else
{
// Disable hostname lookup.
command = PhFormatString(
L"%s\\system32\\tracert.exe -d %s",
USER_SHARED_DATA->NtSystemRoot,
context->IpAddressString
);
}
}
break;
case NETWORK_ACTION_PATHPING:
{
if (PhGetIntegerSetting(L"EnableNetworkResolve"))
{
command = PhFormatString(
L"%s\\system32\\pathping.exe %s",
USER_SHARED_DATA->NtSystemRoot,
context->IpAddressString
);
}
else
{
// Disable hostname lookup.
command = PhFormatString(
L"%s\\system32\\pathping.exe -n %s",
USER_SHARED_DATA->NtSystemRoot,
context->IpAddressString
);
}
}
break;
}
// Allow the write handle to be inherited.
flagInfo.Inherit = TRUE;
flagInfo.ProtectFromClose = FALSE;
NtSetInformationObject(
pipeWriteHandle,
ObjectHandleFlagInformation,
&flagInfo,
sizeof(OBJECT_HANDLE_FLAG_INFORMATION)
);
PhCreateProcessWin32Ex(
NULL,
command->Buffer,
NULL,
NULL,
&startupInfo,
PH_CREATE_PROCESS_INHERIT_HANDLES,
NULL,
NULL,
&context->ProcessHandle,
NULL
);
// Essential; when the process exits, the last instance of the pipe will be disconnected and our thread will exit.
NtClose(pipeWriteHandle);
// Create a thread which will wait for output and display it.
if (threadHandle = PhCreateThread(0, StdOutNetworkTracertThreadStart, context))
NtClose(threadHandle);
}
return STATUS_SUCCESS;
}

View File

@@ -0,0 +1,216 @@
/*
* Process Hacker Network Tools -
* Whois dialog
*
* Copyright (C) 2013 dmex
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nettools.h"
#include <mxml.h>
#include <winhttp.h>
BOOLEAN ReadRequestString(
_In_ HINTERNET Handle,
_Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
_Out_ ULONG *DataLength
)
{
PSTR data;
ULONG allocatedLength;
ULONG dataLength;
ULONG returnLength;
BYTE buffer[PAGE_SIZE];
allocatedLength = sizeof(buffer);
data = (PSTR)PhAllocate(allocatedLength);
dataLength = 0;
// Zero the buffer
memset(buffer, 0, PAGE_SIZE);
while (WinHttpReadData(Handle, buffer, PAGE_SIZE, &returnLength))
{
if (returnLength == 0)
break;
if (allocatedLength < dataLength + returnLength)
{
allocatedLength *= 2;
data = (PSTR)PhReAllocate(data, allocatedLength);
}
// Copy the returned buffer into our pointer
memcpy(data + dataLength, buffer, returnLength);
// Zero the returned buffer for the next loop
//memset(buffer, 0, returnLength);
dataLength += returnLength;
}
if (allocatedLength < dataLength + 1)
{
allocatedLength++;
data = (PSTR)PhReAllocate(data, allocatedLength);
}
// Ensure that the buffer is null-terminated.
data[dataLength] = 0;
*DataLength = dataLength;
*Data = data;
return TRUE;
}
NTSTATUS NetworkWhoisThreadStart(
_In_ PVOID Parameter
)
{
BOOLEAN isSuccess = FALSE;
ULONG xmlLength = 0;
PSTR xmlBuffer = NULL;
PPH_STRING phVersion = NULL;
PPH_STRING userAgent = NULL;
PPH_STRING whoisHttpGetString = NULL;
HINTERNET connectionHandle = NULL;
HINTERNET requestHandle = NULL;
HINTERNET sessionHandle = NULL;
PNETWORK_OUTPUT_CONTEXT context = NULL;
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
//4.4.3. IP Addresses and Networks
// https://www.arin.net/resources/whoisrws/whois_api.html
//TODO: use REF string from /rest/ip/ lookup for querying the IP network: "/rest/net/NET-74-125-0-0-1?showDetails=true"
// or use CIDR string from /rest/ip/ lookup for querying the IP network: "/rest/cidr/216.34.181.0/24?showDetails=true
//WinHttpAddRequestHeaders(requestHandle, L"application/arin.whoisrws-v1+xml", -1L, 0);
__try
{
// Query thread context.
if ((context = (PNETWORK_OUTPUT_CONTEXT)Parameter) == NULL)
__leave;
// Query PH version.
if ((phVersion = PhGetPhVersion()) == NULL)
__leave;
// Create a user agent string.
if ((userAgent = PhConcatStrings2(L"Process Hacker ", phVersion->Buffer)) == NULL)
__leave;
// Query the current system proxy
WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
// Open the HTTP session with the system proxy configuration if available
if (!(sessionHandle = WinHttpOpen(
userAgent->Buffer,
proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
proxyConfig.lpszProxy,
proxyConfig.lpszProxyBypass,
0
)))
{
__leave;
}
if (WindowsVersion >= WINDOWS_8_1)
{
// Enable GZIP and DEFLATE support on Windows 8.1 and above using undocumented flags.
ULONG httpFlags = WINHTTP_DECOMPRESSION_FLAG_GZIP | WINHTTP_DECOMPRESSION_FLAG_DEFLATE;
WinHttpSetOption(
sessionHandle,
WINHTTP_OPTION_DECOMPRESSION,
&httpFlags,
sizeof(ULONG)
);
}
if (!(connectionHandle = WinHttpConnect(
sessionHandle,
L"whois.arin.net",
INTERNET_DEFAULT_HTTP_PORT,
0
)))
{
__leave;
}
if (!(whoisHttpGetString = PhFormatString(L"/rest/ip/%s", context->IpAddressString)))
__leave;
if (!(requestHandle = WinHttpOpenRequest(
connectionHandle,
NULL,
whoisHttpGetString->Buffer,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_REFRESH
)))
{
__leave;
}
if (!WinHttpAddRequestHeaders(requestHandle, L"Accept: text/plain", -1L, 0))
__leave;
if (!WinHttpSendRequest(
requestHandle,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0
))
{
__leave;
}
if (!WinHttpReceiveResponse(requestHandle, NULL))
__leave;
if (!ReadRequestString(requestHandle, &xmlBuffer, &xmlLength))
__leave;
PostMessage(context->WindowHandle, NTM_RECEIVEDWHOIS, (WPARAM)xmlLength, (LPARAM)xmlBuffer);
PostMessage(context->WindowHandle, NTM_RECEIVEDFINISH, 0, 0);
isSuccess = TRUE;
}
__finally
{
if (phVersion)
PhDereferenceObject(phVersion);
if (userAgent)
PhDereferenceObject(userAgent);
if (whoisHttpGetString)
PhDereferenceObject(whoisHttpGetString);
if (requestHandle)
WinHttpCloseHandle(requestHandle);
if (connectionHandle)
WinHttpCloseHandle(connectionHandle);
if (sessionHandle)
WinHttpCloseHandle(sessionHandle);
}
return STATUS_SUCCESS;
}