go my file uploader
This commit is contained in:
18
plugins/WindowExplorer/CHANGELOG.txt
Normal file
18
plugins/WindowExplorer/CHANGELOG.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
1.5
|
||||
* Fixed window list not displaying Modern UI windows
|
||||
|
||||
1.4
|
||||
* Fixed hook support for low integrity processes
|
||||
|
||||
1.3
|
||||
* Fixed hook bugs
|
||||
|
||||
1.2
|
||||
* Added more window properties
|
||||
|
||||
1.1
|
||||
* Added Always on Top and Opacity
|
||||
* Renamed Show/Hide and Enable/Disable to Visible and Enabled
|
||||
|
||||
1.0
|
||||
* Initial release
|
||||
307
plugins/WindowExplorer/WindowExplorer.rc
Normal file
307
plugins/WindowExplorer/WindowExplorer.rc
Normal file
@@ -0,0 +1,307 @@
|
||||
// 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,5,0,0
|
||||
PRODUCTVERSION 1,5,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", "wj32"
|
||||
VALUE "FileDescription", "Window Explorer plugin for Process Hacker"
|
||||
VALUE "FileVersion", "1.5"
|
||||
VALUE "InternalName", "WindowExplorer"
|
||||
VALUE "LegalCopyright", "Licensed under the GNU GPL, v3."
|
||||
VALUE "OriginalFilename", "WindowExplorer.dll"
|
||||
VALUE "ProductName", "Window Explorer plugin for Process Hacker"
|
||||
VALUE "ProductVersion", "1.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0xc09, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_WNDLIST DIALOGEX 0, 0, 447, 309
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "Windows"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
PUSHBUTTON "Refresh",IDC_REFRESH,7,6,50,14
|
||||
CONTROL "Windows",IDC_LIST,"PhTreeNew",WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 0x2,7,25,433,277,WS_EX_CLIENTEDGE
|
||||
END
|
||||
|
||||
IDD_WNDPROPS DIALOGEX 0, 0, 233, 152
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Properties"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Property list for the window:",IDC_STATIC,7,7,92,8
|
||||
CONTROL "",IDC_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,20,219,125
|
||||
END
|
||||
|
||||
IDD_WNDGENERAL DIALOGEX 0, 0, 233, 147
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "General"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Text:",IDC_STATIC,7,8,18,8
|
||||
EDITTEXT IDC_TEXT,33,7,193,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
LTEXT "Thread:",IDC_STATIC,7,22,26,8
|
||||
LTEXT "Static",IDC_THREAD,77,22,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Rectangle:",IDC_STATIC,7,33,36,8
|
||||
LTEXT "Static",IDC_RECTANGLE,77,33,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Normal rectangle:",IDC_STATIC,7,44,60,8
|
||||
LTEXT "Static",IDC_NORMALRECTANGLE,77,44,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Client rectangle:",IDC_STATIC,7,55,56,8
|
||||
LTEXT "Static",IDC_CLIENTRECTANGLE,77,55,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Instance handle:",IDC_STATIC,7,66,56,8
|
||||
LTEXT "Static",IDC_INSTANCEHANDLE,77,66,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Menu handle:",IDC_STATIC,7,77,45,8
|
||||
LTEXT "Static",IDC_MENUHANDLE,77,77,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "User data:",IDC_STATIC,7,88,36,8
|
||||
LTEXT "Static",IDC_USERDATA,77,88,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Unicode:",IDC_STATIC,7,99,29,8
|
||||
LTEXT "Static",IDC_UNICODE,77,99,149,8
|
||||
LTEXT "Window proc:",IDC_STATIC,7,110,45,8
|
||||
EDITTEXT IDC_WINDOWPROC,75,110,151,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
LTEXT "Dialog proc:",IDC_STATIC,7,121,39,8
|
||||
EDITTEXT IDC_DIALOGPROC,75,121,151,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
LTEXT "Dialog control ID:",IDC_STATIC,7,132,61,8
|
||||
LTEXT "Static",IDC_CTRLID,77,132,149,8
|
||||
END
|
||||
|
||||
IDD_WNDSTYLES DIALOGEX 0, 0, 233, 140
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Styles"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Styles:",IDC_STATIC,7,7,23,8
|
||||
LTEXT "Static",IDC_STYLES,67,7,159,8
|
||||
LISTBOX IDC_STYLESLIST,7,19,219,46,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Extended styles:",IDC_STATIC,7,69,56,8
|
||||
LTEXT "Static",IDC_EXTENDEDSTYLES,67,69,159,8
|
||||
LISTBOX IDC_EXTENDEDSTYLESLIST,7,81,219,46,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
IDD_WNDCLASS DIALOGEX 0, 0, 233, 132
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Class"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
LTEXT "Name:",IDC_STATIC,7,8,22,8
|
||||
EDITTEXT IDC_NAME,33,7,193,12,ES_AUTOHSCROLL | ES_READONLY
|
||||
LTEXT "Atom:",IDC_STATIC,7,22,20,8
|
||||
LTEXT "Static",IDC_ATOM,77,22,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Styles:",IDC_STATIC,7,33,23,8
|
||||
EDITTEXT IDC_STYLES,75,33,150,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
LTEXT "Instance handle:",IDC_STATIC,7,44,56,8
|
||||
LTEXT "Static",IDC_INSTANCEHANDLE,77,44,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Icon handle:",IDC_STATIC,7,55,42,8
|
||||
LTEXT "Static",IDC_ICONHANDLE,77,55,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Small icon handle:",IDC_STATIC,7,66,60,8
|
||||
LTEXT "Static",IDC_SMALLICONHANDLE,77,66,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Cursor handle:",IDC_STATIC,7,77,49,8
|
||||
LTEXT "Static",IDC_CURSORHANDLE,77,77,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Background brush:",IDC_STATIC,7,88,61,8
|
||||
LTEXT "Static",IDC_BACKGROUNDBRUSH,77,88,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Menu name:",IDC_STATIC,7,99,41,8
|
||||
LTEXT "Static",IDC_MENUNAME,77,99,149,8,SS_ENDELLIPSIS
|
||||
LTEXT "Window proc:",IDC_STATIC,7,110,45,8
|
||||
EDITTEXT IDC_WINDOWPROC,75,110,151,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_WNDLIST, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 440
|
||||
TOPMARGIN, 6
|
||||
BOTTOMMARGIN, 302
|
||||
END
|
||||
|
||||
IDD_WNDPROPS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 226
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 145
|
||||
END
|
||||
|
||||
IDD_WNDGENERAL, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 226
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 140
|
||||
END
|
||||
|
||||
IDD_WNDSTYLES, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 226
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 133
|
||||
END
|
||||
|
||||
IDD_WNDCLASS, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 226
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 125
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Menu
|
||||
//
|
||||
|
||||
IDR_WINDOW MENU
|
||||
BEGIN
|
||||
POPUP "Window"
|
||||
BEGIN
|
||||
MENUITEM "Bring to front", ID_WINDOW_BRINGTOFRONT
|
||||
MENUITEM "Restore", ID_WINDOW_RESTORE
|
||||
MENUITEM "Minimize", ID_WINDOW_MINIMIZE
|
||||
MENUITEM "Maximize", ID_WINDOW_MAXIMIZE
|
||||
MENUITEM "Close", ID_WINDOW_CLOSE
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Visible", ID_WINDOW_VISIBLE
|
||||
MENUITEM "Enabled", ID_WINDOW_ENABLED
|
||||
MENUITEM "Always on top", ID_WINDOW_ALWAYSONTOP
|
||||
POPUP "Opacity"
|
||||
BEGIN
|
||||
MENUITEM "10%", ID_OPACITY_10
|
||||
MENUITEM "20%", ID_OPACITY_20
|
||||
MENUITEM "30%", ID_OPACITY_30
|
||||
MENUITEM "40%", ID_OPACITY_40
|
||||
MENUITEM "50%", ID_OPACITY_50
|
||||
MENUITEM "60%", ID_OPACITY_60
|
||||
MENUITEM "70%", ID_OPACITY_70
|
||||
MENUITEM "80%", ID_OPACITY_80
|
||||
MENUITEM "90%", ID_OPACITY_90
|
||||
MENUITEM "Opaque", ID_OPACITY_OPAQUE
|
||||
END
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Highlight", ID_WINDOW_HIGHLIGHT
|
||||
MENUITEM "Go to thread", ID_WINDOW_GOTOTHREAD
|
||||
MENUITEM "Properties", ID_WINDOW_PROPERTIES
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Copy\aCtrl+C", ID_WINDOW_COPY
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// AFX_DIALOG_LAYOUT
|
||||
//
|
||||
|
||||
IDD_WNDGENERAL AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
IDD_WNDLIST AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
IDD_WNDCLASS AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
#endif // English (Australia) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
106
plugins/WindowExplorer/WindowExplorer.vcxproj
Normal file
106
plugins/WindowExplorer/WindowExplorer.vcxproj
Normal file
@@ -0,0 +1,106 @@
|
||||
<?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>{37488DC1-E45F-4626-A87C-3A854A153D1A}</ProjectGuid>
|
||||
<RootNamespace>WindowExplorer</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectName>WindowExplorer</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>
|
||||
<DelayLoadDLLs>ProcessHacker.exe;comctl32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Link>
|
||||
<DelayLoadDLLs>ProcessHacker.exe;comctl32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Link>
|
||||
<DelayLoadDLLs>ProcessHacker.exe;comctl32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Link>
|
||||
<DelayLoadDLLs>ProcessHacker.exe;comctl32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="hook.c" />
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="utils.c" />
|
||||
<ClCompile Include="wnddlg.c" />
|
||||
<ClCompile Include="wndprp.c" />
|
||||
<ClCompile Include="wndtree.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="wndexp.h" />
|
||||
<ClInclude Include="wndtree.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CHANGELOG.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="WindowExplorer.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
||||
56
plugins/WindowExplorer/WindowExplorer.vcxproj.filters
Normal file
56
plugins/WindowExplorer/WindowExplorer.vcxproj.filters
Normal file
@@ -0,0 +1,56 @@
|
||||
<?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="wndtree.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wnddlg.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wndprp.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hook.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="wndexp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wndtree.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CHANGELOG.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="WindowExplorer.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
509
plugins/WindowExplorer/hook.c
Normal file
509
plugins/WindowExplorer/hook.c
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Process Hacker Window Explorer -
|
||||
* hook procedure
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Window Explorer uses a hook procedure in order to get window procedure
|
||||
* and other information that can't be retrieved using GetWindowLongPtr.
|
||||
* Because WindowExplorer.dll needs to be loaded into processes other
|
||||
* than Process Hacker, both ProcessHacker.exe and comctl32.dll are set as
|
||||
* delay-loaded DLLs. The other DLLs that we depend on (gdi32.dll,
|
||||
* kernel32.dll, ntdll.dll, user32.dll) are all guaranteed to be already
|
||||
* loaded whenever WindowExplorer.dll needs to be loaded.
|
||||
*/
|
||||
|
||||
#include "wndexp.h"
|
||||
|
||||
BOOLEAN WepCreateServerObjects(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN WepOpenServerObjects(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID WepCloseServerObjects(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID WepWriteClientData(
|
||||
_In_ HWND hwnd
|
||||
);
|
||||
|
||||
LRESULT CALLBACK WepCallWndProc(
|
||||
_In_ int nCode,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
// Shared
|
||||
ULONG WeServerMessage;
|
||||
HANDLE WeServerSharedSection;
|
||||
PWE_HOOK_SHARED_DATA WeServerSharedData;
|
||||
HANDLE WeServerSharedSectionLock;
|
||||
HANDLE WeServerSharedSectionEvent;
|
||||
// Server
|
||||
HHOOK WeHookHandle = NULL;
|
||||
// The current message ID is used to detect out-of-sync clients.
|
||||
ULONG WeCurrentMessageId = 0;
|
||||
|
||||
// Server
|
||||
|
||||
VOID WeHookServerInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (WeHookHandle)
|
||||
return;
|
||||
|
||||
WeServerMessage = RegisterWindowMessage(WE_SERVER_MESSAGE_NAME);
|
||||
|
||||
if (!WepCreateServerObjects())
|
||||
return;
|
||||
|
||||
WeHookHandle = SetWindowsHookEx(WH_CALLWNDPROC, WepCallWndProc, PluginInstance->DllBase, 0);
|
||||
}
|
||||
|
||||
VOID WeHookServerUninitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (WeHookHandle)
|
||||
{
|
||||
UnhookWindowsHookEx(WeHookHandle);
|
||||
WeHookHandle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN WepCreateServerObjects(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
WCHAR buffer[256];
|
||||
UNICODE_STRING objectName;
|
||||
SECURITY_DESCRIPTOR securityDescriptor;
|
||||
UCHAR saclBuffer[sizeof(ACL) + FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)];
|
||||
PACL sacl;
|
||||
UCHAR mandatoryLabelAceBuffer[FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG)];
|
||||
PSYSTEM_MANDATORY_LABEL_ACE mandatoryLabelAce;
|
||||
PSID sid;
|
||||
|
||||
if (!WeServerSharedSection)
|
||||
{
|
||||
LARGE_INTEGER maximumSize;
|
||||
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
maximumSize.QuadPart = sizeof(WE_HOOK_SHARED_DATA);
|
||||
|
||||
if (!NT_SUCCESS(NtCreateSection(
|
||||
&WeServerSharedSection,
|
||||
SECTION_ALL_ACCESS,
|
||||
&objectAttributes,
|
||||
&maximumSize,
|
||||
PAGE_READWRITE,
|
||||
SEC_COMMIT,
|
||||
NULL
|
||||
)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WeServerSharedData)
|
||||
{
|
||||
PVOID viewBase;
|
||||
SIZE_T viewSize;
|
||||
|
||||
viewBase = NULL;
|
||||
viewSize = sizeof(WE_HOOK_SHARED_DATA);
|
||||
|
||||
if (!NT_SUCCESS(NtMapViewOfSection(
|
||||
WeServerSharedSection,
|
||||
NtCurrentProcess(),
|
||||
&viewBase,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&viewSize,
|
||||
ViewShare,
|
||||
0,
|
||||
PAGE_READWRITE
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WeServerSharedData = viewBase;
|
||||
}
|
||||
|
||||
if (!WeServerSharedSectionLock)
|
||||
{
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_LOCK_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
if (!NT_SUCCESS(NtCreateMutant(
|
||||
&WeServerSharedSectionLock,
|
||||
MUTANT_ALL_ACCESS,
|
||||
&objectAttributes,
|
||||
FALSE
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WeServerSharedSectionEvent)
|
||||
{
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_EVENT_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
if (!NT_SUCCESS(NtCreateEvent(
|
||||
&WeServerSharedSectionEvent,
|
||||
EVENT_ALL_ACCESS,
|
||||
&objectAttributes,
|
||||
NotificationEvent,
|
||||
FALSE
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// If mandatory labels are supported, set it to the lowest possible level.
|
||||
if (WE_WindowsVersion >= WINDOWS_VISTA)
|
||||
{
|
||||
static SID_IDENTIFIER_AUTHORITY mandatoryLabelAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;
|
||||
|
||||
RtlCreateSecurityDescriptor(&securityDescriptor, SECURITY_DESCRIPTOR_REVISION);
|
||||
|
||||
sacl = (PACL)saclBuffer;
|
||||
RtlCreateAcl(sacl, sizeof(saclBuffer), ACL_REVISION);
|
||||
|
||||
mandatoryLabelAce = (PSYSTEM_MANDATORY_LABEL_ACE)mandatoryLabelAceBuffer;
|
||||
mandatoryLabelAce->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE;
|
||||
mandatoryLabelAce->Header.AceFlags = 0;
|
||||
mandatoryLabelAce->Header.AceSize = sizeof(mandatoryLabelAceBuffer);
|
||||
mandatoryLabelAce->Mask = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP;
|
||||
|
||||
sid = (PSID)&mandatoryLabelAce->SidStart;
|
||||
RtlInitializeSid(sid, &mandatoryLabelAuthority, 1);
|
||||
*RtlSubAuthoritySid(sid, 0) = SECURITY_MANDATORY_LOW_RID;
|
||||
|
||||
if (NT_SUCCESS(RtlAddAce(sacl, ACL_REVISION, MAXULONG32, mandatoryLabelAce, sizeof(mandatoryLabelAceBuffer))))
|
||||
{
|
||||
if (NT_SUCCESS(RtlSetSaclSecurityDescriptor(&securityDescriptor, TRUE, sacl, FALSE)))
|
||||
{
|
||||
NtSetSecurityObject(WeServerSharedSection, LABEL_SECURITY_INFORMATION, &securityDescriptor);
|
||||
NtSetSecurityObject(WeServerSharedSectionLock, LABEL_SECURITY_INFORMATION, &securityDescriptor);
|
||||
NtSetSecurityObject(WeServerSharedSectionEvent, LABEL_SECURITY_INFORMATION, &securityDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN WepOpenServerObjects(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
WCHAR buffer[256];
|
||||
UNICODE_STRING objectName;
|
||||
|
||||
if (!WeServerSharedSection)
|
||||
{
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
if (!NT_SUCCESS(NtOpenSection(
|
||||
&WeServerSharedSection,
|
||||
SECTION_ALL_ACCESS,
|
||||
&objectAttributes
|
||||
)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WeServerSharedData)
|
||||
{
|
||||
PVOID viewBase;
|
||||
SIZE_T viewSize;
|
||||
|
||||
viewBase = NULL;
|
||||
viewSize = sizeof(WE_HOOK_SHARED_DATA);
|
||||
|
||||
if (!NT_SUCCESS(NtMapViewOfSection(
|
||||
WeServerSharedSection,
|
||||
NtCurrentProcess(),
|
||||
&viewBase,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
&viewSize,
|
||||
ViewShare,
|
||||
0,
|
||||
PAGE_READWRITE
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WeServerSharedData = viewBase;
|
||||
}
|
||||
|
||||
if (!WeServerSharedSectionLock)
|
||||
{
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_LOCK_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
if (!NT_SUCCESS(NtOpenMutant(
|
||||
&WeServerSharedSectionLock,
|
||||
MUTANT_ALL_ACCESS,
|
||||
&objectAttributes
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WeServerSharedSectionEvent)
|
||||
{
|
||||
WeFormatLocalObjectName(WE_SERVER_SHARED_SECTION_EVENT_NAME, buffer, &objectName);
|
||||
InitializeObjectAttributes(&objectAttributes, &objectName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
if (!NT_SUCCESS(NtOpenEvent(
|
||||
&WeServerSharedSectionEvent,
|
||||
EVENT_ALL_ACCESS,
|
||||
&objectAttributes
|
||||
)))
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID WepCloseServerObjects(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (WeServerSharedSection)
|
||||
{
|
||||
NtClose(WeServerSharedSection);
|
||||
WeServerSharedSection = NULL;
|
||||
}
|
||||
|
||||
if (WeServerSharedData)
|
||||
{
|
||||
NtUnmapViewOfSection(NtCurrentProcess(), WeServerSharedData);
|
||||
WeServerSharedData = NULL;
|
||||
}
|
||||
|
||||
if (WeServerSharedSectionLock)
|
||||
{
|
||||
NtClose(WeServerSharedSectionLock);
|
||||
WeServerSharedSectionLock = NULL;
|
||||
}
|
||||
|
||||
if (WeServerSharedSectionEvent)
|
||||
{
|
||||
NtClose(WeServerSharedSectionEvent);
|
||||
WeServerSharedSectionEvent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN WeIsServerActive(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (WepOpenServerObjects())
|
||||
{
|
||||
WepCloseServerObjects();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN WeLockServerSharedData(
|
||||
_Out_ PWE_HOOK_SHARED_DATA *Data
|
||||
)
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
if (!WeServerSharedSectionLock)
|
||||
return FALSE;
|
||||
|
||||
timeout.QuadPart = -WE_CLIENT_MESSAGE_TIMEOUT * PH_TIMEOUT_MS;
|
||||
|
||||
if (NtWaitForSingleObject(WeServerSharedSectionLock, FALSE, &timeout) != WAIT_OBJECT_0)
|
||||
return FALSE;
|
||||
|
||||
*Data = WeServerSharedData;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID WeUnlockServerSharedData(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NtReleaseMutant(WeServerSharedSectionLock, NULL);
|
||||
}
|
||||
|
||||
BOOLEAN WeSendServerRequest(
|
||||
_In_ HWND hWnd
|
||||
)
|
||||
{
|
||||
ULONG threadId;
|
||||
ULONG processId;
|
||||
LARGE_INTEGER timeout;
|
||||
|
||||
if (!WeServerSharedData || !WeServerSharedSectionEvent)
|
||||
return FALSE;
|
||||
|
||||
threadId = GetWindowThreadProcessId(hWnd, &processId);
|
||||
|
||||
if (UlongToHandle(processId) == NtCurrentProcessId())
|
||||
{
|
||||
// We are trying to get information about the server. Call the procedure directly.
|
||||
WepWriteClientData(hWnd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Call the client and wait for the client to finish.
|
||||
|
||||
WeCurrentMessageId++;
|
||||
WeServerSharedData->MessageId = WeCurrentMessageId;
|
||||
NtResetEvent(WeServerSharedSectionEvent, NULL);
|
||||
|
||||
if (!SendNotifyMessage(hWnd, WeServerMessage, (WPARAM)NtCurrentProcessId(), WeCurrentMessageId))
|
||||
return FALSE;
|
||||
|
||||
timeout.QuadPart = -WE_CLIENT_MESSAGE_TIMEOUT * PH_TIMEOUT_MS;
|
||||
|
||||
if (NtWaitForSingleObject(WeServerSharedSectionEvent, FALSE, &timeout) != STATUS_WAIT_0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Client
|
||||
|
||||
VOID WeHookClientInitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
WeServerMessage = RegisterWindowMessage(WE_SERVER_MESSAGE_NAME);
|
||||
}
|
||||
|
||||
VOID WeHookClientUninitialization(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
VOID WepWriteClientData(
|
||||
_In_ HWND hwnd
|
||||
)
|
||||
{
|
||||
WCHAR className[256];
|
||||
LOGICAL isUnicode;
|
||||
|
||||
memset(&WeServerSharedData->c, 0, sizeof(WeServerSharedData->c));
|
||||
isUnicode = IsWindowUnicode(hwnd);
|
||||
|
||||
if (isUnicode)
|
||||
{
|
||||
WeServerSharedData->c.WndProc = GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
|
||||
WeServerSharedData->c.DlgProc = GetWindowLongPtrW(hwnd, DWLP_DLGPROC);
|
||||
}
|
||||
else
|
||||
{
|
||||
WeServerSharedData->c.WndProc = GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
|
||||
WeServerSharedData->c.DlgProc = GetWindowLongPtrA(hwnd, DWLP_DLGPROC);
|
||||
}
|
||||
|
||||
if (!GetClassName(hwnd, className, sizeof(className) / sizeof(WCHAR)))
|
||||
className[0] = 0;
|
||||
|
||||
WeServerSharedData->c.ClassInfo.cbSize = sizeof(WNDCLASSEX);
|
||||
GetClassInfoEx(NULL, className, &WeServerSharedData->c.ClassInfo);
|
||||
|
||||
if (isUnicode)
|
||||
WeServerSharedData->c.ClassInfo.lpfnWndProc = (PVOID)GetClassLongPtrW(hwnd, GCLP_WNDPROC);
|
||||
else
|
||||
WeServerSharedData->c.ClassInfo.lpfnWndProc = (PVOID)GetClassLongPtrA(hwnd, GCLP_WNDPROC);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WepCallWndProc(
|
||||
_In_ int nCode,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
LRESULT result;
|
||||
PCWPSTRUCT info;
|
||||
|
||||
result = CallNextHookEx(NULL, nCode, wParam, lParam);
|
||||
|
||||
info = (PCWPSTRUCT)lParam;
|
||||
|
||||
if (info->message == WeServerMessage)
|
||||
{
|
||||
HANDLE serverProcessId;
|
||||
ULONG messageId;
|
||||
|
||||
serverProcessId = (HANDLE)info->wParam;
|
||||
messageId = (ULONG)info->lParam;
|
||||
|
||||
if (serverProcessId != NtCurrentProcessId())
|
||||
{
|
||||
if (WepOpenServerObjects())
|
||||
{
|
||||
if (WeServerSharedData->MessageId == messageId)
|
||||
{
|
||||
WepWriteClientData(info->hwnd);
|
||||
NtSetEvent(WeServerSharedSectionEvent, NULL);
|
||||
}
|
||||
|
||||
WepCloseServerObjects();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
390
plugins/WindowExplorer/main.c
Normal file
390
plugins/WindowExplorer/main.c
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Process Hacker Window Explorer -
|
||||
* main program
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wndexp.h"
|
||||
#include "resource.h"
|
||||
|
||||
VOID NTAPI LoadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI UnloadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI ShowOptionsCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI MenuItemCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI MainMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI ProcessPropertiesInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI ProcessMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID NTAPI ThreadMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
BOOLEAN IsHookClient;
|
||||
PPH_PLUGIN PluginInstance;
|
||||
PH_CALLBACK_REGISTRATION PluginLoadCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginUnloadCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginShowOptionsCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION PluginMenuItemCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION MainMenuInitializingCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION ProcessPropertiesInitializingCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION ProcessMenuInitializingCallbackRegistration;
|
||||
PH_CALLBACK_REGISTRATION ThreadMenuInitializingCallbackRegistration;
|
||||
|
||||
LOGICAL DllMain(
|
||||
_In_ HINSTANCE Instance,
|
||||
_In_ ULONG Reason,
|
||||
_Reserved_ PVOID Reserved
|
||||
)
|
||||
{
|
||||
switch (Reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
PPH_PLUGIN_INFORMATION info;
|
||||
BOOLEAN isClient;
|
||||
|
||||
isClient = FALSE;
|
||||
|
||||
if (!GetModuleHandle(L"ProcessHacker.exe") || !WeGetProcedureAddress("PhLibImageBase"))
|
||||
{
|
||||
isClient = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// WindowExplorer appears to be loading within Process Hacker. However, if there is
|
||||
// already a server instance, the the hook will be active, and our DllMain routine
|
||||
// will most likely be called before the plugin system is even initialized. Attempting
|
||||
// to register a plugin would result in an access violation, so load as a client for now.
|
||||
if (WeIsServerActive())
|
||||
isClient = TRUE;
|
||||
}
|
||||
|
||||
if (isClient)
|
||||
{
|
||||
// This DLL is being loaded not as a Process Hacker plugin, but as a hook.
|
||||
IsHookClient = TRUE;
|
||||
WeHookClientInitialization();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
|
||||
|
||||
if (!PluginInstance)
|
||||
return FALSE;
|
||||
|
||||
info->DisplayName = L"Window Explorer";
|
||||
info->Author = L"wj32";
|
||||
info->Description = L"View and manipulate windows.";
|
||||
info->Url = L"https://wj32.org/processhacker/forums/viewtopic.php?t=1116";
|
||||
info->HasOptions = FALSE;
|
||||
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
|
||||
LoadCallback,
|
||||
NULL,
|
||||
&PluginLoadCallbackRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackUnload),
|
||||
UnloadCallback,
|
||||
NULL,
|
||||
&PluginUnloadCallbackRegistration
|
||||
);
|
||||
//PhRegisterCallback(
|
||||
// PhGetPluginCallback(PluginInstance, PluginCallbackShowOptions),
|
||||
// ShowOptionsCallback,
|
||||
// NULL,
|
||||
// &PluginShowOptionsCallbackRegistration
|
||||
// );
|
||||
PhRegisterCallback(
|
||||
PhGetPluginCallback(PluginInstance, PluginCallbackMenuItem),
|
||||
MenuItemCallback,
|
||||
NULL,
|
||||
&PluginMenuItemCallbackRegistration
|
||||
);
|
||||
|
||||
PhRegisterCallback(
|
||||
PhGetGeneralCallback(GeneralCallbackMainMenuInitializing),
|
||||
MainMenuInitializingCallback,
|
||||
NULL,
|
||||
&MainMenuInitializingCallbackRegistration
|
||||
);
|
||||
//PhRegisterCallback(
|
||||
// PhGetGeneralCallback(GeneralCallbackProcessPropertiesInitializing),
|
||||
// ProcessPropertiesInitializingCallback,
|
||||
// NULL,
|
||||
// &ProcessPropertiesInitializingCallbackRegistration
|
||||
// );
|
||||
PhRegisterCallback(
|
||||
PhGetGeneralCallback(GeneralCallbackProcessMenuInitializing),
|
||||
ProcessMenuInitializingCallback,
|
||||
NULL,
|
||||
&ProcessMenuInitializingCallbackRegistration
|
||||
);
|
||||
PhRegisterCallback(
|
||||
PhGetGeneralCallback(GeneralCallbackThreadMenuInitializing),
|
||||
ThreadMenuInitializingCallback,
|
||||
NULL,
|
||||
&ThreadMenuInitializingCallbackRegistration
|
||||
);
|
||||
|
||||
{
|
||||
static PH_SETTING_CREATE settings[] =
|
||||
{
|
||||
{ IntegerSettingType, SETTING_NAME_SHOW_DESKTOP_WINDOWS, L"0" },
|
||||
{ StringSettingType, SETTING_NAME_WINDOW_TREE_LIST_COLUMNS, L"" },
|
||||
{ IntegerPairSettingType, SETTING_NAME_WINDOWS_WINDOW_POSITION, L"100,100" },
|
||||
{ ScalableIntegerPairSettingType, SETTING_NAME_WINDOWS_WINDOW_SIZE, L"@96|690,540" }
|
||||
};
|
||||
|
||||
PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
{
|
||||
if (IsHookClient)
|
||||
{
|
||||
WeHookClientUninitialization();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID NTAPI LoadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
VOID NTAPI UnloadCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
WeHookServerUninitialization();
|
||||
}
|
||||
|
||||
VOID NTAPI ShowOptionsCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
BOOL CALLBACK WepEnumDesktopProc(
|
||||
_In_ LPTSTR lpszDesktop,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PhAddItemList((PPH_LIST)lParam, PhaCreateString(lpszDesktop)->Buffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID NTAPI MenuItemCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
|
||||
|
||||
switch (menuItem->Id)
|
||||
{
|
||||
case ID_VIEW_WINDOWS:
|
||||
{
|
||||
WE_WINDOW_SELECTOR selector;
|
||||
|
||||
selector.Type = WeWindowSelectorAll;
|
||||
WeShowWindowsDialog(WE_PhMainWndHandle, &selector);
|
||||
}
|
||||
break;
|
||||
case ID_VIEW_DESKTOPWINDOWS:
|
||||
{
|
||||
PPH_LIST desktopNames;
|
||||
PPH_STRING selectedChoice = NULL;
|
||||
|
||||
desktopNames = PH_AUTO(PhCreateList(4));
|
||||
EnumDesktops(GetProcessWindowStation(), WepEnumDesktopProc, (LPARAM)desktopNames);
|
||||
|
||||
if (PhaChoiceDialog(
|
||||
WE_PhMainWndHandle,
|
||||
L"Desktop Windows",
|
||||
L"Display windows for the following desktop:",
|
||||
(PWSTR *)desktopNames->Items,
|
||||
desktopNames->Count,
|
||||
NULL,
|
||||
PH_CHOICE_DIALOG_CHOICE,
|
||||
&selectedChoice,
|
||||
NULL,
|
||||
NULL
|
||||
))
|
||||
{
|
||||
WE_WINDOW_SELECTOR selector;
|
||||
|
||||
selector.Type = WeWindowSelectorDesktop;
|
||||
PhSetReference(&selector.Desktop.DesktopName, selectedChoice);
|
||||
WeShowWindowsDialog(WE_PhMainWndHandle, &selector);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_PROCESS_WINDOWS:
|
||||
{
|
||||
WE_WINDOW_SELECTOR selector;
|
||||
|
||||
selector.Type = WeWindowSelectorProcess;
|
||||
selector.Process.ProcessId = ((PPH_PROCESS_ITEM)menuItem->Context)->ProcessId;
|
||||
WeShowWindowsDialog(WE_PhMainWndHandle, &selector);
|
||||
}
|
||||
break;
|
||||
case ID_THREAD_WINDOWS:
|
||||
{
|
||||
WE_WINDOW_SELECTOR selector;
|
||||
|
||||
selector.Type = WeWindowSelectorThread;
|
||||
selector.Thread.ThreadId = ((PPH_THREAD_ITEM)menuItem->Context)->ThreadId;
|
||||
WeShowWindowsDialog(WE_PhMainWndHandle, &selector);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID NTAPI MainMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
ULONG insertIndex;
|
||||
PPH_EMENU_ITEM menuItem;
|
||||
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
|
||||
|
||||
if (menuInfo->u.MainMenu.SubMenuIndex != PH_MENU_ITEM_LOCATION_VIEW)
|
||||
return;
|
||||
|
||||
if (menuItem = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_STARTSWITH, L"System Information", 0))
|
||||
insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
|
||||
else
|
||||
insertIndex = 0;
|
||||
|
||||
PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_WINDOWS, L"Windows", NULL), insertIndex);
|
||||
|
||||
if (PhGetIntegerSetting(SETTING_NAME_SHOW_DESKTOP_WINDOWS))
|
||||
{
|
||||
insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
|
||||
|
||||
PhInsertEMenuItem(menuInfo->Menu, PhPluginCreateEMenuItem(PluginInstance, 0, ID_VIEW_DESKTOPWINDOWS, L"Desktop Windows...", NULL), insertIndex);
|
||||
}
|
||||
}
|
||||
|
||||
VOID NTAPI ProcessPropertiesInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
NOTHING;
|
||||
}
|
||||
|
||||
VOID NTAPI ProcessMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
|
||||
PPH_PROCESS_ITEM processItem;
|
||||
ULONG flags;
|
||||
PPH_EMENU_ITEM miscMenu;
|
||||
|
||||
if (menuInfo->u.Process.NumberOfProcesses == 1)
|
||||
processItem = menuInfo->u.Process.Processes[0];
|
||||
else
|
||||
processItem = NULL;
|
||||
|
||||
flags = 0;
|
||||
|
||||
if (!processItem)
|
||||
flags = PH_EMENU_DISABLED;
|
||||
|
||||
miscMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"Miscellaneous", 0);
|
||||
|
||||
if (miscMenu)
|
||||
{
|
||||
PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_WINDOWS, L"Windows", processItem), -1);
|
||||
}
|
||||
}
|
||||
|
||||
VOID NTAPI ThreadMenuInitializingCallback(
|
||||
_In_opt_ PVOID Parameter,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
|
||||
PPH_THREAD_ITEM threadItem;
|
||||
ULONG insertIndex;
|
||||
PPH_EMENU_ITEM menuItem;
|
||||
|
||||
if (menuInfo->u.Thread.NumberOfThreads == 1)
|
||||
threadItem = menuInfo->u.Thread.Threads[0];
|
||||
else
|
||||
threadItem = NULL;
|
||||
|
||||
if (menuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Token", 0))
|
||||
insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
|
||||
else
|
||||
insertIndex = 0;
|
||||
|
||||
PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_THREAD_WINDOWS,
|
||||
L"Windows", threadItem), insertIndex);
|
||||
|
||||
if (!threadItem) menuItem->Flags |= PH_EMENU_DISABLED;
|
||||
}
|
||||
81
plugins/WindowExplorer/resource.h
Normal file
81
plugins/WindowExplorer/resource.h
Normal file
@@ -0,0 +1,81 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by WindowExplorer.rc
|
||||
//
|
||||
#define IDD_WNDPROPS 9
|
||||
#define IDD_WNDLIST 101
|
||||
#define ID_VIEW_WINDOWS 101
|
||||
#define ID_THREAD_WINDOWS 102
|
||||
#define ID_PROCESS_WINDOWS 103
|
||||
#define IDR_WINDOW 103
|
||||
#define ID_SHOWCONTEXTMENU 104
|
||||
#define IDD_WNDGENERAL 104
|
||||
#define ID_VIEW_DESKTOPWINDOWS 105
|
||||
#define IDD_WNDSTYLES 105
|
||||
#define IDD_WNDCLASS 106
|
||||
#define IDD_WNDGENERAL1 106
|
||||
#define IDC_LIST 1001
|
||||
#define IDC_REFRESH 1002
|
||||
#define IDC_TEXT 1009
|
||||
#define IDC_RECTANGLE 1010
|
||||
#define IDC_NORMALRECTANGLE 1011
|
||||
#define IDC_CLIENTRECTANGLE 1012
|
||||
#define IDC_THREAD 1016
|
||||
#define IDC_STYLESLIST 1017
|
||||
#define IDC_STYLES 1018
|
||||
#define IDC_EXTENDEDSTYLES 1019
|
||||
#define IDC_EXTENDEDSTYLESLIST 1020
|
||||
#define IDC_INSTANCEHANDLE 1021
|
||||
#define IDC_MENUHANDLE 1022
|
||||
#define IDC_WINDOWPROC 1023
|
||||
#define IDC_WINDOWPROC2 1024
|
||||
#define IDC_DIALOGPROC 1024
|
||||
#define IDC_USERDATA 1025
|
||||
#define IDC_NAME 1026
|
||||
#define IDC_ATOM 1028
|
||||
#define IDC_CURSORHANDLE 1029
|
||||
#define IDC_ICONHANDLE 1030
|
||||
#define IDC_ICONHANDLE2 1031
|
||||
#define IDC_SMALLICONHANDLE 1031
|
||||
#define IDC_BACKGROUNDBRUSH 1032
|
||||
#define IDC_MENUNAME 1033
|
||||
#define IDC_UNICODE 1034
|
||||
#define IDC_CTRLID 1035
|
||||
#define ID_WINDOW_GOTOTHREAD 40001
|
||||
#define ID_WINDOW_COPY 40002
|
||||
#define ID_WINDOW_PROPERTIES 40003
|
||||
#define ID_WINDOW_BRINGTOFRONT 40004
|
||||
#define ID_WINDOW_RESTORE 40005
|
||||
#define ID_WINDOW_MINIMIZE 40006
|
||||
#define ID_WINDOW_MAXIMIZE 40007
|
||||
#define ID_WINDOW_CLOSE 40008
|
||||
#define ID_WINDOW_SHOW 40009
|
||||
#define ID_WINDOW_HIGHLIGHT 40010
|
||||
#define ID_WINDOW_SHOWHIDE 40011
|
||||
#define ID_WINDOW_ENABLE 40012
|
||||
#define ID_WINDOW_ENABLEDISABLE 40013
|
||||
#define ID_WINDOW_ALWAYSONTOP 40014
|
||||
#define ID_WINDOW_OPACITY 40015
|
||||
#define ID_OPACITY_10 40016
|
||||
#define ID_OPACITY_20 40017
|
||||
#define ID_OPACITY_30 40018
|
||||
#define ID_OPACITY_40 40019
|
||||
#define ID_OPACITY_50 40020
|
||||
#define ID_OPACITY_60 40021
|
||||
#define ID_OPACITY_70 40022
|
||||
#define ID_OPACITY_80 40023
|
||||
#define ID_OPACITY_90 40024
|
||||
#define ID_OPACITY_OPAQUE 40025
|
||||
#define ID_WINDOW_VISIBLE 40026
|
||||
#define ID_WINDOW_ENABLED 40027
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 108
|
||||
#define _APS_NEXT_COMMAND_VALUE 40028
|
||||
#define _APS_NEXT_CONTROL_VALUE 1035
|
||||
#define _APS_NEXT_SYMED_VALUE 106
|
||||
#endif
|
||||
#endif
|
||||
104
plugins/WindowExplorer/utils.c
Normal file
104
plugins/WindowExplorer/utils.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Process Hacker Window Explorer -
|
||||
* utility functions
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wndexp.h"
|
||||
|
||||
// WARNING: No functions from ProcessHacker.exe should be used in this file!
|
||||
|
||||
PVOID WeGetProcedureAddress(
|
||||
_In_ PSTR Name
|
||||
)
|
||||
{
|
||||
static PVOID imageBase = NULL;
|
||||
|
||||
if (!imageBase)
|
||||
imageBase = GetModuleHandle(L"ProcessHacker.exe");
|
||||
|
||||
return (PVOID)GetProcAddress(imageBase, Name);
|
||||
}
|
||||
|
||||
VOID WeFormatLocalObjectName(
|
||||
_In_ PWSTR OriginalName,
|
||||
_Inout_updates_(256) PWCHAR Buffer,
|
||||
_Out_ PUNICODE_STRING ObjectName
|
||||
)
|
||||
{
|
||||
SIZE_T length;
|
||||
SIZE_T originalNameLength;
|
||||
|
||||
// Sessions other than session 0 require SeCreateGlobalPrivilege.
|
||||
if (NtCurrentPeb()->SessionId != 0)
|
||||
{
|
||||
memcpy(Buffer, L"\\Sessions\\", 10 * sizeof(WCHAR));
|
||||
_ultow(NtCurrentPeb()->SessionId, Buffer + 10, 10);
|
||||
length = wcslen(Buffer);
|
||||
originalNameLength = wcslen(OriginalName);
|
||||
memcpy(Buffer + length, OriginalName, (originalNameLength + 1) * sizeof(WCHAR));
|
||||
length += originalNameLength;
|
||||
|
||||
ObjectName->Buffer = Buffer;
|
||||
ObjectName->MaximumLength = (ObjectName->Length = (USHORT)(length * sizeof(WCHAR))) + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlInitUnicodeString(ObjectName, OriginalName);
|
||||
}
|
||||
}
|
||||
|
||||
VOID WeInvertWindowBorder(
|
||||
_In_ HWND hWnd
|
||||
)
|
||||
{
|
||||
RECT rect;
|
||||
HDC hdc;
|
||||
|
||||
GetWindowRect(hWnd, &rect);
|
||||
hdc = GetWindowDC(hWnd);
|
||||
|
||||
if (hdc)
|
||||
{
|
||||
ULONG penWidth = GetSystemMetrics(SM_CXBORDER) * 3;
|
||||
INT oldDc;
|
||||
HPEN pen;
|
||||
HBRUSH brush;
|
||||
|
||||
oldDc = SaveDC(hdc);
|
||||
|
||||
// Get an inversion effect.
|
||||
SetROP2(hdc, R2_NOT);
|
||||
|
||||
pen = CreatePen(PS_INSIDEFRAME, penWidth, RGB(0x00, 0x00, 0x00));
|
||||
SelectObject(hdc, pen);
|
||||
|
||||
brush = GetStockObject(NULL_BRUSH);
|
||||
SelectObject(hdc, brush);
|
||||
|
||||
// Draw the rectangle.
|
||||
Rectangle(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top);
|
||||
|
||||
// Cleanup.
|
||||
DeleteObject(pen);
|
||||
|
||||
RestoreDC(hdc, oldDc);
|
||||
ReleaseDC(hWnd, hdc);
|
||||
}
|
||||
}
|
||||
729
plugins/WindowExplorer/wnddlg.c
Normal file
729
plugins/WindowExplorer/wnddlg.c
Normal file
@@ -0,0 +1,729 @@
|
||||
/*
|
||||
* Process Hacker Window Explorer -
|
||||
* window tree dialog
|
||||
*
|
||||
* Copyright (C) 2016 dmex
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wndexp.h"
|
||||
#include "resource.h"
|
||||
#include <windowsx.h>
|
||||
|
||||
typedef struct _WINDOWS_CONTEXT
|
||||
{
|
||||
HWND TreeNewHandle;
|
||||
WE_WINDOW_TREE_CONTEXT TreeContext;
|
||||
WE_WINDOW_SELECTOR Selector;
|
||||
|
||||
PH_LAYOUT_MANAGER LayoutManager;
|
||||
|
||||
HWND HighlightingWindow;
|
||||
ULONG HighlightingWindowCount;
|
||||
} WINDOWS_CONTEXT, *PWINDOWS_CONTEXT;
|
||||
|
||||
VOID WepShowWindowsDialogCallback(
|
||||
_In_ PVOID Parameter
|
||||
);
|
||||
|
||||
INT_PTR CALLBACK WepWindowsDlgProc(
|
||||
_In_ HWND hwndDlg,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
);
|
||||
|
||||
static RECT MinimumSize = { -1, -1, -1, -1 };
|
||||
|
||||
VOID WeShowWindowsDialog(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ PWE_WINDOW_SELECTOR Selector
|
||||
)
|
||||
{
|
||||
PWINDOWS_CONTEXT context;
|
||||
|
||||
context = PhAllocate(sizeof(WINDOWS_CONTEXT));
|
||||
memset(context, 0, sizeof(WINDOWS_CONTEXT));
|
||||
memcpy(&context->Selector, Selector, sizeof(WE_WINDOW_SELECTOR));
|
||||
|
||||
ProcessHacker_Invoke(WE_PhMainWndHandle, WepShowWindowsDialogCallback, context);
|
||||
}
|
||||
|
||||
VOID WepShowWindowsDialogCallback(
|
||||
_In_ PVOID Parameter
|
||||
)
|
||||
{
|
||||
HWND hwnd;
|
||||
PWINDOWS_CONTEXT context = Parameter;
|
||||
|
||||
hwnd = CreateDialogParam(
|
||||
PluginInstance->DllBase,
|
||||
MAKEINTRESOURCE(IDD_WNDLIST),
|
||||
NULL,
|
||||
WepWindowsDlgProc,
|
||||
(LPARAM)context
|
||||
);
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
}
|
||||
|
||||
VOID WepDeleteWindowSelector(
|
||||
_In_ PWE_WINDOW_SELECTOR Selector
|
||||
)
|
||||
{
|
||||
switch (Selector->Type)
|
||||
{
|
||||
case WeWindowSelectorDesktop:
|
||||
PhDereferenceObject(Selector->Desktop.DesktopName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VOID WepFillWindowInfo(
|
||||
_In_ PWE_WINDOW_NODE Node
|
||||
)
|
||||
{
|
||||
HWND hwnd;
|
||||
ULONG threadId;
|
||||
ULONG processId;
|
||||
|
||||
hwnd = Node->WindowHandle;
|
||||
|
||||
GetClassName(hwnd, Node->WindowClass, sizeof(Node->WindowClass) / sizeof(WCHAR));
|
||||
Node->WindowText = PhGetWindowText(hwnd);
|
||||
|
||||
if (!Node->WindowText)
|
||||
Node->WindowText = PhReferenceEmptyString();
|
||||
|
||||
threadId = GetWindowThreadProcessId(hwnd, &processId);
|
||||
Node->ClientId.UniqueProcess = UlongToHandle(processId);
|
||||
Node->ClientId.UniqueThread = UlongToHandle(threadId);
|
||||
|
||||
Node->WindowVisible = !!IsWindowVisible(hwnd);
|
||||
Node->HasChildren = !!FindWindowEx(hwnd, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
VOID WepAddChildWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_In_opt_ PWE_WINDOW_NODE ParentNode,
|
||||
_In_ HWND hwnd
|
||||
)
|
||||
{
|
||||
PWE_WINDOW_NODE childNode;
|
||||
|
||||
childNode = WeAddWindowNode(Context);
|
||||
childNode->WindowHandle = hwnd;
|
||||
WepFillWindowInfo(childNode);
|
||||
|
||||
childNode->Node.Expanded = FALSE;
|
||||
|
||||
if (ParentNode)
|
||||
{
|
||||
// This is a child node.
|
||||
childNode->Parent = ParentNode;
|
||||
PhAddItemList(ParentNode->Children, childNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a root node.
|
||||
PhAddItemList(Context->NodeRootList, childNode);
|
||||
}
|
||||
}
|
||||
|
||||
VOID WepAddChildWindows(
|
||||
_In_ PWINDOWS_CONTEXT Context,
|
||||
_In_opt_ PWE_WINDOW_NODE ParentNode,
|
||||
_In_ HWND hwnd,
|
||||
_In_opt_ HANDLE FilterProcessId,
|
||||
_In_opt_ HANDLE FilterThreadId
|
||||
)
|
||||
{
|
||||
HWND childWindow = NULL;
|
||||
ULONG i = 0;
|
||||
|
||||
// We use FindWindowEx because EnumWindows doesn't return Metro app windows.
|
||||
// Set a reasonable limit to prevent infinite loops.
|
||||
while (i < 0x800 && (childWindow = FindWindowEx(hwnd, childWindow, NULL, NULL)))
|
||||
{
|
||||
ULONG processId;
|
||||
ULONG threadId;
|
||||
|
||||
threadId = GetWindowThreadProcessId(childWindow, &processId);
|
||||
|
||||
if (
|
||||
(!FilterProcessId || UlongToHandle(processId) == FilterProcessId) &&
|
||||
(!FilterThreadId || UlongToHandle(threadId) == FilterThreadId)
|
||||
)
|
||||
{
|
||||
WepAddChildWindowNode(&Context->TreeContext, ParentNode, childWindow);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK WepEnumDesktopWindowsProc(
|
||||
_In_ HWND hwnd,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PWINDOWS_CONTEXT context = (PWINDOWS_CONTEXT)lParam;
|
||||
|
||||
WepAddChildWindowNode(&context->TreeContext, NULL, hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID WepAddDesktopWindows(
|
||||
_In_ PWINDOWS_CONTEXT Context,
|
||||
_In_ PWSTR DesktopName
|
||||
)
|
||||
{
|
||||
HDESK desktopHandle;
|
||||
|
||||
if (desktopHandle = OpenDesktop(DesktopName, 0, FALSE, DESKTOP_ENUMERATE))
|
||||
{
|
||||
EnumDesktopWindows(desktopHandle, WepEnumDesktopWindowsProc, (LPARAM)Context);
|
||||
CloseDesktop(desktopHandle);
|
||||
}
|
||||
}
|
||||
|
||||
VOID WepRefreshWindows(
|
||||
_In_ PWINDOWS_CONTEXT Context
|
||||
)
|
||||
{
|
||||
TreeNew_SetRedraw(Context->TreeNewHandle, FALSE);
|
||||
WeClearWindowTree(&Context->TreeContext);
|
||||
TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
|
||||
switch (Context->Selector.Type)
|
||||
{
|
||||
case WeWindowSelectorAll:
|
||||
{
|
||||
PWE_WINDOW_NODE desktopNode;
|
||||
|
||||
desktopNode = WeAddWindowNode(&Context->TreeContext);
|
||||
desktopNode->WindowHandle = GetDesktopWindow();
|
||||
WepFillWindowInfo(desktopNode);
|
||||
|
||||
PhAddItemList(Context->TreeContext.NodeRootList, desktopNode);
|
||||
|
||||
WepAddChildWindows(Context, desktopNode, desktopNode->WindowHandle, NULL, NULL);
|
||||
|
||||
desktopNode->HasChildren = TRUE;
|
||||
desktopNode->Opened = TRUE;
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorThread:
|
||||
{
|
||||
WepAddChildWindows(Context, NULL, GetDesktopWindow(), NULL, Context->Selector.Thread.ThreadId);
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorProcess:
|
||||
{
|
||||
WepAddChildWindows(Context, NULL, GetDesktopWindow(), Context->Selector.Process.ProcessId, NULL);
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorDesktop:
|
||||
{
|
||||
WepAddDesktopWindows(Context, Context->Selector.Desktop.DesktopName->Buffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TreeNew_SetRedraw(Context->TreeNewHandle, TRUE);
|
||||
}
|
||||
|
||||
PPH_STRING WepGetWindowTitleForSelector(
|
||||
_In_ PWE_WINDOW_SELECTOR Selector
|
||||
)
|
||||
{
|
||||
switch (Selector->Type)
|
||||
{
|
||||
case WeWindowSelectorAll:
|
||||
{
|
||||
return PhCreateString(L"Windows - All");
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorThread:
|
||||
{
|
||||
return PhFormatString(L"Windows - Thread %lu", HandleToUlong(Selector->Thread.ThreadId));
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorProcess:
|
||||
{
|
||||
CLIENT_ID clientId;
|
||||
|
||||
clientId.UniqueProcess = Selector->Process.ProcessId;
|
||||
clientId.UniqueThread = NULL;
|
||||
|
||||
return PhConcatStrings2(L"Windows - ", PH_AUTO_T(PH_STRING, PhGetClientIdName(&clientId))->Buffer);
|
||||
}
|
||||
break;
|
||||
case WeWindowSelectorDesktop:
|
||||
{
|
||||
return PhFormatString(L"Windows - Desktop \"%s\"", Selector->Desktop.DesktopName->Buffer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return PhCreateString(L"Windows");
|
||||
}
|
||||
}
|
||||
|
||||
INT_PTR CALLBACK WepWindowsDlgProc(
|
||||
_In_ HWND hwndDlg,
|
||||
_In_ UINT uMsg,
|
||||
_In_ WPARAM wParam,
|
||||
_In_ LPARAM lParam
|
||||
)
|
||||
{
|
||||
PWINDOWS_CONTEXT context;
|
||||
|
||||
if (uMsg == WM_INITDIALOG)
|
||||
{
|
||||
context = (PWINDOWS_CONTEXT)lParam;
|
||||
SetProp(hwndDlg, L"Context", (HANDLE)context);
|
||||
}
|
||||
else
|
||||
{
|
||||
context = (PWINDOWS_CONTEXT)GetProp(hwndDlg, L"Context");
|
||||
|
||||
if (uMsg == WM_DESTROY)
|
||||
RemoveProp(hwndDlg, L"Context");
|
||||
}
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
PPH_STRING windowTitle;
|
||||
PH_RECTANGLE windowRectangle;
|
||||
|
||||
context->TreeNewHandle = GetDlgItem(hwndDlg, IDC_LIST);
|
||||
WeInitializeWindowTree(hwndDlg, context->TreeNewHandle, &context->TreeContext);
|
||||
|
||||
PhRegisterDialog(hwndDlg);
|
||||
|
||||
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
|
||||
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL, PH_ANCHOR_ALL);
|
||||
|
||||
if (MinimumSize.left == -1)
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = 160;
|
||||
rect.bottom = 100;
|
||||
MapDialogRect(hwndDlg, &rect);
|
||||
MinimumSize = rect;
|
||||
MinimumSize.left = 0;
|
||||
}
|
||||
|
||||
// Set up the window position and size.
|
||||
|
||||
windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION);
|
||||
windowRectangle.Size = PhGetScalableIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_SIZE, TRUE).Pair;
|
||||
PhAdjustRectangleToWorkingArea(NULL, &windowRectangle);
|
||||
|
||||
MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top,
|
||||
windowRectangle.Width, windowRectangle.Height, FALSE);
|
||||
|
||||
// Implement cascading by saving an offsetted rectangle.
|
||||
windowRectangle.Left += 20;
|
||||
windowRectangle.Top += 20;
|
||||
PhSetIntegerPairSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION, windowRectangle.Position);
|
||||
|
||||
windowTitle = PH_AUTO(WepGetWindowTitleForSelector(&context->Selector));
|
||||
SetWindowText(hwndDlg, windowTitle->Buffer);
|
||||
|
||||
WepRefreshWindows(context);
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
{
|
||||
PhSaveWindowPlacementToSetting(SETTING_NAME_WINDOWS_WINDOW_POSITION, SETTING_NAME_WINDOWS_WINDOW_SIZE, hwndDlg);
|
||||
|
||||
PhDeleteLayoutManager(&context->LayoutManager);
|
||||
PhUnregisterDialog(hwndDlg);
|
||||
|
||||
WeDeleteWindowTree(&context->TreeContext);
|
||||
WepDeleteWindowSelector(&context->Selector);
|
||||
PhFree(context);
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDCANCEL:
|
||||
//case IDOK:
|
||||
DestroyWindow(hwndDlg);
|
||||
break;
|
||||
case IDC_REFRESH:
|
||||
WepRefreshWindows(context);
|
||||
break;
|
||||
case ID_SHOWCONTEXTMENU:
|
||||
{
|
||||
POINT point;
|
||||
PWE_WINDOW_NODE *windows;
|
||||
ULONG numberOfWindows;
|
||||
PPH_EMENU menu;
|
||||
|
||||
point.x = (SHORT)LOWORD(lParam);
|
||||
point.y = (SHORT)HIWORD(lParam);
|
||||
|
||||
WeGetSelectedWindowNodes(
|
||||
&context->TreeContext,
|
||||
&windows,
|
||||
&numberOfWindows
|
||||
);
|
||||
|
||||
if (numberOfWindows != 0)
|
||||
{
|
||||
menu = PhCreateEMenu();
|
||||
PhLoadResourceEMenuItem(menu, PluginInstance->DllBase, MAKEINTRESOURCE(IDR_WINDOW), 0);
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_PROPERTIES, PH_EMENU_DEFAULT, PH_EMENU_DEFAULT);
|
||||
|
||||
if (numberOfWindows == 1)
|
||||
{
|
||||
WINDOWPLACEMENT placement = { sizeof(placement) };
|
||||
BYTE alpha;
|
||||
ULONG flags;
|
||||
ULONG i;
|
||||
ULONG id;
|
||||
|
||||
// State
|
||||
|
||||
GetWindowPlacement(windows[0]->WindowHandle, &placement);
|
||||
|
||||
if (placement.showCmd == SW_MINIMIZE)
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_MINIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
else if (placement.showCmd == SW_MAXIMIZE)
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_MAXIMIZE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
else if (placement.showCmd == SW_NORMAL)
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_RESTORE, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
|
||||
// Visible
|
||||
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_VISIBLE, PH_EMENU_CHECKED,
|
||||
(GetWindowLong(windows[0]->WindowHandle, GWL_STYLE) & WS_VISIBLE) ? PH_EMENU_CHECKED : 0);
|
||||
|
||||
// Enabled
|
||||
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_ENABLED, PH_EMENU_CHECKED,
|
||||
!(GetWindowLong(windows[0]->WindowHandle, GWL_STYLE) & WS_DISABLED) ? PH_EMENU_CHECKED : 0);
|
||||
|
||||
// Always on Top
|
||||
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_ALWAYSONTOP, PH_EMENU_CHECKED,
|
||||
(GetWindowLong(windows[0]->WindowHandle, GWL_EXSTYLE) & WS_EX_TOPMOST) ? PH_EMENU_CHECKED : 0);
|
||||
|
||||
// Opacity
|
||||
|
||||
if (GetLayeredWindowAttributes(windows[0]->WindowHandle, NULL, &alpha, &flags))
|
||||
{
|
||||
if (!(flags & LWA_ALPHA))
|
||||
alpha = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 255;
|
||||
}
|
||||
|
||||
if (alpha == 255)
|
||||
{
|
||||
id = ID_OPACITY_OPAQUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
id = 0;
|
||||
|
||||
// Due to integer division, we cannot use simple arithmetic to calculate which menu item to check.
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if (alpha == (BYTE)(255 * (i + 1) / 10))
|
||||
{
|
||||
id = ID_OPACITY_10 + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (id != 0)
|
||||
{
|
||||
PhSetFlagsEMenuItem(menu, id, PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK,
|
||||
PH_EMENU_CHECKED | PH_EMENU_RADIOCHECK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PhSetFlagsAllEMenuItems(menu, PH_EMENU_DISABLED, PH_EMENU_DISABLED);
|
||||
PhSetFlagsEMenuItem(menu, ID_WINDOW_COPY, PH_EMENU_DISABLED, 0);
|
||||
}
|
||||
|
||||
PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_SEND_COMMAND | PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y);
|
||||
PhDestroyEMenu(menu);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_BRINGTOFRONT:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
WINDOWPLACEMENT placement = { sizeof(placement) };
|
||||
|
||||
GetWindowPlacement(selectedNode->WindowHandle, &placement);
|
||||
|
||||
if (placement.showCmd == SW_MINIMIZE)
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_RESTORE);
|
||||
else
|
||||
SetForegroundWindow(selectedNode->WindowHandle);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_RESTORE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_RESTORE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_MINIMIZE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_MINIMIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_MAXIMIZE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_MAXIMIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_CLOSE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
PostMessage(selectedNode->WindowHandle, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_VISIBLE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
if (IsWindowVisible(selectedNode->WindowHandle))
|
||||
{
|
||||
selectedNode->WindowVisible = FALSE;
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_HIDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedNode->WindowVisible = TRUE;
|
||||
ShowWindowAsync(selectedNode->WindowHandle, SW_SHOW);
|
||||
}
|
||||
|
||||
PhInvalidateTreeNewNode(&selectedNode->Node, TN_CACHE_COLOR);
|
||||
TreeNew_InvalidateNode(context->TreeNewHandle, &selectedNode->Node);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_ENABLED:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
EnableWindow(selectedNode->WindowHandle, !IsWindowEnabled(selectedNode->WindowHandle));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_ALWAYSONTOP:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
LOGICAL topMost;
|
||||
|
||||
topMost = GetWindowLong(selectedNode->WindowHandle, GWL_EXSTYLE) & WS_EX_TOPMOST;
|
||||
SetWindowPos(selectedNode->WindowHandle, topMost ? HWND_NOTOPMOST : HWND_TOPMOST,
|
||||
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_OPACITY_10:
|
||||
case ID_OPACITY_20:
|
||||
case ID_OPACITY_30:
|
||||
case ID_OPACITY_40:
|
||||
case ID_OPACITY_50:
|
||||
case ID_OPACITY_60:
|
||||
case ID_OPACITY_70:
|
||||
case ID_OPACITY_80:
|
||||
case ID_OPACITY_90:
|
||||
case ID_OPACITY_OPAQUE:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
ULONG opacity;
|
||||
|
||||
opacity = ((ULONG)LOWORD(wParam) - ID_OPACITY_10) + 1;
|
||||
|
||||
if (opacity == 10)
|
||||
{
|
||||
// Remove the WS_EX_LAYERED bit since it is not needed.
|
||||
PhSetWindowExStyle(selectedNode->WindowHandle, WS_EX_LAYERED, 0);
|
||||
RedrawWindow(selectedNode->WindowHandle, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the WS_EX_LAYERED bit so opacity will work.
|
||||
PhSetWindowExStyle(selectedNode->WindowHandle, WS_EX_LAYERED, WS_EX_LAYERED);
|
||||
SetLayeredWindowAttributes(selectedNode->WindowHandle, 0, (BYTE)(255 * opacity / 10), LWA_ALPHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_HIGHLIGHT:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
if (context->HighlightingWindow)
|
||||
{
|
||||
if (context->HighlightingWindowCount & 1)
|
||||
WeInvertWindowBorder(context->HighlightingWindow);
|
||||
}
|
||||
|
||||
context->HighlightingWindow = selectedNode->WindowHandle;
|
||||
context->HighlightingWindowCount = 10;
|
||||
SetTimer(hwndDlg, 9, 100, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_GOTOTHREAD:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
PPH_PROCESS_ITEM processItem;
|
||||
PPH_PROCESS_PROPCONTEXT propContext;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
{
|
||||
if (processItem = PhReferenceProcessItem(selectedNode->ClientId.UniqueProcess))
|
||||
{
|
||||
if (propContext = PhCreateProcessPropContext(WE_PhMainWndHandle, processItem))
|
||||
{
|
||||
PhSetSelectThreadIdProcessPropContext(propContext, selectedNode->ClientId.UniqueThread);
|
||||
PhShowProcessProperties(propContext);
|
||||
PhDereferenceObject(propContext);
|
||||
}
|
||||
|
||||
PhDereferenceObject(processItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
PhShowError(hwndDlg, L"The process does not exist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_PROPERTIES:
|
||||
{
|
||||
PWE_WINDOW_NODE selectedNode;
|
||||
|
||||
if (selectedNode = WeGetSelectedWindowNode(&context->TreeContext))
|
||||
WeShowWindowProperties(hwndDlg, selectedNode->WindowHandle);
|
||||
}
|
||||
break;
|
||||
case ID_WINDOW_COPY:
|
||||
{
|
||||
PPH_STRING text;
|
||||
|
||||
text = PhGetTreeNewText(context->TreeNewHandle, 0);
|
||||
PhSetClipboardString(hwndDlg, &text->sr);
|
||||
PhDereferenceObject(text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_TIMER:
|
||||
{
|
||||
switch (wParam)
|
||||
{
|
||||
case 9:
|
||||
{
|
||||
WeInvertWindowBorder(context->HighlightingWindow);
|
||||
|
||||
if (--context->HighlightingWindowCount == 0)
|
||||
KillTimer(hwndDlg, 9);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
{
|
||||
PhLayoutManagerLayout(&context->LayoutManager);
|
||||
}
|
||||
break;
|
||||
case WM_SIZING:
|
||||
{
|
||||
PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
|
||||
}
|
||||
break;
|
||||
case WM_WE_PLUSMINUS:
|
||||
{
|
||||
PWE_WINDOW_NODE node = (PWE_WINDOW_NODE)lParam;
|
||||
|
||||
if (!node->Opened)
|
||||
{
|
||||
TreeNew_SetRedraw(context->TreeNewHandle, FALSE);
|
||||
WepAddChildWindows(context, node, node->WindowHandle, NULL, NULL);
|
||||
node->Opened = TRUE;
|
||||
TreeNew_SetRedraw(context->TreeNewHandle, TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
131
plugins/WindowExplorer/wndexp.h
Normal file
131
plugins/WindowExplorer/wndexp.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#ifndef WNDEXP_H
|
||||
#define WNDEXP_H
|
||||
|
||||
#include <phdk.h>
|
||||
#include "wndtree.h"
|
||||
|
||||
extern BOOLEAN IsHookClient;
|
||||
extern PPH_PLUGIN PluginInstance;
|
||||
|
||||
#define PLUGIN_NAME L"ProcessHacker.WindowExplorer"
|
||||
#define SETTING_NAME_SHOW_DESKTOP_WINDOWS (PLUGIN_NAME L".ShowDesktopWindows")
|
||||
#define SETTING_NAME_WINDOW_TREE_LIST_COLUMNS (PLUGIN_NAME L".WindowTreeListColumns")
|
||||
#define SETTING_NAME_WINDOWS_WINDOW_POSITION (PLUGIN_NAME L".WindowsWindowPosition")
|
||||
#define SETTING_NAME_WINDOWS_WINDOW_SIZE (PLUGIN_NAME L".WindowsWindowSize")
|
||||
|
||||
// hook
|
||||
|
||||
#define WE_SERVER_MESSAGE_NAME L"WE_ServerMessage"
|
||||
#define WE_SERVER_SHARED_SECTION_NAME L"\\BaseNamedObjects\\WeSharedSection"
|
||||
#define WE_SERVER_SHARED_SECTION_LOCK_NAME L"\\BaseNamedObjects\\WeSharedSectionLock"
|
||||
#define WE_SERVER_SHARED_SECTION_EVENT_NAME L"\\BaseNamedObjects\\WeSharedSectionEvent"
|
||||
#define WE_CLIENT_MESSAGE_TIMEOUT 2000
|
||||
|
||||
typedef struct _WE_HOOK_SHARED_DATA
|
||||
{
|
||||
ULONG MessageId;
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG_PTR WndProc;
|
||||
ULONG_PTR DlgProc;
|
||||
WNDCLASSEX ClassInfo;
|
||||
} c;
|
||||
} WE_HOOK_SHARED_DATA, *PWE_HOOK_SHARED_DATA;
|
||||
|
||||
VOID WeHookServerInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID WeHookServerUninitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN WeIsServerActive(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN WeLockServerSharedData(
|
||||
_Out_ PWE_HOOK_SHARED_DATA *Data
|
||||
);
|
||||
|
||||
VOID WeUnlockServerSharedData(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN WeSendServerRequest(
|
||||
_In_ HWND hWnd
|
||||
);
|
||||
|
||||
VOID WeHookClientInitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID WeHookClientUninitialization(
|
||||
VOID
|
||||
);
|
||||
|
||||
// wnddlg
|
||||
|
||||
typedef enum _WE_WINDOW_SELECTOR_TYPE
|
||||
{
|
||||
WeWindowSelectorAll,
|
||||
WeWindowSelectorProcess,
|
||||
WeWindowSelectorThread,
|
||||
WeWindowSelectorDesktop
|
||||
} WE_WINDOW_SELECTOR_TYPE;
|
||||
|
||||
typedef struct _WE_WINDOW_SELECTOR
|
||||
{
|
||||
WE_WINDOW_SELECTOR_TYPE Type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
HANDLE ProcessId;
|
||||
} Process;
|
||||
struct
|
||||
{
|
||||
HANDLE ThreadId;
|
||||
} Thread;
|
||||
struct
|
||||
{
|
||||
PPH_STRING DesktopName;
|
||||
} Desktop;
|
||||
};
|
||||
} WE_WINDOW_SELECTOR, *PWE_WINDOW_SELECTOR;
|
||||
|
||||
VOID WeShowWindowsDialog(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ PWE_WINDOW_SELECTOR Selector
|
||||
);
|
||||
|
||||
#define WM_WE_PLUSMINUS (WM_APP + 1)
|
||||
|
||||
// wndprp
|
||||
|
||||
VOID WeShowWindowProperties(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ HWND WindowHandle
|
||||
);
|
||||
|
||||
// utils
|
||||
|
||||
#define WE_PhMainWndHandle (*(HWND *)WeGetProcedureAddress("PhMainWndHandle"))
|
||||
#define WE_WindowsVersion (*(ULONG *)WeGetProcedureAddress("WindowsVersion"))
|
||||
|
||||
PVOID WeGetProcedureAddress(
|
||||
_In_ PSTR Name
|
||||
);
|
||||
|
||||
VOID WeFormatLocalObjectName(
|
||||
_In_ PWSTR OriginalName,
|
||||
_Inout_updates_(256) PWCHAR Buffer,
|
||||
_Out_ PUNICODE_STRING ObjectName
|
||||
);
|
||||
|
||||
VOID WeInvertWindowBorder(
|
||||
_In_ HWND hWnd
|
||||
);
|
||||
|
||||
#endif
|
||||
1207
plugins/WindowExplorer/wndprp.c
Normal file
1207
plugins/WindowExplorer/wndprp.c
Normal file
File diff suppressed because it is too large
Load Diff
461
plugins/WindowExplorer/wndtree.c
Normal file
461
plugins/WindowExplorer/wndtree.c
Normal file
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* Process Hacker Window Explorer -
|
||||
* window treelist
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "wndexp.h"
|
||||
#include "resource.h"
|
||||
|
||||
BOOLEAN WepWindowNodeHashtableEqualFunction(
|
||||
_In_ PVOID Entry1,
|
||||
_In_ PVOID Entry2
|
||||
);
|
||||
|
||||
ULONG WepWindowNodeHashtableHashFunction(
|
||||
_In_ PVOID Entry
|
||||
);
|
||||
|
||||
VOID WepDestroyWindowNode(
|
||||
_In_ PWE_WINDOW_NODE WindowNode
|
||||
);
|
||||
|
||||
BOOLEAN NTAPI WepWindowTreeNewCallback(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_opt_ PVOID Parameter1,
|
||||
_In_opt_ PVOID Parameter2,
|
||||
_In_opt_ PVOID Context
|
||||
);
|
||||
|
||||
VOID WeInitializeWindowTree(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Out_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
)
|
||||
{
|
||||
HWND hwnd;
|
||||
PPH_STRING settings;
|
||||
|
||||
memset(Context, 0, sizeof(WE_WINDOW_TREE_CONTEXT));
|
||||
|
||||
Context->NodeHashtable = PhCreateHashtable(
|
||||
sizeof(PWE_WINDOW_NODE),
|
||||
WepWindowNodeHashtableEqualFunction,
|
||||
WepWindowNodeHashtableHashFunction,
|
||||
100
|
||||
);
|
||||
Context->NodeList = PhCreateList(100);
|
||||
Context->NodeRootList = PhCreateList(30);
|
||||
|
||||
Context->ParentWindowHandle = ParentWindowHandle;
|
||||
Context->TreeNewHandle = TreeNewHandle;
|
||||
hwnd = TreeNewHandle;
|
||||
PhSetControlTheme(hwnd, L"explorer");
|
||||
|
||||
TreeNew_SetCallback(hwnd, WepWindowTreeNewCallback, Context);
|
||||
|
||||
PhAddTreeNewColumn(hwnd, WEWNTLC_CLASS, TRUE, L"Class", 180, PH_ALIGN_LEFT, 0, 0);
|
||||
PhAddTreeNewColumn(hwnd, WEWNTLC_HANDLE, TRUE, L"Handle", 70, PH_ALIGN_LEFT, 1, 0);
|
||||
PhAddTreeNewColumn(hwnd, WEWNTLC_TEXT, TRUE, L"Text", 220, PH_ALIGN_LEFT, 2, 0);
|
||||
PhAddTreeNewColumn(hwnd, WEWNTLC_THREAD, TRUE, L"Thread", 150, PH_ALIGN_LEFT, 3, 0);
|
||||
|
||||
TreeNew_SetTriState(hwnd, TRUE);
|
||||
TreeNew_SetSort(hwnd, 0, NoSortOrder);
|
||||
|
||||
settings = PhGetStringSetting(SETTING_NAME_WINDOW_TREE_LIST_COLUMNS);
|
||||
PhCmLoadSettings(hwnd, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
}
|
||||
|
||||
VOID WeDeleteWindowTree(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PPH_STRING settings;
|
||||
ULONG i;
|
||||
|
||||
settings = PhCmSaveSettings(Context->TreeNewHandle);
|
||||
PhSetStringSetting2(SETTING_NAME_WINDOW_TREE_LIST_COLUMNS, &settings->sr);
|
||||
PhDereferenceObject(settings);
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
WepDestroyWindowNode(Context->NodeList->Items[i]);
|
||||
|
||||
PhDereferenceObject(Context->NodeHashtable);
|
||||
PhDereferenceObject(Context->NodeList);
|
||||
PhDereferenceObject(Context->NodeRootList);
|
||||
}
|
||||
|
||||
BOOLEAN WepWindowNodeHashtableEqualFunction(
|
||||
_In_ PVOID Entry1,
|
||||
_In_ PVOID Entry2
|
||||
)
|
||||
{
|
||||
PWE_WINDOW_NODE windowNode1 = *(PWE_WINDOW_NODE *)Entry1;
|
||||
PWE_WINDOW_NODE windowNode2 = *(PWE_WINDOW_NODE *)Entry2;
|
||||
|
||||
return windowNode1->WindowHandle == windowNode2->WindowHandle;
|
||||
}
|
||||
|
||||
ULONG WepWindowNodeHashtableHashFunction(
|
||||
_In_ PVOID Entry
|
||||
)
|
||||
{
|
||||
return PhHashIntPtr((ULONG_PTR)(*(PWE_WINDOW_NODE *)Entry)->WindowHandle);
|
||||
}
|
||||
|
||||
PWE_WINDOW_NODE WeAddWindowNode(
|
||||
_Inout_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PWE_WINDOW_NODE windowNode;
|
||||
|
||||
windowNode = PhAllocate(sizeof(WE_WINDOW_NODE));
|
||||
memset(windowNode, 0, sizeof(WE_WINDOW_NODE));
|
||||
PhInitializeTreeNewNode(&windowNode->Node);
|
||||
|
||||
memset(windowNode->TextCache, 0, sizeof(PH_STRINGREF) * WEWNTLC_MAXIMUM);
|
||||
windowNode->Node.TextCache = windowNode->TextCache;
|
||||
windowNode->Node.TextCacheSize = WEWNTLC_MAXIMUM;
|
||||
|
||||
windowNode->Children = PhCreateList(1);
|
||||
|
||||
PhAddEntryHashtable(Context->NodeHashtable, &windowNode);
|
||||
PhAddItemList(Context->NodeList, windowNode);
|
||||
|
||||
TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
|
||||
return windowNode;
|
||||
}
|
||||
|
||||
PWE_WINDOW_NODE WeFindWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_In_ HWND WindowHandle
|
||||
)
|
||||
{
|
||||
WE_WINDOW_NODE lookupWindowNode;
|
||||
PWE_WINDOW_NODE lookupWindowNodePtr = &lookupWindowNode;
|
||||
PWE_WINDOW_NODE *windowNode;
|
||||
|
||||
lookupWindowNode.WindowHandle = WindowHandle;
|
||||
|
||||
windowNode = (PWE_WINDOW_NODE *)PhFindEntryHashtable(
|
||||
Context->NodeHashtable,
|
||||
&lookupWindowNodePtr
|
||||
);
|
||||
|
||||
if (windowNode)
|
||||
return *windowNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID WeRemoveWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_In_ PWE_WINDOW_NODE WindowNode
|
||||
)
|
||||
{
|
||||
ULONG index;
|
||||
|
||||
// Remove from hashtable/list and cleanup.
|
||||
|
||||
PhRemoveEntryHashtable(Context->NodeHashtable, &WindowNode);
|
||||
|
||||
if ((index = PhFindItemList(Context->NodeList, WindowNode)) != -1)
|
||||
PhRemoveItemList(Context->NodeList, index);
|
||||
|
||||
WepDestroyWindowNode(WindowNode);
|
||||
|
||||
TreeNew_NodesStructured(Context->TreeNewHandle);
|
||||
}
|
||||
|
||||
VOID WepDestroyWindowNode(
|
||||
_In_ PWE_WINDOW_NODE WindowNode
|
||||
)
|
||||
{
|
||||
PhDereferenceObject(WindowNode->Children);
|
||||
|
||||
if (WindowNode->WindowText) PhDereferenceObject(WindowNode->WindowText);
|
||||
|
||||
if (WindowNode->ThreadString) PhDereferenceObject(WindowNode->ThreadString);
|
||||
|
||||
PhFree(WindowNode);
|
||||
}
|
||||
|
||||
#define SORT_FUNCTION(Column) WepWindowTreeNewCompare##Column
|
||||
|
||||
#define BEGIN_SORT_FUNCTION(Column) static int __cdecl WepWindowTreeNewCompare##Column( \
|
||||
_In_ void *_context, \
|
||||
_In_ const void *_elem1, \
|
||||
_In_ const void *_elem2 \
|
||||
) \
|
||||
{ \
|
||||
PWE_WINDOW_NODE node1 = *(PWE_WINDOW_NODE *)_elem1; \
|
||||
PWE_WINDOW_NODE node2 = *(PWE_WINDOW_NODE *)_elem2; \
|
||||
int sortResult = 0;
|
||||
|
||||
#define END_SORT_FUNCTION \
|
||||
return PhModifySort(sortResult, ((PWE_WINDOW_TREE_CONTEXT)_context)->TreeNewSortOrder); \
|
||||
}
|
||||
|
||||
BEGIN_SORT_FUNCTION(Class)
|
||||
{
|
||||
sortResult = _wcsicmp(node1->WindowClass, node2->WindowClass);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(Handle)
|
||||
{
|
||||
sortResult = uintptrcmp((ULONG_PTR)node1->WindowHandle, (ULONG_PTR)node2->WindowHandle);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(Text)
|
||||
{
|
||||
sortResult = PhCompareString(node1->WindowText, node2->WindowText, TRUE);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BEGIN_SORT_FUNCTION(Thread)
|
||||
{
|
||||
sortResult = uintptrcmp((ULONG_PTR)node1->ClientId.UniqueProcess, (ULONG_PTR)node2->ClientId.UniqueProcess);
|
||||
|
||||
if (sortResult == 0)
|
||||
sortResult = uintptrcmp((ULONG_PTR)node1->ClientId.UniqueThread, (ULONG_PTR)node2->ClientId.UniqueThread);
|
||||
}
|
||||
END_SORT_FUNCTION
|
||||
|
||||
BOOLEAN NTAPI WepWindowTreeNewCallback(
|
||||
_In_ HWND hwnd,
|
||||
_In_ PH_TREENEW_MESSAGE Message,
|
||||
_In_opt_ PVOID Parameter1,
|
||||
_In_opt_ PVOID Parameter2,
|
||||
_In_opt_ PVOID Context
|
||||
)
|
||||
{
|
||||
PWE_WINDOW_TREE_CONTEXT context;
|
||||
PWE_WINDOW_NODE node;
|
||||
|
||||
context = Context;
|
||||
|
||||
switch (Message)
|
||||
{
|
||||
case TreeNewGetChildren:
|
||||
{
|
||||
PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
|
||||
|
||||
node = (PWE_WINDOW_NODE)getChildren->Node;
|
||||
|
||||
if (context->TreeNewSortOrder == NoSortOrder)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
getChildren->Children = (PPH_TREENEW_NODE *)context->NodeRootList->Items;
|
||||
getChildren->NumberOfChildren = context->NodeRootList->Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
getChildren->Children = (PPH_TREENEW_NODE *)node->Children->Items;
|
||||
getChildren->NumberOfChildren = node->Children->Count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
static PVOID sortFunctions[] =
|
||||
{
|
||||
SORT_FUNCTION(Class),
|
||||
SORT_FUNCTION(Handle),
|
||||
SORT_FUNCTION(Text),
|
||||
SORT_FUNCTION(Thread)
|
||||
};
|
||||
int (__cdecl *sortFunction)(void *, const void *, const void *);
|
||||
|
||||
if (context->TreeNewSortColumn < WEWNTLC_MAXIMUM)
|
||||
sortFunction = sortFunctions[context->TreeNewSortColumn];
|
||||
else
|
||||
sortFunction = NULL;
|
||||
|
||||
if (sortFunction)
|
||||
{
|
||||
qsort_s(context->NodeList->Items, context->NodeList->Count, sizeof(PVOID), sortFunction, context);
|
||||
}
|
||||
|
||||
getChildren->Children = (PPH_TREENEW_NODE *)context->NodeList->Items;
|
||||
getChildren->NumberOfChildren = context->NodeList->Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewIsLeaf:
|
||||
{
|
||||
PPH_TREENEW_IS_LEAF isLeaf = Parameter1;
|
||||
|
||||
node = (PWE_WINDOW_NODE)isLeaf->Node;
|
||||
|
||||
if (context->TreeNewSortOrder == NoSortOrder)
|
||||
isLeaf->IsLeaf = !node->HasChildren;
|
||||
else
|
||||
isLeaf->IsLeaf = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetCellText:
|
||||
{
|
||||
PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
|
||||
|
||||
node = (PWE_WINDOW_NODE)getCellText->Node;
|
||||
|
||||
switch (getCellText->Id)
|
||||
{
|
||||
case WEWNTLC_CLASS:
|
||||
PhInitializeStringRef(&getCellText->Text, node->WindowClass);
|
||||
break;
|
||||
case WEWNTLC_HANDLE:
|
||||
PhPrintPointer(node->WindowHandleString, node->WindowHandle);
|
||||
PhInitializeStringRef(&getCellText->Text, node->WindowHandleString);
|
||||
break;
|
||||
case WEWNTLC_TEXT:
|
||||
getCellText->Text = PhGetStringRef(node->WindowText);
|
||||
break;
|
||||
case WEWNTLC_THREAD:
|
||||
if (!node->ThreadString)
|
||||
node->ThreadString = PhGetClientIdName(&node->ClientId);
|
||||
getCellText->Text = PhGetStringRef(node->ThreadString);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
getCellText->Flags = TN_CACHE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewGetNodeColor:
|
||||
{
|
||||
PPH_TREENEW_GET_NODE_COLOR getNodeColor = Parameter1;
|
||||
|
||||
node = (PWE_WINDOW_NODE)getNodeColor->Node;
|
||||
|
||||
if (!node->WindowVisible)
|
||||
getNodeColor->ForeColor = RGB(0x55, 0x55, 0x55);
|
||||
|
||||
getNodeColor->Flags = TN_CACHE;
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewSortChanged:
|
||||
{
|
||||
TreeNew_GetSort(hwnd, &context->TreeNewSortColumn, &context->TreeNewSortOrder);
|
||||
// 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(context->ParentWindowHandle, WM_COMMAND, ID_WINDOW_COPY, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewLeftDoubleClick:
|
||||
{
|
||||
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_WINDOW_PROPERTIES, 0);
|
||||
}
|
||||
return TRUE;
|
||||
case TreeNewNodeExpanding:
|
||||
{
|
||||
SendMessage(context->ParentWindowHandle, WM_WE_PLUSMINUS, 0, (LPARAM)Parameter1);
|
||||
}
|
||||
return FALSE;
|
||||
case TreeNewContextMenu:
|
||||
{
|
||||
PPH_TREENEW_MOUSE_EVENT mouseEvent = Parameter1;
|
||||
|
||||
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_SHOWCONTEXTMENU, MAKELONG(mouseEvent->Location.x, mouseEvent->Location.y));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID WeClearWindowTree(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
WepDestroyWindowNode(Context->NodeList->Items[i]);
|
||||
|
||||
PhClearHashtable(Context->NodeHashtable);
|
||||
PhClearList(Context->NodeList);
|
||||
PhClearList(Context->NodeRootList);
|
||||
}
|
||||
|
||||
PWE_WINDOW_NODE WeGetSelectedWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
)
|
||||
{
|
||||
PWE_WINDOW_NODE windowNode = NULL;
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
{
|
||||
windowNode = Context->NodeList->Items[i];
|
||||
|
||||
if (windowNode->Node.Selected)
|
||||
return windowNode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID WeGetSelectedWindowNodes(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_Out_ PWE_WINDOW_NODE **Windows,
|
||||
_Out_ PULONG NumberOfWindows
|
||||
)
|
||||
{
|
||||
PPH_LIST list;
|
||||
ULONG i;
|
||||
|
||||
list = PhCreateList(2);
|
||||
|
||||
for (i = 0; i < Context->NodeList->Count; i++)
|
||||
{
|
||||
PWE_WINDOW_NODE node = Context->NodeList->Items[i];
|
||||
|
||||
if (node->Node.Selected)
|
||||
{
|
||||
PhAddItemList(list, node);
|
||||
}
|
||||
}
|
||||
|
||||
*Windows = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
|
||||
*NumberOfWindows = list->Count;
|
||||
|
||||
PhDereferenceObject(list);
|
||||
}
|
||||
90
plugins/WindowExplorer/wndtree.h
Normal file
90
plugins/WindowExplorer/wndtree.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef WNDTREE_H
|
||||
#define WNDTREE_H
|
||||
|
||||
#define WEWNTLC_CLASS 0
|
||||
#define WEWNTLC_HANDLE 1
|
||||
#define WEWNTLC_TEXT 2
|
||||
#define WEWNTLC_THREAD 3
|
||||
#define WEWNTLC_MAXIMUM 4
|
||||
|
||||
typedef struct _WE_WINDOW_NODE
|
||||
{
|
||||
PH_TREENEW_NODE Node;
|
||||
|
||||
struct _WE_WINDOW_NODE *Parent;
|
||||
PPH_LIST Children;
|
||||
|
||||
union
|
||||
{
|
||||
ULONG Flags;
|
||||
struct
|
||||
{
|
||||
ULONG HasChildren : 1;
|
||||
ULONG Opened : 1;
|
||||
ULONG WindowVisible : 1;
|
||||
ULONG Spare : 29;
|
||||
};
|
||||
};
|
||||
|
||||
PH_STRINGREF TextCache[WEWNTLC_MAXIMUM];
|
||||
|
||||
HWND WindowHandle;
|
||||
WCHAR WindowClass[64];
|
||||
PPH_STRING WindowText;
|
||||
CLIENT_ID ClientId;
|
||||
|
||||
WCHAR WindowHandleString[PH_PTR_STR_LEN_1];
|
||||
PPH_STRING ThreadString;
|
||||
} WE_WINDOW_NODE, *PWE_WINDOW_NODE;
|
||||
|
||||
typedef struct _WE_WINDOW_TREE_CONTEXT
|
||||
{
|
||||
HWND ParentWindowHandle;
|
||||
HWND TreeNewHandle;
|
||||
ULONG TreeNewSortColumn;
|
||||
PH_SORT_ORDER TreeNewSortOrder;
|
||||
|
||||
PPH_HASHTABLE NodeHashtable;
|
||||
PPH_LIST NodeList;
|
||||
PPH_LIST NodeRootList;
|
||||
} WE_WINDOW_TREE_CONTEXT, *PWE_WINDOW_TREE_CONTEXT;
|
||||
|
||||
VOID WeInitializeWindowTree(
|
||||
_In_ HWND ParentWindowHandle,
|
||||
_In_ HWND TreeNewHandle,
|
||||
_Out_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID WeDeleteWindowTree(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
);
|
||||
|
||||
PWE_WINDOW_NODE WeAddWindowNode(
|
||||
_Inout_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
);
|
||||
|
||||
PWE_WINDOW_NODE WeFindWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_In_ HWND WindowHandle
|
||||
);
|
||||
|
||||
VOID WeRemoveWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_In_ PWE_WINDOW_NODE WindowNode
|
||||
);
|
||||
|
||||
VOID WeClearWindowTree(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
);
|
||||
|
||||
PWE_WINDOW_NODE WeGetSelectedWindowNode(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context
|
||||
);
|
||||
|
||||
VOID WeGetSelectedWindowNodes(
|
||||
_In_ PWE_WINDOW_TREE_CONTEXT Context,
|
||||
_Out_ PWE_WINDOW_NODE **Windows,
|
||||
_Out_ PULONG NumberOfWindows
|
||||
);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user