diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
index 0220038e2..7e8604121 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj
@@ -266,6 +266,7 @@
+
diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
index 1c1a9dc8a..608ee980b 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcxproj.filters
@@ -441,6 +441,9 @@
Process Hacker
+
+ Process Hacker
+
diff --git a/2.x/trunk/ProcessHacker/include/phapp.h b/2.x/trunk/ProcessHacker/include/phapp.h
index d066750bc..6cc77c069 100644
--- a/2.x/trunk/ProcessHacker/include/phapp.h
+++ b/2.x/trunk/ProcessHacker/include/phapp.h
@@ -26,7 +26,6 @@
extern PPH_STRING PhApplicationDirectory;
extern PPH_STRING PhApplicationFileName;
extern HFONT PhApplicationFont;
-extern HFONT PhBoldListViewFont;
extern HFONT PhBoldMessageFont;
extern PPH_STRING PhCurrentUserName;
extern HFONT PhIconTitleFont;
@@ -470,6 +469,10 @@ VOID PhShowServiceContextMenu(
__in POINT Location
);
+VOID PhShowNetworkContextMenu(
+ __in POINT Location
+ );
+
// plugins
#ifndef PLUGINS_PRIVATE
diff --git a/2.x/trunk/ProcessHacker/include/phplug.h b/2.x/trunk/ProcessHacker/include/phplug.h
index d25af93f2..22ef94f99 100644
--- a/2.x/trunk/ProcessHacker/include/phplug.h
+++ b/2.x/trunk/ProcessHacker/include/phplug.h
@@ -28,7 +28,8 @@ typedef enum _PH_GENERAL_CALLBACK
GeneralCallbackHandleMenuInitializing = 16, // PPH_PLUGIN_MENU_INFORMATION Data [properties thread]
GeneralCallbackProcessTreeNewInitializing = 17, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
GeneralCallbackServiceTreeNewInitializing = 18, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
- GeneralCallbackModuleTreeNewInitializing = 19, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
+ GeneralCallbackNetworkTreeNewInitializing = 19, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
+ GeneralCallbackModuleTreeNewInitializing = 20, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackMaximum
} PH_GENERAL_CALLBACK, *PPH_GENERAL_CALLBACK;
diff --git a/2.x/trunk/ProcessHacker/include/providers.h b/2.x/trunk/ProcessHacker/include/providers.h
index 715e08c42..7e5b56b47 100644
--- a/2.x/trunk/ProcessHacker/include/providers.h
+++ b/2.x/trunk/ProcessHacker/include/providers.h
@@ -402,10 +402,10 @@ VOID PhServiceProviderUpdate(
#ifndef PH_NETPRV_PRIVATE
extern PPH_OBJECT_TYPE PhNetworkItemType;
-extern PH_CALLBACK PhNetworkItemAddedEvent;
-extern PH_CALLBACK PhNetworkItemModifiedEvent;
-extern PH_CALLBACK PhNetworkItemRemovedEvent;
-extern PH_CALLBACK PhNetworkItemsUpdatedEvent;
+PHAPPAPI extern PH_CALLBACK PhNetworkItemAddedEvent;
+PHAPPAPI extern PH_CALLBACK PhNetworkItemModifiedEvent;
+PHAPPAPI extern PH_CALLBACK PhNetworkItemRemovedEvent;
+PHAPPAPI extern PH_CALLBACK PhNetworkItemsUpdatedEvent;
extern BOOLEAN PhEnableNetworkProviderResolve;
#endif
diff --git a/2.x/trunk/ProcessHacker/include/uimodels.h b/2.x/trunk/ProcessHacker/include/uimodels.h
index 9e4e71178..a31a885c1 100644
--- a/2.x/trunk/ProcessHacker/include/uimodels.h
+++ b/2.x/trunk/ProcessHacker/include/uimodels.h
@@ -432,6 +432,86 @@ VOID PhWriteServiceList(
__in ULONG Mode
);
+// netlist
+
+// Columns
+
+#define PHNETLC_PROCESS 0
+#define PHNETLC_LOCALADDRESS 1
+#define PHNETLC_LOCALPORT 2
+#define PHNETLC_REMOTEADDRESS 3
+#define PHNETLC_REMOTEPORT 4
+#define PHNETLC_PROTOCOL 5
+#define PHNETLC_STATE 6
+#define PHNETLC_OWNER 7
+#define PHNETLC_MAXIMUM 8
+
+typedef struct _PH_NETWORK_NODE
+{
+ PH_TREENEW_NODE Node;
+
+ PH_SH_STATE ShState;
+
+ PPH_NETWORK_ITEM NetworkItem;
+
+ PH_STRINGREF TextCache[PHNETLC_MAXIMUM];
+
+ PPH_STRING ProcessNameText;
+ PH_STRINGREF LocalAddressText;
+ PH_STRINGREF RemoteAddressText;
+
+ PPH_STRING TooltipText;
+} PH_NETWORK_NODE, *PPH_NETWORK_NODE;
+
+VOID PhNetworkTreeListInitialization();
+
+VOID PhInitializeNetworkTreeList(
+ __in HWND hwnd
+ );
+
+VOID PhLoadSettingsNetworkTreeList();
+
+VOID PhSaveSettingsNetworkTreeList();
+
+PPH_NETWORK_NODE PhAddNetworkNode(
+ __in PPH_NETWORK_ITEM NetworkItem,
+ __in ULONG RunId
+ );
+
+PPH_NETWORK_NODE PhFindNetworkNode(
+ __in PPH_NETWORK_ITEM NetworkItem
+ );
+
+VOID PhRemoveNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ );
+
+VOID PhUpdateNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ );
+
+VOID PhTickNetworkNodes();
+
+PPH_NETWORK_ITEM PhGetSelectedNetworkItem();
+
+VOID PhGetSelectedNetworkItems(
+ __out PPH_NETWORK_ITEM **NetworkItems,
+ __out PULONG NumberOfNetworkItems
+ );
+
+VOID PhDeselectAllNetworkNodes();
+
+VOID PhSelectAndEnsureVisibleNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ );
+
+VOID PhCopyNetworkList();
+
+VOID PhWriteNetworkList(
+ __inout PPH_FILE_STREAM FileStream,
+ __in ULONG Mode
+ );
+
// modlist
// Columns
diff --git a/2.x/trunk/ProcessHacker/main.c b/2.x/trunk/ProcessHacker/main.c
index 03e75d895..5347acf64 100644
--- a/2.x/trunk/ProcessHacker/main.c
+++ b/2.x/trunk/ProcessHacker/main.c
@@ -47,7 +47,6 @@ VOID PhpEnablePrivileges();
PPH_STRING PhApplicationDirectory;
PPH_STRING PhApplicationFileName;
PHAPPAPI HFONT PhApplicationFont;
-HFONT PhBoldListViewFont;
HFONT PhBoldMessageFont;
PPH_STRING PhCurrentUserName = NULL;
HFONT PhIconTitleFont;
diff --git a/2.x/trunk/ProcessHacker/mainwnd.c b/2.x/trunk/ProcessHacker/mainwnd.c
index 12fc97dfb..e358990ec 100644
--- a/2.x/trunk/ProcessHacker/mainwnd.c
+++ b/2.x/trunk/ProcessHacker/mainwnd.c
@@ -73,14 +73,6 @@ VOID PhMainWndTabControlOnNotify(
VOID PhMainWndTabControlOnSelectionChanged();
-VOID PhMainWndNetworkListViewOnNotify(
- __in LPNMHDR Header
- );
-
-VOID PhMainWndNetworkListViewOnContextMenu(
- __in LPARAM lParam
- );
-
VOID PhReloadSysParameters();
VOID PhpInitialLoadSettings();
@@ -154,20 +146,6 @@ VOID PhpGetSelectedProcesses(
__out PULONG NumberOfProcesses
);
-PPH_SERVICE_ITEM PhpGetSelectedService();
-
-VOID PhpGetSelectedServices(
- __out PPH_SERVICE_ITEM **Services,
- __out PULONG NumberOfServices
- );
-
-PPH_NETWORK_ITEM PhpGetSelectedNetworkItem();
-
-VOID PhpGetSelectedNetworkItems(
- __out PPH_NETWORK_ITEM **NetworkItems,
- __out PULONG NumberOfNetworkItems
- );
-
VOID PhpShowProcessProperties(
__in PPH_PROCESS_ITEM ProcessItem
);
@@ -212,7 +190,7 @@ VOID PhMainWndOnServicesUpdated();
VOID PhMainWndOnNetworkItemAdded(
__in ULONG RunId,
- __in PPH_NETWORK_ITEM NetworkItem
+ __in __assumeRefs(1) PPH_NETWORK_ITEM NetworkItem
);
VOID PhMainWndOnNetworkItemModified(
@@ -244,11 +222,12 @@ static INT MaxTabIndex;
static PPH_LIST AdditionalTabPageList = NULL;
static HWND ProcessTreeListHandle;
static HWND ServiceTreeListHandle;
-static HWND NetworkListViewHandle;
+static HWND NetworkTreeListHandle;
static HFONT CurrentCustomFont;
static BOOLEAN NetworkFirstTime = TRUE;
static BOOLEAN ServiceTreeListLoaded = FALSE;
+static BOOLEAN NetworkTreeListLoaded = FALSE;
static BOOLEAN UpdateAutomatically = TRUE;
static PH_CALLBACK_REGISTRATION SymInitRegistration;
@@ -275,8 +254,6 @@ static PH_CALLBACK_REGISTRATION NetworkItemModifiedRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemRemovedRegistration;
static PH_CALLBACK_REGISTRATION NetworkItemsUpdatedRegistration;
static BOOLEAN NetworkNeedsRedraw = FALSE;
-static BOOLEAN NetworkNeedsSort = FALSE;
-static PH_IMAGE_LIST_WRAPPER NetworkImageListWrapper;
static PPH_PLUGIN_MENU_ITEM SelectedMenuItemPlugin;
static ULONG SelectedRunAsMode;
@@ -639,7 +616,7 @@ LRESULT CALLBACK PhMainWndProc(
else if (selectedTab == ServicesTabIndex)
PhWriteServiceList(fileStream, mode);
else if (selectedTab == NetworkTabIndex)
- lines = PhGetListViewLines(NetworkListViewHandle, mode);
+ lines = PhGetListViewLines(NetworkTreeListHandle, mode);
if (lines)
{
@@ -1382,7 +1359,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_GOTOPROCESS:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
PPH_PROCESS_NODE processNode;
if (serviceItem)
@@ -1398,7 +1375,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_START:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1410,7 +1387,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_CONTINUE:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1422,7 +1399,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_PAUSE:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1434,7 +1411,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_STOP:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1446,7 +1423,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_DELETE:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1461,7 +1438,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_SERVICE_PROPERTIES:
{
- PPH_SERVICE_ITEM serviceItem = PhpGetSelectedService();
+ PPH_SERVICE_ITEM serviceItem = PhGetSelectedServiceItem();
if (serviceItem)
{
@@ -1480,7 +1457,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_NETWORK_GOTOPROCESS:
{
- PPH_NETWORK_ITEM networkItem = PhpGetSelectedNetworkItem();
+ PPH_NETWORK_ITEM networkItem = PhGetSelectedNetworkItem();
PPH_PROCESS_NODE processNode;
if (networkItem)
@@ -1496,7 +1473,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_NETWORK_VIEWSTACK:
{
- PPH_NETWORK_ITEM networkItem = PhpGetSelectedNetworkItem();
+ PPH_NETWORK_ITEM networkItem = PhGetSelectedNetworkItem();
if (networkItem)
{
@@ -1511,11 +1488,11 @@ LRESULT CALLBACK PhMainWndProc(
PPH_NETWORK_ITEM *networkItems;
ULONG numberOfNetworkItems;
- PhpGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
+ PhGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
PhReferenceObjects(networkItems, numberOfNetworkItems);
if (PhUiCloseConnections(hWnd, networkItems, numberOfNetworkItems))
- PhSetStateAllListViewItems(NetworkListViewHandle, 0, LVIS_SELECTED);
+ PhSetStateAllListViewItems(NetworkTreeListHandle, 0, LVIS_SELECTED);
PhDereferenceObjects(networkItems, numberOfNetworkItems);
PhFree(networkItems);
@@ -1523,7 +1500,7 @@ LRESULT CALLBACK PhMainWndProc(
break;
case ID_NETWORK_COPY:
{
- PhCopyListView(NetworkListViewHandle);
+ PhCopyListView(NetworkTreeListHandle);
}
break;
case ID_TAB_NEXT:
@@ -1673,7 +1650,7 @@ LRESULT CALLBACK PhMainWndProc(
else if (selectedIndex == ServicesTabIndex)
SetFocus(ServiceTreeListHandle);
else if (selectedIndex == NetworkTabIndex)
- SetFocus(NetworkListViewHandle);
+ SetFocus(NetworkTreeListHandle);
}
break;
case WM_NOTIFY:
@@ -1684,10 +1661,6 @@ LRESULT CALLBACK PhMainWndProc(
{
PhMainWndTabControlOnNotify(header);
}
- else if (header->hwndFrom == NetworkListViewHandle)
- {
- PhMainWndNetworkListViewOnNotify(header);
- }
else if (header->code == RFN_VALIDATE)
{
LPNMRUNFILEDLG runFileDlg = (LPNMRUNFILEDLG)header;
@@ -1752,14 +1725,6 @@ LRESULT CALLBACK PhMainWndProc(
}
}
break;
- case WM_CONTEXTMENU:
- {
- if ((HWND)wParam == NetworkListViewHandle)
- {
- PhMainWndNetworkListViewOnContextMenu(lParam);
- }
- }
- break;
case WM_WTSSESSION_CHANGE:
{
if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_LOGOFF)
@@ -1906,7 +1871,7 @@ LRESULT CALLBACK PhMainWndProc(
else if (index == ServicesTabIndex)
SetFocus(ServiceTreeListHandle);
else if (index == NetworkTabIndex)
- SetFocus(NetworkListViewHandle);
+ SetFocus(NetworkTreeListHandle);
}
break;
case WM_PH_GET_LAYOUT_PADDING:
@@ -1945,12 +1910,12 @@ LRESULT CALLBACK PhMainWndProc(
{
INT lvItemIndex;
- PhSetStateAllListViewItems(NetworkListViewHandle, 0, LVIS_SELECTED);
- lvItemIndex = PhFindListViewItemByParam(NetworkListViewHandle, -1, (PVOID)lParam);
+ PhSetStateAllListViewItems(NetworkTreeListHandle, 0, LVIS_SELECTED);
+ lvItemIndex = PhFindListViewItemByParam(NetworkTreeListHandle, -1, (PVOID)lParam);
if (lvItemIndex != -1)
{
- ListView_SetItemState(NetworkListViewHandle, lvItemIndex,
+ ListView_SetItemState(NetworkTreeListHandle, lvItemIndex,
LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
}
}
@@ -1980,7 +1945,7 @@ LRESULT CALLBACK PhMainWndProc(
SendMessage(ProcessTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
SendMessage(ServiceTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
- SendMessage(NetworkListViewHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
+ SendMessage(NetworkTreeListHandle, WM_SETFONT, (WPARAM)newFont, TRUE);
}
}
@@ -2072,7 +2037,6 @@ LRESULT CALLBACK PhMainWndProc(
PPH_NETWORK_ITEM networkItem = (PPH_NETWORK_ITEM)lParam;
PhMainWndOnNetworkItemAdded(runId, networkItem);
- PhDereferenceObject(networkItem);
}
break;
case WM_PH_NETWORK_ITEM_MODIFIED:
@@ -2092,34 +2056,11 @@ LRESULT CALLBACK PhMainWndProc(
break;
}
- REFLECT_MESSAGE(NetworkListViewHandle, uMsg, wParam, lParam);
+ REFLECT_MESSAGE(NetworkTreeListHandle, uMsg, wParam, lParam);
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
-VOID PhpReloadListViewFont()
-{
- HFONT fontHandle;
- LOGFONT font;
-
- if (NetworkListViewHandle && (fontHandle = (HFONT)SendMessage(NetworkListViewHandle, WM_GETFONT, 0, 0)))
- {
- if (GetObject(fontHandle, sizeof(LOGFONT), &font))
- {
- font.lfWeight = FW_BOLD;
- fontHandle = CreateFontIndirect(&font);
-
- if (fontHandle)
- {
- if (PhBoldListViewFont)
- DeleteObject(PhBoldListViewFont);
-
- PhBoldListViewFont = fontHandle;
- }
- }
- }
-}
-
VOID PhReloadSysParameters()
{
PhSysWindowColor = GetSysColor(COLOR_WINDOW);
@@ -2130,8 +2071,6 @@ VOID PhReloadSysParameters()
DeleteObject(PhBoldMessageFont);
PhInitializeFont(PhMainWndHandle);
SendMessage(TabControlHandle, WM_SETFONT, (WPARAM)PhApplicationFont, FALSE);
-
- PhpReloadListViewFont();
}
VOID PhpInitialLoadSettings()
@@ -2245,8 +2184,7 @@ VOID PhpInitialLoadSettings()
PhDereferenceObject(customFont);
PhLoadSettingsProcessTreeList();
- // Service list settings are loaded on demand.
- PhLoadListViewColumnsFromSetting(L"NetworkListViewColumns", NetworkListViewHandle);
+ // Service and network list settings are loaded on demand.
}
VOID PhMainSymInitHandler(
@@ -2336,7 +2274,8 @@ VOID PhpSaveAllSettings()
PhSaveSettingsProcessTreeList();
if (ServiceTreeListLoaded)
PhSaveSettingsServiceTreeList();
- PhSaveListViewColumnsToSetting(L"NetworkListViewColumns", NetworkListViewHandle);
+ if (NetworkTreeListLoaded)
+ PhSaveSettingsNetworkTreeList();
PhSetIntegerSetting(L"IconMask", NotifyIconMask);
PhSetIntegerSetting(L"IconNotifyMask", NotifyIconNotifyMask);
@@ -2435,6 +2374,16 @@ VOID PhpNeedServiceTreeList()
}
}
+VOID PhpNeedNetworkTreeList()
+{
+ if (!NetworkTreeListLoaded)
+ {
+ NetworkTreeListLoaded = TRUE;
+
+ PhLoadSettingsNetworkTreeList();
+ }
+}
+
BOOLEAN PhpProcessComputerCommand(
__in ULONG Id
)
@@ -3037,38 +2986,6 @@ VOID PhpShowProcessProperties(
}
}
-PPH_SERVICE_ITEM PhpGetSelectedService()
-{
- return PhGetSelectedServiceItem();
-}
-
-VOID PhpGetSelectedServices(
- __out PPH_SERVICE_ITEM **Services,
- __out PULONG NumberOfServices
- )
-{
- PhGetSelectedServiceItems(Services, NumberOfServices);
-}
-
-PPH_NETWORK_ITEM PhpGetSelectedNetworkItem()
-{
- return PhGetSelectedListViewItemParam(
- NetworkListViewHandle
- );
-}
-
-VOID PhpGetSelectedNetworkItems(
- __out PPH_NETWORK_ITEM **NetworkItems,
- __out PULONG NumberOfNetworkItems
- )
-{
- PhGetSelectedListViewItemParams(
- NetworkListViewHandle,
- NetworkItems,
- NumberOfNetworkItems
- );
-}
-
static VOID NTAPI ProcessAddedHandler(
__in_opt PVOID Parameter,
__in_opt PVOID Context
@@ -3280,24 +3197,20 @@ VOID PhMainWndOnCreate()
);
BringWindowToTop(ServiceTreeListHandle);
- NetworkListViewHandle = PhCreateListViewControl(PhMainWndHandle, ID_MAINWND_NETWORKLV);
- PhSetListViewStyle(NetworkListViewHandle, TRUE, TRUE);
- SendMessage(ListView_GetToolTips(NetworkListViewHandle), TTM_SETDELAYTIME, TTDT_AUTOPOP, 0x7fff);
- BringWindowToTop(NetworkListViewHandle);
- PhpReloadListViewFont();
-
- PhSetControlTheme(NetworkListViewHandle, L"explorer");
-
- PhAddListViewColumn(NetworkListViewHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Process");
- PhAddListViewColumn(NetworkListViewHandle, 1, 1, 1, LVCFMT_LEFT, 120, L"Local Address");
- PhAddListViewColumn(NetworkListViewHandle, 2, 2, 2, LVCFMT_RIGHT, 50, L"Local Port");
- PhAddListViewColumn(NetworkListViewHandle, 3, 3, 3, LVCFMT_LEFT, 120, L"Remote Address");
- PhAddListViewColumn(NetworkListViewHandle, 4, 4, 4, LVCFMT_RIGHT, 50, L"Remote Port");
- PhAddListViewColumn(NetworkListViewHandle, 5, 5, 5, LVCFMT_LEFT, 45, L"Protocol");
- PhAddListViewColumn(NetworkListViewHandle, 6, 6, 6, LVCFMT_LEFT, 70, L"State");
-
- if (WINDOWS_HAS_SERVICE_TAGS)
- PhAddListViewColumn(NetworkListViewHandle, 7, 7, 7, LVCFMT_LEFT, 80, L"Owner");
+ NetworkTreeListHandle = CreateWindow(
+ PH_TREENEW_CLASSNAME,
+ L"",
+ WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_BORDER | TN_STYLE_ICONS | TN_STYLE_DOUBLE_BUFFERED,
+ 0,
+ 0,
+ 3,
+ 3,
+ PhMainWndHandle,
+ (HMENU)ID_MAINWND_NETWORKTL,
+ PhLibImageBase,
+ NULL
+ );
+ BringWindowToTop(NetworkTreeListHandle);
PhProcessTreeListInitialization();
PhInitializeProcessTreeList(ProcessTreeListHandle);
@@ -3305,8 +3218,8 @@ VOID PhMainWndOnCreate()
PhServiceTreeListInitialization();
PhInitializeServiceTreeList(ServiceTreeListHandle);
- PhSetExtendedListViewWithSettings(NetworkListViewHandle);
- ExtendedListView_SetStateHighlighting(NetworkListViewHandle, TRUE);
+ PhNetworkTreeListInitialization();
+ PhInitializeNetworkTreeList(NetworkTreeListHandle);
PhRegisterCallback(
&PhProcessAddedEvent,
@@ -3579,7 +3492,7 @@ VOID PhMainWndTabControlOnLayout(
}
else if (selectedIndex == NetworkTabIndex)
{
- *deferHandle = DeferWindowPos(*deferHandle, NetworkListViewHandle, NULL,
+ *deferHandle = DeferWindowPos(*deferHandle, NetworkTreeListHandle, NULL,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
@@ -3641,6 +3554,8 @@ VOID PhMainWndTabControlOnSelectionChanged()
if (selectedIndex == NetworkTabIndex)
{
+ PhpNeedNetworkTreeList();
+
PhSetEnabledProvider(&NetworkProviderRegistration, UpdateAutomatically);
if (UpdateAutomatically || NetworkFirstTime)
@@ -3656,7 +3571,7 @@ VOID PhMainWndTabControlOnSelectionChanged()
ShowWindow(ProcessTreeListHandle, selectedIndex == ProcessesTabIndex ? SW_SHOW : SW_HIDE);
ShowWindow(ServiceTreeListHandle, selectedIndex == ServicesTabIndex ? SW_SHOW : SW_HIDE);
- ShowWindow(NetworkListViewHandle, selectedIndex == NetworkTabIndex ? SW_SHOW : SW_HIDE);
+ ShowWindow(NetworkTreeListHandle, selectedIndex == NetworkTabIndex ? SW_SHOW : SW_HIDE);
// Additional tabs
@@ -4124,7 +4039,7 @@ VOID PhShowServiceContextMenu(
PPH_SERVICE_ITEM *services;
ULONG numberOfServices;
- PhpGetSelectedServices(&services, &numberOfServices);
+ PhGetSelectedServiceItems(&services, &numberOfServices);
if (numberOfServices != 0)
{
@@ -4228,75 +4143,14 @@ VOID PhpInitializeNetworkMenu(
}
}
-VOID PhMainWndNetworkListViewOnNotify(
- __in LPNMHDR Header
+VOID PhShowNetworkContextMenu(
+ __in POINT Location
)
{
- switch (Header->code)
- {
- case NM_DBLCLK:
- {
- SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_GOTOPROCESS, 0);
- }
- break;
- case LVN_KEYDOWN:
- {
- LPNMLVKEYDOWN keyDown = (LPNMLVKEYDOWN)Header;
-
- switch (keyDown->wVKey)
- {
- case 'C':
- if (GetKeyState(VK_CONTROL) < 0)
- SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_COPY, 0);
- break;
- case VK_RETURN:
- SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_GOTOPROCESS, 0);
- break;
- }
- }
- break;
- case LVN_GETINFOTIP:
- {
- LPNMLVGETINFOTIP getInfoTip = (LPNMLVGETINFOTIP)Header;
- PPH_NETWORK_ITEM networkItem;
-
- if (getInfoTip->iSubItem == 0 && PhGetListViewItemParam(
- NetworkListViewHandle,
- getInfoTip->iItem,
- &networkItem
- ))
- {
- PPH_PROCESS_ITEM processItem;
- PPH_STRING tip;
-
- if (processItem = PhReferenceProcessItem(networkItem->ProcessId))
- {
- tip = PhGetProcessTooltipText(processItem);
- PhCopyListViewInfoTip(getInfoTip, &tip->sr);
- PhDereferenceObject(tip);
- PhDereferenceObject(processItem);
- }
- }
- }
- break;
- }
-}
-
-VOID PhMainWndNetworkListViewOnContextMenu(
- __in LPARAM lParam
- )
-{
- POINT point;
PPH_NETWORK_ITEM *networkItems;
ULONG numberOfNetworkItems;
- point.x = (SHORT)LOWORD(lParam);
- point.y = (SHORT)HIWORD(lParam);
-
- if (point.x == -1 && point.y == -1)
- PhGetListViewContextMenuPoint(NetworkListViewHandle, &point);
-
- PhpGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
+ PhGetSelectedNetworkItems(&networkItems, &numberOfNetworkItems);
if (numberOfNetworkItems != 0)
{
@@ -4326,8 +4180,8 @@ VOID PhMainWndNetworkListViewOnContextMenu(
PhMainWndHandle,
PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP,
- point.x,
- point.y
+ Location.x,
+ Location.y
);
if (item)
@@ -4661,189 +4515,50 @@ VOID PhMainWndOnServicesUpdated()
}
}
-PWSTR PhpGetNetworkItemProcessName(
- __in PPH_NETWORK_ITEM NetworkItem
- )
-{
- PPH_STRING string;
- PH_FORMAT format[4];
-
- if (!NetworkItem->ProcessId)
- return L"Waiting Connections";
-
- PhInitFormatS(&format[1], L" (");
- PhInitFormatU(&format[2], (ULONG)NetworkItem->ProcessId);
- PhInitFormatC(&format[3], ')');
-
- if (NetworkItem->ProcessName)
- PhInitFormatSR(&format[0], NetworkItem->ProcessName->sr);
- else
- PhInitFormatS(&format[0], L"Unknown Process");
-
- string = PhFormat(format, 4, 96);
- PhaDereferenceObject(string);
-
- return string->Buffer;
-}
-
-VOID PhpSetNetworkItemImageIndex(
- __in INT ItemIndex,
- __in PPH_NETWORK_ITEM NetworkItem
- )
-{
- INT imageIndex;
-
- if (NetworkItem->ProcessIconValid && NetworkItem->ProcessIcon)
- {
- imageIndex = PhImageListWrapperAddIcon(&NetworkImageListWrapper, NetworkItem->ProcessIcon);
- }
- else
- {
- imageIndex = 0;
- }
-
- PhSetListViewItemImageIndex(NetworkListViewHandle, ItemIndex, imageIndex);
-}
-
VOID PhMainWndOnNetworkItemAdded(
__in ULONG RunId,
- __in PPH_NETWORK_ITEM NetworkItem
+ __in __assumeRefs(1) PPH_NETWORK_ITEM NetworkItem
)
{
- INT lvItemIndex;
+ PPH_NETWORK_NODE networkNode;
if (!NetworkNeedsRedraw)
{
- ExtendedListView_SetRedraw(NetworkListViewHandle, FALSE);
+ TreeNew_SetRedraw(NetworkTreeListHandle, FALSE);
NetworkNeedsRedraw = TRUE;
}
- // Add a reference for the pointer being stored in the list view item.
- PhReferenceObject(NetworkItem);
-
- if (RunId == 1) ExtendedListView_SetStateHighlighting(NetworkListViewHandle, FALSE);
- lvItemIndex = PhAddListViewItem(
- NetworkListViewHandle,
- MAXINT,
- PhpGetNetworkItemProcessName(NetworkItem),
- NetworkItem
- );
- if (RunId == 1) ExtendedListView_SetStateHighlighting(NetworkListViewHandle, TRUE);
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 1,
- PhGetStringOrDefault(NetworkItem->LocalHostString, NetworkItem->LocalAddressString));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 2, NetworkItem->LocalPortString);
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 3,
- PhGetStringOrDefault(NetworkItem->RemoteHostString, NetworkItem->RemoteAddressString));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 4, NetworkItem->RemotePortString);
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 5, PhGetProtocolTypeName(NetworkItem->ProtocolType));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 6,
- (NetworkItem->ProtocolType & PH_TCP_PROTOCOL_TYPE) ? PhGetTcpStateName(NetworkItem->State) : NULL);
-
- if (WINDOWS_HAS_SERVICE_TAGS)
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 7, PhGetString(NetworkItem->OwnerName));
-
- if (!NetworkImageListWrapper.Handle)
- {
- HICON icon;
-
- PhGetStockApplicationIcon(&icon, NULL);
- PhInitializeImageListWrapper(&NetworkImageListWrapper, PhSmallIconSize.X, PhSmallIconSize.Y, ILC_COLOR32 | ILC_MASK);
- PhImageListWrapperAddIcon(&NetworkImageListWrapper, icon);
- ListView_SetImageList(NetworkListViewHandle, NetworkImageListWrapper.Handle, LVSIL_SMALL);
- }
-
- PhpSetNetworkItemImageIndex(lvItemIndex, NetworkItem);
-
- NetworkNeedsSort = TRUE;
+ networkNode = PhAddNetworkNode(NetworkItem, RunId);
+ PhDereferenceObject(NetworkItem);
}
VOID PhMainWndOnNetworkItemModified(
__in PPH_NETWORK_ITEM NetworkItem
)
{
- INT lvItemIndex;
- INT imageIndex;
-
- if (!NetworkNeedsRedraw)
- {
- ExtendedListView_SetRedraw(NetworkListViewHandle, FALSE);
- NetworkNeedsRedraw = TRUE;
- }
-
- lvItemIndex = PhFindListViewItemByParam(NetworkListViewHandle, -1, NetworkItem);
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 0,
- PhpGetNetworkItemProcessName(NetworkItem));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 1,
- PhGetStringOrDefault(NetworkItem->LocalHostString, NetworkItem->LocalAddressString));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 3,
- PhGetStringOrDefault(NetworkItem->RemoteHostString, NetworkItem->RemoteAddressString));
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 6,
- (NetworkItem->ProtocolType & PH_TCP_PROTOCOL_TYPE) ? PhGetTcpStateName(NetworkItem->State) : NULL);
-
- if (WINDOWS_HAS_SERVICE_TAGS)
- PhSetListViewSubItem(NetworkListViewHandle, lvItemIndex, 7, PhGetString(NetworkItem->OwnerName));
-
- // Only set a new icon if we didn't have a proper one before.
- if (PhGetListViewItemImageIndex(
- NetworkListViewHandle,
- lvItemIndex,
- &imageIndex
- ) && imageIndex == 0)
- {
- PhpSetNetworkItemImageIndex(lvItemIndex, NetworkItem);
- }
-
- NetworkNeedsSort = TRUE;
+ PhUpdateNetworkNode(PhFindNetworkNode(NetworkItem));
}
VOID PhMainWndOnNetworkItemRemoved(
__in PPH_NETWORK_ITEM NetworkItem
)
{
- INT lvItemIndex;
- INT imageIndex;
-
if (!NetworkNeedsRedraw)
{
- ExtendedListView_SetRedraw(NetworkListViewHandle, FALSE);
+ TreeNew_SetRedraw(NetworkTreeListHandle, FALSE);
NetworkNeedsRedraw = TRUE;
}
- lvItemIndex = PhFindListViewItemByParam(NetworkListViewHandle, -1, NetworkItem);
-
- if (PhGetListViewItemImageIndex(
- NetworkListViewHandle,
- lvItemIndex,
- &imageIndex
- ) && imageIndex != 0)
- {
- PhImageListWrapperRemove(&NetworkImageListWrapper, imageIndex);
- // Set to a generic icon so we don't get random icons popping up due to
- // the delay caused by state highlighting.
- PhSetListViewItemImageIndex(NetworkListViewHandle, lvItemIndex, 0);
- }
-
- PhRemoveListViewItem(
- NetworkListViewHandle,
- lvItemIndex
- );
- // Remove the reference we added in PhMainWndOnNetworkItemAdded.
- PhDereferenceObject(NetworkItem);
+ PhRemoveNetworkNode(PhFindNetworkNode(NetworkItem));
}
VOID PhMainWndOnNetworkItemsUpdated()
{
- ExtendedListView_Tick(NetworkListViewHandle);
-
- if (NetworkNeedsSort)
- {
- ExtendedListView_SortItems(NetworkListViewHandle);
- NetworkNeedsSort = FALSE;
- }
+ PhTickNetworkNodes();
if (NetworkNeedsRedraw)
{
- ExtendedListView_SetRedraw(NetworkListViewHandle, TRUE);
+ TreeNew_SetRedraw(NetworkTreeListHandle, TRUE);
NetworkNeedsRedraw = FALSE;
}
}
diff --git a/2.x/trunk/ProcessHacker/modlist.c b/2.x/trunk/ProcessHacker/modlist.c
index db1a2d4c4..04bb60433 100644
--- a/2.x/trunk/ProcessHacker/modlist.c
+++ b/2.x/trunk/ProcessHacker/modlist.c
@@ -661,7 +661,7 @@ BOOLEAN NTAPI PhpModuleTreeNewCallback(
}
}
- getNodeFont->Font = context->BoldFont ? context->BoldFont : PhBoldListViewFont;
+ getNodeFont->Font = context->BoldFont ? context->BoldFont : NULL;
getNodeFont->Flags = TN_CACHE;
return TRUE;
}
diff --git a/2.x/trunk/ProcessHacker/netlist.c b/2.x/trunk/ProcessHacker/netlist.c
new file mode 100644
index 000000000..41a9d4e94
--- /dev/null
+++ b/2.x/trunk/ProcessHacker/netlist.c
@@ -0,0 +1,742 @@
+/*
+ * Process Hacker -
+ * network list
+ *
+ * Copyright (C) 2011 wj32
+ *
+ * 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 .
+ */
+
+#include
+#include
+#include
+#include
+
+BOOLEAN PhpNetworkNodeHashtableCompareFunction(
+ __in PVOID Entry1,
+ __in PVOID Entry2
+ );
+
+ULONG PhpNetworkNodeHashtableHashFunction(
+ __in PVOID Entry
+ );
+
+VOID PhpRemoveNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ );
+
+LONG PhpNetworkTreeNewPostSortFunction(
+ __in LONG Result,
+ __in PVOID Node1,
+ __in PVOID Node2,
+ __in PH_SORT_ORDER SortOrder
+ );
+
+BOOLEAN NTAPI PhpNetworkTreeNewCallback(
+ __in HWND hwnd,
+ __in PH_TREENEW_MESSAGE Message,
+ __in_opt PVOID Parameter1,
+ __in_opt PVOID Parameter2,
+ __in_opt PVOID Context
+ );
+
+PPH_STRING PhpGetNetworkItemProcessName(
+ __in PPH_NETWORK_ITEM NetworkItem
+ );
+
+VOID PhpUpdateNetworkNodeAddressStrings(
+ __in PPH_NETWORK_NODE NetworkNode
+ );
+
+static HWND NetworkTreeListHandle;
+static ULONG NetworkTreeListSortColumn;
+static PH_SORT_ORDER NetworkTreeListSortOrder;
+static PH_CM_MANAGER NetworkTreeListCm;
+
+static PPH_HASHTABLE NetworkNodeHashtable; // hashtable of all nodes
+static PPH_LIST NetworkNodeList; // list of all nodes
+
+BOOLEAN PhNetworkTreeListStateHighlighting = TRUE;
+static PPH_POINTER_LIST NetworkNodeStateList = NULL; // list of nodes which need to be processed
+
+VOID PhNetworkTreeListInitialization()
+{
+ NetworkNodeHashtable = PhCreateHashtable(
+ sizeof(PPH_NETWORK_NODE),
+ PhpNetworkNodeHashtableCompareFunction,
+ PhpNetworkNodeHashtableHashFunction,
+ 100
+ );
+ NetworkNodeList = PhCreateList(100);
+}
+
+BOOLEAN PhpNetworkNodeHashtableCompareFunction(
+ __in PVOID Entry1,
+ __in PVOID Entry2
+ )
+{
+ PPH_NETWORK_NODE networkNode1 = *(PPH_NETWORK_NODE *)Entry1;
+ PPH_NETWORK_NODE networkNode2 = *(PPH_NETWORK_NODE *)Entry2;
+
+ return networkNode1->NetworkItem == networkNode2->NetworkItem;
+}
+
+ULONG PhpNetworkNodeHashtableHashFunction(
+ __in PVOID Entry
+ )
+{
+#ifdef _M_IX86
+ return PhHashInt32((ULONG)(*(PPH_NETWORK_NODE *)Entry)->NetworkItem);
+#else
+ return PhHashInt64((ULONG64)(*(PPH_NETWORK_NODE *)Entry)->NetworkItem);
+#endif
+}
+
+VOID PhInitializeNetworkTreeList(
+ __in HWND hwnd
+ )
+{
+ PH_PLUGIN_TREENEW_INFORMATION treeNewInfo;
+
+ NetworkTreeListHandle = hwnd;
+ PhSetControlTheme(NetworkTreeListHandle, L"explorer");
+ SendMessage(TreeNew_GetTooltips(NetworkTreeListHandle), TTM_SETMAXTIPWIDTH, 0, MAXSHORT);
+ SendMessage(TreeNew_GetTooltips(NetworkTreeListHandle), TTM_SETDELAYTIME, TTDT_AUTOPOP, 0x7fff);
+
+ TreeNew_SetCallback(hwnd, PhpNetworkTreeNewCallback, NULL);
+
+ TreeNew_SetRedraw(hwnd, FALSE);
+
+ // Default columns
+ PhAddTreeNewColumn(hwnd, PHNETLC_PROCESS, TRUE, L"Name", 100, PH_ALIGN_LEFT, 0, 0);
+ PhAddTreeNewColumn(hwnd, PHNETLC_LOCALADDRESS, TRUE, L"Local Address", 120, PH_ALIGN_LEFT, 1, 0);
+ PhAddTreeNewColumn(hwnd, PHNETLC_LOCALPORT, TRUE, L"Local Port", 50, PH_ALIGN_RIGHT, 2, DT_RIGHT);
+ PhAddTreeNewColumn(hwnd, PHNETLC_REMOTEADDRESS, TRUE, L"Remote Address", 120, PH_ALIGN_LEFT, 3, 0);
+ PhAddTreeNewColumn(hwnd, PHNETLC_REMOTEPORT, TRUE, L"Remote Port", 50, PH_ALIGN_RIGHT, 4, DT_RIGHT);
+ PhAddTreeNewColumn(hwnd, PHNETLC_PROTOCOL, TRUE, L"Protocol", 45, PH_ALIGN_LEFT, 5, 0);
+ PhAddTreeNewColumn(hwnd, PHNETLC_STATE, TRUE, L"State", 70, PH_ALIGN_LEFT, 6, 0);
+ PhAddTreeNewColumn(hwnd, PHNETLC_OWNER, WINDOWS_HAS_SERVICE_TAGS, L"Owner", 80, PH_ALIGN_LEFT, 7, 0);
+
+ TreeNew_SetRedraw(hwnd, TRUE);
+
+ TreeNew_SetSort(hwnd, 0, AscendingSortOrder);
+
+ PhCmInitializeManager(&NetworkTreeListCm, hwnd, PHNETLC_MAXIMUM, PhpNetworkTreeNewPostSortFunction);
+
+ if (PhPluginsEnabled)
+ {
+ treeNewInfo.TreeNewHandle = hwnd;
+ treeNewInfo.CmData = &NetworkTreeListCm;
+ PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackNetworkTreeNewInitializing), &treeNewInfo);
+ }
+}
+
+VOID PhLoadSettingsNetworkTreeList()
+{
+ PPH_STRING settings;
+ PPH_STRING sortSettings;
+
+ settings = PhGetStringSetting(L"NetworkTreeListColumns");
+ sortSettings = PhGetStringSetting(L"NetworkTreeListSort");
+ PhCmLoadSettingsEx(NetworkTreeListHandle, &NetworkTreeListCm, &settings->sr, &sortSettings->sr);
+ PhDereferenceObject(settings);
+ PhDereferenceObject(sortSettings);
+}
+
+VOID PhSaveSettingsNetworkTreeList()
+{
+ PPH_STRING settings;
+ PPH_STRING sortSettings;
+
+ settings = PhCmSaveSettingsEx(NetworkTreeListHandle, &NetworkTreeListCm, &sortSettings);
+ PhSetStringSetting2(L"NetworkTreeListColumns", &settings->sr);
+ PhSetStringSetting2(L"NetworkTreeListSort", &sortSettings->sr);
+ PhDereferenceObject(settings);
+ PhDereferenceObject(sortSettings);
+}
+
+PPH_NETWORK_NODE PhAddNetworkNode(
+ __in PPH_NETWORK_ITEM NetworkItem,
+ __in ULONG RunId
+ )
+{
+ PPH_NETWORK_NODE networkNode;
+
+ networkNode = PhAllocate(sizeof(PH_NETWORK_NODE));
+ memset(networkNode, 0, sizeof(PH_NETWORK_NODE));
+ PhInitializeTreeNewNode(&networkNode->Node);
+
+ if (PhNetworkTreeListStateHighlighting && RunId != 1)
+ {
+ PhChangeShStateTn(
+ &networkNode->Node,
+ &networkNode->ShState,
+ &NetworkNodeStateList,
+ NewItemState,
+ PhCsColorNew,
+ NULL
+ );
+ }
+
+ networkNode->NetworkItem = NetworkItem;
+ PhReferenceObject(NetworkItem);
+
+ memset(networkNode->TextCache, 0, sizeof(PH_STRINGREF) * PHNETLC_MAXIMUM);
+ networkNode->Node.TextCache = networkNode->TextCache;
+ networkNode->Node.TextCacheSize = PHNETLC_MAXIMUM;
+
+ networkNode->ProcessNameText = PhpGetNetworkItemProcessName(NetworkItem);
+ PhpUpdateNetworkNodeAddressStrings(networkNode);
+
+ PhAddEntryHashtable(NetworkNodeHashtable, &networkNode);
+ PhAddItemList(NetworkNodeList, networkNode);
+
+ TreeNew_NodesStructured(NetworkTreeListHandle);
+
+ return networkNode;
+}
+
+PPH_NETWORK_NODE PhFindNetworkNode(
+ __in PPH_NETWORK_ITEM NetworkItem
+ )
+{
+ PH_NETWORK_NODE lookupNetworkNode;
+ PPH_NETWORK_NODE lookupNetworkNodePtr = &lookupNetworkNode;
+ PPH_NETWORK_NODE *networkNode;
+
+ lookupNetworkNode.NetworkItem = NetworkItem;
+
+ networkNode = (PPH_NETWORK_NODE *)PhFindEntryHashtable(
+ NetworkNodeHashtable,
+ &lookupNetworkNodePtr
+ );
+
+ if (networkNode)
+ return *networkNode;
+ else
+ return NULL;
+}
+
+VOID PhRemoveNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ )
+{
+ if (PhNetworkTreeListStateHighlighting)
+ {
+ PhChangeShStateTn(
+ &NetworkNode->Node,
+ &NetworkNode->ShState,
+ &NetworkNodeStateList,
+ RemovingItemState,
+ PhCsColorRemoved,
+ NetworkTreeListHandle
+ );
+ }
+ else
+ {
+ PhpRemoveNetworkNode(NetworkNode);
+ }
+}
+
+VOID PhpRemoveNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ )
+{
+ ULONG index;
+
+ // Remove from hashtable/list and cleanup.
+
+ PhRemoveEntryHashtable(NetworkNodeHashtable, &NetworkNode);
+
+ if ((index = PhFindItemList(NetworkNodeList, NetworkNode)) != -1)
+ PhRemoveItemList(NetworkNodeList, index);
+
+ if (NetworkNode->ProcessNameText) PhDereferenceObject(NetworkNode->ProcessNameText);
+ if (NetworkNode->TooltipText) PhDereferenceObject(NetworkNode->TooltipText);
+
+ PhDereferenceObject(NetworkNode->NetworkItem);
+
+ PhFree(NetworkNode);
+
+ TreeNew_NodesStructured(NetworkTreeListHandle);
+}
+
+VOID PhUpdateNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ )
+{
+ memset(NetworkNode->TextCache, 0, sizeof(PH_STRINGREF) * PHNETLC_MAXIMUM);
+ PhpUpdateNetworkNodeAddressStrings(NetworkNode);
+ PhSwapReference(&NetworkNode->TooltipText, NULL);
+
+ PhInvalidateTreeNewNode(&NetworkNode->Node, TN_CACHE_ICON);
+ TreeNew_NodesStructured(NetworkTreeListHandle);
+}
+
+VOID PhTickNetworkNodes()
+{
+ PH_TICK_SH_STATE_TN(PH_NETWORK_NODE, ShState, NetworkNodeStateList, PhpRemoveNetworkNode, PhCsHighlightingDuration, NetworkTreeListHandle, TRUE, NULL);
+}
+
+#define SORT_FUNCTION(Column) PhpNetworkTreeNewCompare##Column
+
+#define BEGIN_SORT_FUNCTION(Column) static int __cdecl PhpNetworkTreeNewCompare##Column( \
+ __in const void *_elem1, \
+ __in const void *_elem2 \
+ ) \
+{ \
+ PPH_NETWORK_NODE node1 = *(PPH_NETWORK_NODE *)_elem1; \
+ PPH_NETWORK_NODE node2 = *(PPH_NETWORK_NODE *)_elem2; \
+ PPH_NETWORK_ITEM networkItem1 = node1->NetworkItem; \
+ PPH_NETWORK_ITEM networkItem2 = node2->NetworkItem; \
+ int sortResult = 0;
+
+#define END_SORT_FUNCTION \
+ /* if (sortResult == 0) */ \
+ /* sortResult = PhCompareString(networkItem1->Name, networkItem2->Name, TRUE); */ \
+ \
+ return PhModifySort(sortResult, NetworkTreeListSortOrder); \
+}
+
+LONG PhpNetworkTreeNewPostSortFunction(
+ __in LONG Result,
+ __in PVOID Node1,
+ __in PVOID Node2,
+ __in PH_SORT_ORDER SortOrder
+ )
+{
+ return PhModifySort(Result, SortOrder);
+}
+
+BEGIN_SORT_FUNCTION(Process)
+{
+ sortResult = PhCompareString(node1->ProcessNameText, node2->ProcessNameText, TRUE);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(LocalAddress)
+{
+ sortResult = PhCompareStringRef(&node1->LocalAddressText, &node2->LocalAddressText, TRUE);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(LocalPort)
+{
+ sortResult = uintcmp(networkItem1->LocalEndpoint.Port, networkItem2->LocalEndpoint.Port);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(RemoteAddress)
+{
+ sortResult = PhCompareStringRef(&node1->RemoteAddressText, &node2->RemoteAddressText, TRUE);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(RemotePort)
+{
+ sortResult = uintcmp(networkItem1->RemoteEndpoint.Port, networkItem2->RemoteEndpoint.Port);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(Protocol)
+{
+ sortResult = uintcmp(networkItem1->ProtocolType, networkItem2->ProtocolType);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(State)
+{
+ sortResult = uintcmp(networkItem1->State, networkItem2->State);
+}
+END_SORT_FUNCTION
+
+BEGIN_SORT_FUNCTION(Owner)
+{
+ sortResult = PhCompareStringWithNull(networkItem1->OwnerName, networkItem2->OwnerName, TRUE);
+}
+END_SORT_FUNCTION
+
+BOOLEAN NTAPI PhpNetworkTreeNewCallback(
+ __in HWND hwnd,
+ __in PH_TREENEW_MESSAGE Message,
+ __in_opt PVOID Parameter1,
+ __in_opt PVOID Parameter2,
+ __in_opt PVOID Context
+ )
+{
+ PPH_NETWORK_NODE node;
+
+ if (PhCmForwardMessage(hwnd, Message, Parameter1, Parameter2, &NetworkTreeListCm))
+ return TRUE;
+
+ switch (Message)
+ {
+ case TreeNewGetChildren:
+ {
+ PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
+
+ if (!getChildren->Node)
+ {
+ static PVOID sortFunctions[] =
+ {
+ SORT_FUNCTION(Process),
+ SORT_FUNCTION(LocalAddress),
+ SORT_FUNCTION(LocalPort),
+ SORT_FUNCTION(RemoteAddress),
+ SORT_FUNCTION(RemotePort),
+ SORT_FUNCTION(Protocol),
+ SORT_FUNCTION(State),
+ SORT_FUNCTION(Owner)
+ };
+ int (__cdecl *sortFunction)(const void *, const void *);
+
+ if (!PhCmForwardSort(
+ (PPH_TREENEW_NODE *)NetworkNodeList->Items,
+ NetworkNodeList->Count,
+ NetworkTreeListSortColumn,
+ NetworkTreeListSortOrder,
+ &NetworkTreeListCm
+ ))
+ {
+ if (NetworkTreeListSortColumn < PHNETLC_MAXIMUM)
+ sortFunction = sortFunctions[NetworkTreeListSortColumn];
+ else
+ sortFunction = NULL;
+
+ if (sortFunction)
+ {
+ qsort(NetworkNodeList->Items, NetworkNodeList->Count, sizeof(PVOID), sortFunction);
+ }
+ }
+
+ getChildren->Children = (PPH_TREENEW_NODE *)NetworkNodeList->Items;
+ getChildren->NumberOfChildren = NetworkNodeList->Count;
+ }
+ }
+ return TRUE;
+ case TreeNewIsLeaf:
+ {
+ PPH_TREENEW_IS_LEAF isLeaf = Parameter1;
+
+ isLeaf->IsLeaf = TRUE;
+ }
+ return TRUE;
+ case TreeNewGetCellText:
+ {
+ PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
+ PPH_NETWORK_ITEM networkItem;
+
+ node = (PPH_NETWORK_NODE)getCellText->Node;
+ networkItem = node->NetworkItem;
+
+ switch (getCellText->Id)
+ {
+ case PHNETLC_PROCESS:
+ getCellText->Text = node->ProcessNameText->sr;
+ break;
+ case PHNETLC_LOCALADDRESS:
+ getCellText->Text = node->LocalAddressText;
+ break;
+ case PHNETLC_LOCALPORT:
+ PhInitializeStringRef(&getCellText->Text, networkItem->LocalPortString);
+ break;
+ case PHNETLC_REMOTEADDRESS:
+ getCellText->Text = node->RemoteAddressText;
+ break;
+ case PHNETLC_REMOTEPORT:
+ PhInitializeStringRef(&getCellText->Text, networkItem->RemotePortString);
+ break;
+ case PHNETLC_PROTOCOL:
+ PhInitializeStringRef(&getCellText->Text, PhGetProtocolTypeName(networkItem->ProtocolType));
+ break;
+ case PHNETLC_STATE:
+ if (networkItem->ProtocolType & PH_TCP_PROTOCOL_TYPE)
+ PhInitializeStringRef(&getCellText->Text, PhGetTcpStateName(networkItem->State));
+ else
+ PhInitializeEmptyStringRef(&getCellText->Text);
+ break;
+ case PHNETLC_OWNER:
+ if (WINDOWS_HAS_SERVICE_TAGS)
+ getCellText->Text = PhGetStringRef(networkItem->OwnerName);
+ else
+ PhInitializeStringRef(&getCellText->Text, L"N/A"); // make sure the user knows this column doesn't work on XP
+ break;
+ default:
+ return FALSE;
+ }
+
+ getCellText->Flags = TN_CACHE;
+ }
+ return TRUE;
+ case TreeNewGetNodeIcon:
+ {
+ PPH_TREENEW_GET_NODE_ICON getNodeIcon = Parameter1;
+
+ node = (PPH_NETWORK_NODE)getNodeIcon->Node;
+
+ if (node->NetworkItem->ProcessIconValid)
+ {
+ // TODO: Check if the icon handle is actually valid, since the process item
+ // might get destroyed while the network node is still valid.
+ getNodeIcon->Icon = node->NetworkItem->ProcessIcon;
+ }
+ else
+ {
+ PhGetStockApplicationIcon(&getNodeIcon->Icon, NULL);
+ }
+
+ getNodeIcon->Flags = TN_CACHE;
+ }
+ return TRUE;
+ case TreeNewGetCellTooltip:
+ {
+ PPH_TREENEW_GET_CELL_TOOLTIP getCellTooltip = Parameter1;
+ PPH_PROCESS_ITEM processItem;
+
+ node = (PPH_NETWORK_NODE)getCellTooltip->Node;
+
+ if (getCellTooltip->Column->Id != 0)
+ return FALSE;
+
+ if (!node->TooltipText)
+ {
+ if (processItem = PhReferenceProcessItem(node->NetworkItem->ProcessId))
+ {
+ node->TooltipText = PhGetProcessTooltipText(processItem);
+ PhDereferenceObject(processItem);
+ }
+ }
+
+ if (!PhIsNullOrEmptyString(node->TooltipText))
+ {
+ getCellTooltip->Text = node->TooltipText->sr;
+ getCellTooltip->Unfolding = FALSE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ case TreeNewSortChanged:
+ {
+ TreeNew_GetSort(hwnd, &NetworkTreeListSortColumn, &NetworkTreeListSortOrder);
+ // Force a rebuild to sort the items.
+ TreeNew_NodesStructured(hwnd);
+ }
+ return TRUE;
+ case TreeNewKeyDown:
+ {
+ PPH_TREENEW_KEY_EVENT keyEvent = Parameter1;
+
+ switch (keyEvent->VirtualKey)
+ {
+ case 'C':
+ if (GetKeyState(VK_CONTROL) < 0)
+ SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_COPY, 0);
+ break;
+ case VK_RETURN:
+ SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_GOTOPROCESS, 0);
+ break;
+ }
+ }
+ return TRUE;
+ case TreeNewHeaderRightClick:
+ {
+ HMENU menu;
+ HMENU subMenu;
+ POINT point;
+
+ menu = LoadMenu(PhInstanceHandle, MAKEINTRESOURCE(IDR_GENERICHEADER));
+ subMenu = GetSubMenu(menu, 0);
+ GetCursorPos(&point);
+
+ if ((UINT)TrackPopupMenu(
+ subMenu,
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
+ point.x,
+ point.y,
+ 0,
+ hwnd,
+ NULL
+ ) == ID_HEADER_CHOOSECOLUMNS)
+ {
+ PhShowChooseColumnsDialog(hwnd, hwnd, PH_CONTROL_TYPE_TREE_NEW);
+
+ // Make sure the column we're sorting by is actually visible,
+ // and if not, sort by the default column.
+ if (NetworkTreeListSortOrder != NoSortOrder)
+ {
+ PH_TREENEW_COLUMN column;
+
+ TreeNew_GetColumn(NetworkTreeListHandle, NetworkTreeListSortColumn, &column);
+
+ if (!column.Visible)
+ TreeNew_SetSort(NetworkTreeListHandle, 0, AscendingSortOrder);
+ }
+ }
+
+ DestroyMenu(menu);
+ }
+ return TRUE;
+ case TreeNewLeftDoubleClick:
+ {
+ SendMessage(PhMainWndHandle, WM_COMMAND, ID_NETWORK_GOTOPROCESS, 0);
+ }
+ return TRUE;
+ case TreeNewContextMenu:
+ {
+ PPH_TREENEW_MOUSE_EVENT mouseEvent = Parameter1;
+
+ PhShowNetworkContextMenu(mouseEvent->Location);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+PPH_STRING PhpGetNetworkItemProcessName(
+ __in PPH_NETWORK_ITEM NetworkItem
+ )
+{
+ PH_FORMAT format[4];
+
+ if (!NetworkItem->ProcessId)
+ return PhCreateString(L"Waiting Connections");
+
+ PhInitFormatS(&format[1], L" (");
+ PhInitFormatU(&format[2], (ULONG)NetworkItem->ProcessId);
+ PhInitFormatC(&format[3], ')');
+
+ if (NetworkItem->ProcessName)
+ PhInitFormatSR(&format[0], NetworkItem->ProcessName->sr);
+ else
+ PhInitFormatS(&format[0], L"Unknown Process");
+
+ return PhFormat(format, 4, 96);
+}
+
+VOID PhpUpdateNetworkNodeAddressStrings(
+ __in PPH_NETWORK_NODE NetworkNode
+ )
+{
+ if (NetworkNode->NetworkItem->LocalHostString)
+ NetworkNode->LocalAddressText = NetworkNode->NetworkItem->LocalHostString->sr;
+ else
+ PhInitializeStringRef(&NetworkNode->LocalAddressText, NetworkNode->NetworkItem->LocalAddressString);
+
+ if (NetworkNode->NetworkItem->RemoteHostString)
+ NetworkNode->RemoteAddressText = NetworkNode->NetworkItem->RemoteHostString->sr;
+ else
+ PhInitializeStringRef(&NetworkNode->RemoteAddressText, NetworkNode->NetworkItem->RemoteAddressString);
+}
+
+PPH_NETWORK_ITEM PhGetSelectedNetworkItem()
+{
+ PPH_NETWORK_ITEM networkItem = NULL;
+ ULONG i;
+
+ for (i = 0; i < NetworkNodeList->Count; i++)
+ {
+ PPH_NETWORK_NODE node = NetworkNodeList->Items[i];
+
+ if (node->Node.Selected)
+ {
+ networkItem = node->NetworkItem;
+ break;
+ }
+ }
+
+ return networkItem;
+}
+
+VOID PhGetSelectedNetworkItems(
+ __out PPH_NETWORK_ITEM **NetworkItems,
+ __out PULONG NumberOfNetworkItems
+ )
+{
+ PPH_LIST list;
+ ULONG i;
+
+ list = PhCreateList(2);
+
+ for (i = 0; i < NetworkNodeList->Count; i++)
+ {
+ PPH_NETWORK_NODE node = NetworkNodeList->Items[i];
+
+ if (node->Node.Selected)
+ {
+ PhAddItemList(list, node->NetworkItem);
+ }
+ }
+
+ *NetworkItems = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
+ *NumberOfNetworkItems = list->Count;
+
+ PhDereferenceObject(list);
+}
+
+VOID PhDeselectAllNetworkNodes()
+{
+ TreeNew_DeselectRange(NetworkTreeListHandle, 0, -1);
+}
+
+VOID PhSelectAndEnsureVisibleNetworkNode(
+ __in PPH_NETWORK_NODE NetworkNode
+ )
+{
+ PhDeselectAllNetworkNodes();
+
+ if (!NetworkNode->Node.Visible)
+ return;
+
+ TreeNew_SetFocusNode(NetworkTreeListHandle, &NetworkNode->Node);
+ TreeNew_SetMarkNode(NetworkTreeListHandle, &NetworkNode->Node);
+ TreeNew_EnsureVisible(NetworkTreeListHandle, &NetworkNode->Node);
+}
+
+VOID PhCopyNetworkList()
+{
+ PPH_FULL_STRING text;
+
+ text = PhGetTreeNewText(NetworkTreeListHandle, PHNETLC_MAXIMUM);
+ PhSetClipboardStringEx(NetworkTreeListHandle, text->Buffer, text->Length);
+ PhDereferenceObject(text);
+}
+
+VOID PhWriteNetworkList(
+ __inout PPH_FILE_STREAM FileStream,
+ __in ULONG Mode
+ )
+{
+ PPH_LIST lines;
+ ULONG i;
+
+ lines = PhGetGenericTreeNewLines(NetworkTreeListHandle, Mode);
+
+ for (i = 0; i < lines->Count; i++)
+ {
+ PPH_STRING line;
+
+ line = lines->Items[i];
+ PhWriteStringAsAnsiFileStream(FileStream, &line->sr);
+ PhDereferenceObject(line);
+ PhWriteStringAsAnsiFileStream2(FileStream, L"\r\n");
+ }
+
+ PhDereferenceObject(lines);
+}
diff --git a/2.x/trunk/ProcessHacker/proctree.c b/2.x/trunk/ProcessHacker/proctree.c
index 5f98579bb..035101eb7 100644
--- a/2.x/trunk/ProcessHacker/proctree.c
+++ b/2.x/trunk/ProcessHacker/proctree.c
@@ -1269,7 +1269,6 @@ BOOLEAN NTAPI PhpProcessTreeNewCallback(
if (sortFunction)
{
- // Don't use PhSortList to avoid overhead.
qsort(ProcessNodeList->Items, ProcessNodeList->Count, sizeof(PVOID), sortFunction);
}
}
diff --git a/2.x/trunk/ProcessHacker/resource.h b/2.x/trunk/ProcessHacker/resource.h
index 448fbebbb..9a0aabe85 100644
--- a/2.x/trunk/ProcessHacker/resource.h
+++ b/2.x/trunk/ProcessHacker/resource.h
@@ -437,11 +437,10 @@
#define IDC_ZPRIVATEWS_V 1289
#define IDC_ZSHAREABLEWS_V 1290
#define IDC_ZSHAREDWS_V 1291
-#define IDC_CHECK2 1292
#define IDC_ENABLEINSTANTTOOLTIPS 1292
#define ID_MAINWND_PROCESSTL 2001
#define ID_MAINWND_SERVICETL 2002
-#define ID_MAINWND_NETWORKLV 2003
+#define ID_MAINWND_NETWORKTL 2003
#define ID_MAINWND_PROCESSLV 2004
#define ID_HACKER_EXIT 40001
#define ID_USERS 40002
diff --git a/2.x/trunk/ProcessHacker/sdk/phapppub.h b/2.x/trunk/ProcessHacker/sdk/phapppub.h
index 0212f57ba..abdf148f1 100644
--- a/2.x/trunk/ProcessHacker/sdk/phapppub.h
+++ b/2.x/trunk/ProcessHacker/sdk/phapppub.h
@@ -61,6 +61,17 @@ typedef struct _PH_SERVICE_NODE
// Other members are not exposed.
} PH_SERVICE_NODE, *PPH_SERVICE_NODE;
+typedef struct _PH_NETWORK_NODE
+{
+ PH_TREENEW_NODE Node;
+
+ PH_SH_STATE ShState;
+
+ PPH_NETWORK_ITEM NetworkItem;
+
+ // Other members are not exposed.
+} PH_NETWORK_NODE, *PPH_NETWORK_NODE;
+
typedef struct _PH_MODULE_NODE
{
PH_TREENEW_NODE Node;
diff --git a/2.x/trunk/ProcessHacker/settings.c b/2.x/trunk/ProcessHacker/settings.c
index 3f82ae7f0..4aa121506 100644
--- a/2.x/trunk/ProcessHacker/settings.c
+++ b/2.x/trunk/ProcessHacker/settings.c
@@ -123,7 +123,8 @@ VOID PhSettingsInitialization()
PhpAddStringSetting(L"MemoryReadWriteAddressChoices", L"");
PhpAddStringSetting(L"ModuleTreeListColumns", L"");
PhpAddStringSetting(L"ModuleTreeListSort", L"0,0"); // 0, NoSortOrder
- PhpAddStringSetting(L"NetworkListViewColumns", L"");
+ PhpAddStringSetting(L"NetworkTreeListColumns", L"");
+ PhpAddStringSetting(L"NetworkTreeListSort", L"0,1"); // 0, AscendingSortOrder
PhpAddIntegerSetting(L"NoPurgeProcessRecords", L"0");
PhpAddStringSetting(L"PluginsDirectory", L"plugins");
PhpAddStringSetting(L"ProcessServiceListViewColumns", L"");
diff --git a/2.x/trunk/ProcessHacker/srvlist.c b/2.x/trunk/ProcessHacker/srvlist.c
index fd8492456..89fdd1d88 100644
--- a/2.x/trunk/ProcessHacker/srvlist.c
+++ b/2.x/trunk/ProcessHacker/srvlist.c
@@ -284,7 +284,7 @@ VOID PhUpdateServiceNode(
PhSwapReference(&ServiceNode->TooltipText, NULL);
ServiceNode->ValidMask = 0;
- PhInvalidateTreeNewNode(&ServiceNode->Node, TN_CACHE_COLOR | TN_CACHE_ICON);
+ PhInvalidateTreeNewNode(&ServiceNode->Node, TN_CACHE_ICON);
TreeNew_NodesStructured(ServiceTreeListHandle);
}
@@ -459,7 +459,6 @@ BOOLEAN NTAPI PhpServiceTreeNewCallback(
if (sortFunction)
{
- // Don't use PhSortList to avoid overhead.
qsort(ServiceNodeList->Items, ServiceNodeList->Count, sizeof(PVOID), sortFunction);
}
}