go my file uploader

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

22
.gitattributes vendored Normal file
View File

@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=crlf
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

149
.gitignore vendored Normal file
View File

@ -0,0 +1,149 @@
#################
## Visual Studio
#################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover
## TODO: If you have NuGet Package Restore enabled, uncomment this
#packages/
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.db
# Visual Studio profiler
*.psess
*.vsp
# ReSharper is a .NET coding add-in
_ReSharper*
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
#Backup*/
UpgradeLog*.XML
############
## Windows
############
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
# Mac crap
.DS_Store
##########################
## Project specific rules
##########################
build/Installer/*.exe
ProcessHacker/include/phapprev.h
ProcessHacker/sdk/phapppub.h
plugins-extra/
sdk/
KProcessHacker/*.log
KProcessHacker/*.err
KProcessHacker/*.wrn
KProcessHacker/*/objchk_*
KProcessHacker/*/objfre_*
!plugins/SamplePlugin/bin/
plugins/SamplePlugin/bin/Debug32/
plugins/SamplePlugin/bin/Debug64/
plugins/SamplePlugin/bin/Release32/*
!plugins/SamplePlugin/bin/Release32/SamplePlugin.dll
plugins/SamplePlugin/bin/Release64/*
!plugins/SamplePlugin/bin/Release64/SamplePlugin.dll
!tools/CustomSignTool/bin/
tools/CustomSignTool/bin/Debug*/
tools/CustomSignTool/bin/Release*/*
!tools/CustomSignTool/bin/Release32/CustomSignTool.exe
!tools/CustomSignTool/bin/Release64/CustomSignTool.exe
!tools/fixlib/bin/
tools/fixlib/bin/Debug/
tools/fixlib/bin/Release/*
!tools/fixlib/bin/Release/fixlib.exe
!tools/GenerateHeader/GenerateHeader/bin/
tools/GenerateHeader/GenerateHeader/bin/Debug/
tools/GenerateHeader/GenerateHeader/bin/Release/*
!tools/GenerateHeader/GenerateHeader/bin/Release/GenerateHeader.exe
!tools/GenerateZw/GenerateZw/bin/
tools/GenerateZw/GenerateZw/bin/Debug/
tools/GenerateZw/GenerateZw/bin/Release/*
!tools/GenerateZw/GenerateZw/bin/Release/GenerateZw.exe
!tools/UpdateGitRevision/UpdateGitRevision/bin/
tools/UpdateGitRevision/UpdateGitRevision/bin/Debug/
tools/UpdateGitRevision/UpdateGitRevision/bin/Release/*
!tools/UpdateGitRevision/UpdateGitRevision/bin/Release/UpdateGitRevision.exe

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "plugins-extra"]
path = plugins-extra
url = https://github.com/processhacker2/plugins-extra

654
CHANGELOG.txt Normal file
View File

@ -0,0 +1,654 @@
Process Hacker
2.39
* HIGHLIGHTS:
* Improved compatibility with security and anti-cheat software
* Added ability to edit process environment variables
* Fixed .NET process detection
* OTHER CHANGES:
* Improved tooltip information for dllhost.exe
* Removed Terminator
* Updated DotNetTools plugin:
* Fixed .NET assembly tab performance issues
* Added extra .NET memory counters to the .NET performance tab
* Added "Show sizes in bytes" checkbox to the .NET performance tab
* Added right-click menu to the .NET assembly tab
* Updated ExtendedTools plugin:
* Fixed "No process" disk event bug
* Updated HardwareDevices plugin:
* Fixed incorrect drive letters
* Fixed drive letter and panel clipping issue
2.38
* HIGHLIGHTS:
* Added labels to indicate the maximum data point in each I/O graph
* Graph grids now scale correctly when resized
* Improved high DPI scaling
* Added exploit mitigation policy information to process properties (Windows 8 and above)
* Added File modified time and File size columns for processes and modules
* Added Key modified time column for services
* Clicking a tray icon now shows the pop-up UI (useful for touch-enabled devices)
* The NetAdapters plugin has been renamed to HardwareDevices
* This plugin shows network adapter and disk drive graphs
* If you are manually upgrading, please delete NetAdapters.dll from the plugins folder
* Updated UserNotes plugin:
* Added "Collapse by default" option for processes
* OTHER CHANGES:
* Added "Start when I log on" option
* Added "Not responding" text to tray icon rich pop-up for programs that are hung
* Added right-click menu and double-click action for environment variables
* Added dialog box to show long command line strings
* Added Time stamp column for processes
* Added -sysinfo command line parameter for opening System Information at startup
* Added 32x32 icons for high DPI displays
* Digital signature verification is now performed with very low I/O priority
* Improved performance when handling a large number of threads, modules or handles
* The pop-up UI no longer displays when double-clicking the tray icon
* Fixed ASLR state being shown as N/A in process properties
* Fixed multi monitor window placement bug
* Fixed handle enumeration bug affecting processes with PID >= 65536
* Fixed Interrupts being missing from the max CPU usage history
* Updated ToolStatus plugin:
* Added 32x32 icons for high DPI displays
* Fixed status bar crash
* NOTE:
* This release has significant internal code changes. Please make sure all plugins are up-to-date.
2.37
* HIGHLIGHTS:
* Updated for Windows 10
* The "Include CPU (and other) usage of children in collapsed processes" option now aggregates memory and I/O statistics
* Added regex search to "Find Handles or DLLs"
* Added process exit codes to log
* Fixed crash that occurred under some conditions when processes terminated
* OTHER CHANGES:
* Added warning when trying to search for handles when the system has too many handles open
* Upgraded to PCRE2
* Updated DotNetTools plugin:
* Rewrite of .NET Performance statistics and AppDomain enumeration
* Updated OnlineChecks plugin:
* Fixed virusscan.jotti.org uploader
* Updated NetAdapters plugin:
* Added adapter details window
* Updated ToolStatus plugin:
* Added CPU, Memory and I/O graphs to the toolbar (not enabled by default)
* Added toolbar and status bar customization, as well as a new theme
* Added option to auto-hide the main menu
* Updated UserNotes plugin:
* Added individual process highlighting support
2.36
* HIGHLIGHTS:
* New rich pop-up UI when hovering the cursor over a tray icon, showing the most active processes
* Completely new Memory tab for processes, with heap, stack and working set usage
* Process Hacker now takes 32-bit dumps of 32-bit processes on 64-bit Windows
* NOTE: When using the portable (.zip) release, the entire archive must be extracted
* Updated DotNetTools plugin:
* Process Hacker now displays managed stack traces for 32-bit .NET processes on 64-bit Windows
* Fixed inaccurate stack traces when clicking Refresh
* Added AppDomain column for threads in .NET programs
* OTHER CHANGES:
* Added customizable bytes per row setting for memory editor
* Dramatically faster handle listing and search when running without administrative privileges
* Improved accuracy and speed of symbol resolution, especially when new modules are loaded
* Added trigger and delayed start information to service list
* Added file information to service list tooltips
* Balloon tips for process/service notifications are now clickable
* Added handle names for unnamed File objects
* Added I/O Priority to tray icon process menu
* Added warning for users who attempt to start the 32-bit version on 64-bit Windows
* Updated ExtendedServices plugin:
* Added service protection and SID information
* Added auto-elevation when saving recovery information, triggers and other service settings
* Updated ExtendedTools plugin:
* Added tray icon mini info window support
* Improved automatic GPU node selection
* Updated UserNotes plugin:
* Added tray icon mini info window support
* Fixed a bug in phsvc that caused hangs when automatically elevating actions
* Fixed hang when viewing handle security for certain File objects
* Fixed lack of information on startup when using slower refresh intervals
* Fixed Read/Write Address crash
* Fixed service non-polling mode on Windows 8 and above
* Fixed file dialog crash in Windows PE environments
* Fixed string scanning false positive case
* Fixed process window detection for Modern UI apps
* Fixed handle list selection bug when disabling "Hide unnamed handles"
* NOTE:
* This release has significant internal code changes. Please make sure all plugins are up-to-date.
2.35
* NEW/IMPROVED:
* Added Load Time and Load Reason columns for modules (Windows 8 and above)
* Added handle names for Job and Section objects
* Added Read/Write Memory for Section objects (in process Handles tab)
* Added CF Guard (Control Flow Guard) column for processes and modules
* Added highlighting for AppContainer DLLs
* Added AppContainer and CF Guard image characteristics to peview
* Added Open Key and Open File Location menu items for services
* Set priority and I/O priority for multiple processes at once
* Support for up to 64 processors when setting process/thread affinity
* Updated ExtendedTools plugin:
* Added Disk and Network graphs for all processes
* Updated UserNotes plugin:
* Added ability to save I/O priority
* FIXED:
* Fixed memory editor copy bug
2.34
* NEW/IMPROVED:
* Proper Unicode support
* CPU and GPU graphs are displayed in a grid now (thanks pavel_kv!)
* Start Task Manager now elevates when necessary
* Better names for memory regions in Memory tab (for PEBs, TEBs, thread stacks)
* Added tooltip information for user-mode driver framework (UMDF) host processes
* Added option to reduce row height (set ThinRows to 1 in settings.xml)
* Added NetAdapters plugin: adds graphs for selected network adapters to the System Information window
* Updated ExtendedTools plugin:
* Added GPU graphs for all processes
* Can now use the search box in the Disk tab
* Improved kernel logger handling
* FIXED:
* Fixed touch scrolling
* Fixed EtwRegistration object names for 64-bit Windows 8.1
* Fixed tray icons being clipped in high DPI environments
* Fixed crash in memory editor
* Fixed multi monitor window placement bug
2.33
* NEW/IMPROVED:
* View digital signature information from process properties and peview
* Signatures for Windows 8 apps are now detected
* Improved file, key, process and thread handle properties
* Added DPI Awareness column
* Added new Windows 8.1 process protection information
* KProcessHacker is no longer needed for highlighting of GUI threads
* Added suspend count for threads on Windows 8.1
* Updated DotNetTools plugin:
* Improved .NET assembly enumeration timeout handling
* FIXED:
* Service start type and error control are never updated if modified outside of Process Hacker
2.32
* NOTE:
* All executable files are now signed.
* NEW/IMPROVED:
* Updated for Windows 8.1
* Added progress display for thread stacks
* Updated ExtendedServices plugin:
* Added new trigger data types
* Updated NetworkTools plugin:
* Updated UI
* Updated OnlineChecks plugin:
* Added file analyzed prompt
* FIXED:
* Fixed handling of long symbol names
* Fixed Run As preventing Windows 8 apps from starting
* Fixed console host information for Windows 8.1
* Fixed reflected processes not terminating on Windows 8.1
* Fixed CPU frequency on Windows 8.1
2.31
* NEW/IMPROVED:
* Updated ExtendedServices plugin:
* Fixed some bugs relating to Windows 8
* Updated OnlineChecks plugin:
* Added upload progress
* Updated UserNotes plugin:
* Fixed bug where process priorities were not actually saved
* FIXED:
* Fixed module list not updating properly
* DLL enumeration crash
2.30
* NEW/IMPROVED:
* Added "Icon click toggles visibility" option
* Re-enabled powerful process termination on 32-bit Windows 8
* Updated UserNotes plugin:
* Added ability to save process priority
* Added "Only for processes with the same command line" option for process comments
* FIXED:
* Fixed crash on CPUs without SSE2
2.29
* NEW/IMPROVED:
* Added App ID column for processes
* Added new ASLR information for Windows 8
* Added Restart to Boot Options and Hybrid Shutdown menu items for Windows 8
* Added ability to specify processes by their names and inject and unload DLLs in command line
* Removed 512 character limit when copying text
* Moved Terminator to Miscellaneous menu
* Updated default dbghelp.dll path for Windows SDK v8
* Updated ExtendedServices plugin:
* Added new triggers for Windows 8
* Fixed bug when restarting services
* Updated ExtendedTools plugin:
* Improved support for multiple GPUs (again)
* GPU column now respects "Include CPU usage of children" option
* Updated ToolStatus plugin:
* Fixed search box fonts
* Fixed controls not being properly hidden/removed from the window when disabled
* Updated WindowExplorer plugin:
* Fixed window list not displaying Modern UI windows
* FIXED:
* Fixed Load Count column sorting bug
* Fixed signature verification on Windows 8
* Fixed task scheduler information on Windows 8
* Fixed drag bug in tree list
* Fixed KProcessHacker bug affecting TmTx objects
* Fixed Run As feature on Windows 8
* Fixed bug where -settings parameter is not propagated
* Fixed tab key behavior on main window
* Fixed recognition of Modern UI windows
2.28
* NEW/IMPROVED:
* peview now resolves .lnk targets
* Fixed Ctrl+A for processes, services and network connections and added Ctrl+A for other windows
* Changed confirmation prompts to select the destructive action by default
* Updated DotNetTools plugin:
* Fixed inaccurate stack traces for certain .NET programs
* Updated ExtendedTools plugin:
* Fixed network graph scaling
* Updated ToolStatus plugin:
* Added search box
* Updated Updater plugin
* FIXED:
* Fixed Verification Status column sorting bug in module list
* Fixed rare System Information crash
* Fixed bug in opening process handles
* Fixed freezing when viewing stack traces of certain system threads
2.27
* NEW/IMPROVED:
* Updated OnlineChecks plugin:
* 2012-01-16: Updated VirusTotal uploader and added hash checking
* FIXED:
* Fixed Description column sorting bug
* Fixed notification icon bug
2.26
* NEW/IMPROVED:
* Added option to show Commit Charge in system information summary view
* Added -priority and -selectpid command line options
* Updated ExtendedTools plugin:
* Improved support for multiple GPUs
* FIXED:
* Fixed 100% CPU when starting on some machines
2.25
* NEW/IMPROVED:
* Improved CPU frequency calculation
* Updated ExtendedTools plugin:
* Added GPU node selection
* Fixed incorrect GPU usage calculation
* FIXED:
* Graph tooltip position with large cursors
* Fixed .NET process detection
* Fixed incorrect values in Bits column
2.24
* NOTE:
* This release has significant internal code changes. Please make sure all plugins are up-to-date.
* NEW/IMPROVED:
* Completely new system information window
* Added option to scroll to new processes
* Added option to hide driver services
* Added menu item to copy individual cells
* Improved module scanning
* Added Start Task Manager menu item
* Added Image base to peview
* Updated ExtendedTools plugin:
* Added support for new system information window
* Added Disk, Network and GPU tray icons
* Added support for custom fonts in the Disk tab
* Updated Updater plugin:
* Added download speed
* Added remaining time
* FIXED:
* Fixed retrieval of version information for certain files
* Fixed driver file names on Windows XP
* Fixed Run As Administrator when used with complex commands
2.23
* NEW/IMPROVED:
* Added display of token capabilities, user/device claims and security attributes
* Added ability to change token integrity levels
* Added Description column to service list
* Added option to reset all settings
* Made grid color darker
* Enabled multi-selection in the hidden processes window
* Added UserNotes plugin
* Updated ExtendedNotifications plugin:
* Added Growl support
* Updated ExtendedTools plugin:
* Added GPU monitoring
* Added rate columns for disk and network I/O
* FIXED:
* Fixed copying lists when plugin columns are enabled
* Freezing when viewing the tooltip for a process with a very long command line
* Disabled Hidden Processes feature on 64-bit systems
2.22
* NEW/IMPROVED:
* Added highlighting for metro style apps
* Added Package Name column
* Added package name to process tooltip
* Improved .NET process detection
* Updated OS Context column for Windows 8
* Updated ExtendedTools plugin:
* Updated disk monitoring for Windows 8
* Updated memory list information for Windows 8
* Updated WindowExplorer plugin:
* Fixed hook support for low integrity processes
* FIXED:
* Fixed memory leaks
* Fixed bug preventing Interrupts/DPCs from being shown as the max. CPU process on 64-bit systems
* Fixed DEP Status column on 64-bit systems
2.21
* NEW/IMPROVED:
* Added Private Bytes Delta, ASLR and Subsystem columns
* Added ASLR and Time Stamp columns to modules list
* Added check for debugger in Terminator
* FIXED:
* Fixed Show CPU Below 0.01 not respecting locale
* Fixed copying from network list
2.20
* NEW/IMPROVED:
* Added support for managed thread stacks on x64
* Added column selection for handle list
* Added CPU column to threads list
* Improved module detection
* Added Ideal Processor to Threads tab
* Added pool usage and minimum/maximum working set columns
* Implemented Properties button for Thread handles
* Set descending sort as the default for most numeric columns
* Extended header context menu
* Removed tooltip text truncation
* Improved cycle-based CPU usage calculation
* Set default KProcessHacker security level to only allow connections when Process Hacker is running as administrator.
See README.txt for instructions on how to restore the old behavior.
* Added Updater plugin
* Updated DotNetTools plugin:
* Added managed symbol resolution for thread stacks
* Updated ExtendedTools plugin:
* Added Disk tab
* Added Hard Faults, Hard Faults Delta and Peak Threads columns to process tree list
* Added Firewall Status column
* FIXED:
* Fixed file name resolution bug
* Save settings on shutdown/logoff
* Fixed state highlighting bug
* Fixed command line propagation for -elevate
* Fixed tree list mouse wheel handling
* Fixed saving network list
2.19
* NEW/IMPROVED:
* Added cycle-based CPU usage for Windows 7
* Added Show CPU Below 0.01
* Added OS Context column
* Rewrote graph drawing code for improved performance
* Optimized retrieval of cycle time and private working set information for Windows 7
* Added Open File Location to process context menu and reorganized some items
* Added checkboxes to Terminator
* FIXED:
* Crash when sorting by Time Stamp
* GDI handle leak in drag selection
2.18
* NEW/IMPROVED:
* Completely rewritten tree list control:
* Process Name column is now fixed to the left
* Tooltips for column headers
* Improved performance
* Bug fixes
* Added more process tree list columns
* Added Time stamp column to network list
* Date/time display is now swapped (so time is shown before date)
* Added W3 terminator test
* Added DotNetTools plugin
* Updated ExtendedServices plugin:
* Disabled editing of required privileges for drivers
* Updated ExtendedTools plugin:
* Added ETW columns for processes and network connections
* Updated OnlineChecks plugin:
* Added Comodo Instant Malware Analysis
* Updated WindowExplorer plugin:
* Fixed hook bugs
* FIXED:
* Fixed Run As This User
* Verification Status sorting
2.17
* NEW/IMPROVED:
* Added support for setting page priority
* Added elevation support for setting priority
* Added support for automatically using a settings file in the program directory (e.g. ProcessHacker.exe.settings.xml)
* Improved Run As mechanism
* Updated ExtendedServices plugin:
* Added support for editing triggers
* Added support for editing preshutdown time-out
* Added support for editing required privileges
* Added elevation support for restarting services
* Updated WindowExplorer plugin:
* Added more window properties
* FIXED:
* Handle leak
2.16
* NEW/IMPROVED:
* Updated WindowExplorer plugin
* PE viewer: Added version string to CLR tab
* PE viewer: Added display of delay imports
* PE viewer: Added Load Config tab
* Improved wait analysis
* Added arrows to the service list to indicate whether a service is running
* FIXED:
* Fixed the IPv6-related workaround causing crashes
* Incorrect handling of window positions
2.15
* NEW/IMPROVED:
* Updated ExtendedServices plugin
* Updated ToolStatus plugin
* Added DEP Status column
* Improved User Name column
* FIXED:
* Image file versions
* Workaround for an IPv6-related bug in Windows XP
* DPCs and Interrupts in System Information tooltips
* File dialog crash on Windows XP
* ExtendedTools plugin: WS Watch refresh bug
2.14
* NEW/IMPROVED:
* ExtendedServices plugin: Option to add a Services menu for processes
* Command line support for setting process priority and I/O priority
* Improved termination of explorer.exe
* FIXED:
* Icon should restore the main window if it is minimized
* System Information window crashes
* Hide Processes From Other Users and Hide Signed Processes settings are now saved
* Font selection on Windows XP
* ToolStatus plugin: Always on Top status being reset by Find Window
* Service-related crashes
* WindowExplorer plugin: sorting in tree list
* Process minidump creation with old versions of dbghelp.dll
2.13
* NEW/IMPROVED:
* Added copy support to PE viewer
* Added Connect Time, Disconnect Time and Last Input Time to session properties
* Added more working set counters to the Statistics tab
* FIXED:
* Column sort arrows
* CPU usage calculations
2.12
* NEW/IMPROVED:
* Updated KProcessHacker for Windows 7 SP1
* Added elevation support for more actions
* Added ability to disable plugins
* Updated ToolStatus plugin
* Added Remote Control for sessions
* More command line options
* FIXED:
* Memory leaks
* Run As issues with different sessions
2.11
* NEW/IMPROVED:
* Added WS Watch and other features to ExtendedTools plugin
* Added WindowExplorer plugin
* Properties for hidden processes
* Improved menus
* Debug console can now be closed without affecting the entire program
* FIXED:
* Always on Top issues
* Hang when setting DEP status of a terminating process
* Encoding bug in NetworkTools plugin
* LSA interfacing issues
* Creating dumps of self
2.10
* NEW/IMPROVED:
* KProcessHacker is now signed, so it works on 64-bit systems. Thank you to the ReactOS Foundation.
* Added Run As Limited User
* Added CPU, private bytes and I/O history columns
* Added font selection
* Slightly improved highlighting configuration
* FIXED:
* High DPI support
* Multi-monitor support in graph tooltips
* DEP status retrieval
* ExtendedTools plugin crash
* Notification icon menu crash
* Memory leaks
* Other small bug fixes
2.9
* NEW/IMPROVED:
* Added column selection for modules list
* Added wait analysis for 64-bit systems
* Added signature verification for modules
* Added ExtendedTools plugin (Vista and above only) with Disk and Network information
* Updated ExtendedNotifications plugin: added ability to log events to a file
* Updated ExtendedServices plugin: new tab on Vista and above
* Updated ToolStatus plugin: resolves ghost windows to hung windows
* Environment variables and current directory are now correctly shown for WOW64 processes
* I/O priority names are now used instead of numbers
* FIXED:
* Network list bug
* Memory leaks
2.8
* NEW/IMPROVED:
* Better service list (including column selection)
* Added Peak Handles
* Process tree sorting is now preserved
* Save works for services and network connections
* Pausing now works correctly with the Network tab
* Added option to display inclusive CPU usages for collapsed processes
* Added CLR tab to peview
* Added ability to destroy heaps
* Improved process tree list appearance
* Certain command line parameters are now propagated
* FIXED:
* Icon handling bugs
* Memory leaks
* Extended tooltips for WOW64 processes
2.7
* NEW/IMPROVED:
* Vastly improved startup time and lower memory usage
* Added Cycles and Cycles Delta columns
* Added option to disable address resolution for network connections
* Added Logon Time to session properties
* Added time stamp display to peview
* FIXED:
* ToolStatus layout problems
* .NET highlighting crashes
* Run As on Windows XP
2.6
* NEW/IMPROVED:
* Sorting for most lists is now much faster
* Hide Signed Processes option
* Added plugin for uploading files to online virus scanners
* Added Network tools plugin
* Updated ExtendedServices plugin
* PE viewer now verifies checksums
* Performance improvements
* FIXED:
* Fixed service handle leak
2.5
* NEW/IMPROVED:
* Unmap section views in Memory tab
* Plugin for extended service information (including recovery information, dependencies and dependents)
* FIXED:
* Critical bug for file dialogs on Windows XP
* Esc couldn't close Service Properties on open
* Small bug fixes
2.4
* NEW/IMPROVED:
* Better Run As behaviour
* Show Processes From All Users option
* Can now unmap section views
* Control over thread affinity
* Window Title and Window Status columns
* Plugin for filtering notifications
* Plugin for toolbar and status bar
* Performance improvements
* FIXED:
* Memory leak
* SbieSupport plugin on 64-bit
* Crash when running under certain conditions
* Memory case-insensitive filter
* Process parent association bug
* REMOVED:
* Process database
2.3
* NEW/IMPROVED:
* Can add processes to jobs
* Double-clicking in the system information graphs now opens information for the relevant process
* Setting I/O priority doesn't need KProcessHacker anymore
* Elevation for certain actions
* FIXED:
* HKCU key name resolution
* Network connection host resolution
* Information window resizing
* Log clearing
2.2
* NEW/IMPROVED:
* Plugins support
* Can now unload 32-bit modules on 64-bit systems
* Tasks are shown in tooltips for taskeng.exe/taskhost.exe processes
* Run As can now start processes elevated
* Handle count by type
* Process priorities in notification icon menu
* CSV export
* Relative start times
* FIXED:
* Run and Run As shortcuts
* Command line handling
* Process tree selection
2.1
* NEW/IMPROVED:
* Add Pause key shortcut to pause/resume updates
* Added Ctrl+Tab and Ctrl+Shift+Tab shortcuts
* Grid is a bit darker
* Checks for digital signatures and packing is now off by default and optional
* FIXED:
* MD5 calculation code for files was wrong
* Process record bugs
2.0
* First release in the Process Hacker 2.x branch.

132
COPYRIGHT.txt Normal file
View File

@ -0,0 +1,132 @@
== Process Hacker ==
Process Hacker is licensed under the GNU GPL v3, with exceptions. A full
copy of the license is provided in LICENSE.txt.
Copyright (C) 2009-2016 wj32 and various authors
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
== Mini-XML ==
Process Hacker uses Mini-XML licensed under the following terms:
The Mini-XML library and included programs are provided under the
terms of the GNU Library General Public License (LGPL) with the
following exceptions:
1. Static linking of applications to the Mini-XML library
does not constitute a derivative work and does not require
the author to provide source code for the application, use
the shared Mini-XML libraries, or link their applications
against a user-supplied version of Mini-XML.
If you link the application to a modified version of
Mini-XML, then the changes to Mini-XML must be provided
under the terms of the LGPL in sections 1, 2, and 4.
2. You do not have to provide a copy of the Mini-XML license
with programs that are linked to the Mini-XML library, nor
do you have to identify the Mini-XML license in your
program or documentation as required by section 6 of the
LGPL.
== PCRE ==
Process Hacker uses Perl-Compatible Regular Expressions licensed under the
following terms:
PCRE is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Release 8 of PCRE is distributed under the terms of the "BSD" licence, as
specified below.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the name of Google
Inc. nor the names of their contributors may be used to endorse or
promote products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
== MD5 ==
Process Hacker uses a MD5 implementation licensed under the following terms:
MD5 hash implementation and interface functions
Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
== SHA ==
Process Hacker uses a SHA implementation licensed under the following terms:
Copyright 2004 Filip Navara
Based on public domain SHA code by Steve Reid <steve@edmweb.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
== Natural order string comparison ==
Process Hacker uses "strnatcmp.c" licensed under the following terms:
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This code has been modified for Process Hacker.

1753
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

205
HACKING.md Normal file
View File

@ -0,0 +1,205 @@
## Building
Process Hacker must be built using a Microsoft C compiler. Do not attempt to use any other compiler or be prepared to spend a long time trying to fix things. The only tested IDE is Visual Studio 2015.
The Windows SDK 10 must be installed. To create a XP-compatible driver, KProcessHacker must be built using WDK v7, not the latest WDK.
## Conventions
### Names
* Functions, function parameters, and global variables use CamelCase.
* Local variables use lowerCamelCase.
* Structs, enums and unions use CAPS_WITH_UNDERSCORES.
All names must have an appropriate prefix (with some exceptions):
* "Ph" or "PH_" (structures) for public names.
* "Php" or "PHP_" for private names.
* Some variants such as "Pha".
* Private prefixes are created by appending "p" to the prefix. E.g. "Ph" -> "Php", "Pha" -> "Phap".
* Functions and global variables without a prefix must be declared "static".
* "static" names must not have a public prefix.
* Names with a private prefix do not have to be "static".
* Structures without a prefix must be declared in a ".c" file. Structures declared in a ".c" file may or may not have a prefix.
### Types
Unless used for the Win32 API, the standard types are:
* `BOOLEAN` for a 1 byte boolean, or `LOGICAL` for a 4 byte boolean.
* `UCHAR` for 1 byte.
* `SHORT`/`USHORT` for 2 bytes.
* `LONG`/`ULONG` for 4 bytes.
* `LONG64`/`ULONG64` for 8 bytes.
* `CHAR` for a 1 byte character.
* `WCHAR` for a 2 byte character.
* `PSTR` for a string of 1 byte characters.
* `PWSTR` for a string of 2 byte characters.
#### Booleans
Always use:
```
if (booleanVariable) // not "if (booleanVariable == TRUE)"
{
...
}
```
to test a boolean value.
### Annotations, qualifiers
* All functions use SAL annotations, such as `_In_`, `_Inout_`, `_Out_`, etc.
* Do not use `const`, unless obvious optimizations can be made by the compiler (e.g. inlining).
* Do not use `volatile` in definitions. Instead, cast to a volatile pointer when necessary.
### Function success indicators
There are three main types of indicators used:
* A `NTSTATUS` value is returned. The `NT_SUCCESS` macro checks if a status value indicates success.
* A `BOOLEAN` value is returned. `TRUE` indicates success.
* The result of the function is returned (e.g. a pointer). A special value (e.g. `NULL`) indicates failure.
Unless indicated, a function which fails is guaranteed not to modify any of its output parameters (`_Out_`, `_Out_opt_`, etc.).
For functions which are passed a callback function, it is not guaranteed that a failed function has not executed the callback function.
### Threads
Every thread start routine must have the following signature:
```
NTSTATUS NameOfRoutine(
_In_ PVOID Parameter
);
```
Thread creation is done through the `PhCreateThread` function.
### Collections
The collections available are summarized below:
Name | Use | Type
--------------------- | ----------------------- | ---------------
`PH_ARRAY` | Array | Non-intrusive
`PH_LIST` | Array | Non-intrusive
`LIST_ENTRY` | Doubly linked list | Intrusive
`SINGLE_LIST_ENTRY` | Singly linked list | Intrusive
`PH_POINTER_LIST` | Array | Non-intrusive
`LIST_ENTRY` | Stack | Intrusive
`SINGLE_LIST_ENTRY` | Stack | Intrusive
`LIST_ENTRY` | Queue | Intrusive
`RTL_AVL_TABLE` | Binary tree (AVL) | Non-intrusive
`PH_AVL_LINKS` | Binary tree (AVL) | Intrusive
`RTL_GENERIC_TABLE` | Binary tree (splay) | Non-intrusive
`PH_HASHTABLE` | Hashtable | Non-intrusive
`PH_HASH_ENTRY` | Hashtable | Intrusive
`PH_CIRCULAR_BUFFER` | Circular buffer | Non-intrusive
### Synchronization
The queued lock should be used for all synchronization, due to its small size and good performance. Although the queued lock is a reader-writer lock, it can be used as a mutex simply by using the exclusive acquire/release functions.
Events can be used through `PH_EVENT`. This object does not create a kernel event object until needed, and testing its state is very fast.
Rundown protection is available through `PH_RUNDOWN_PROTECT`.
Condition variables are available using the queued lock. Simply declare and initialize a queued lock variable, and use the `PhPulse(All)Condition` and `PhWaitForCondition` functions.
Custom locking with low overhead can be built using the wake event, built on the queued lock. Test one or more conditions in a loop and use `PhQueueWakeEvent`/`PhWaitForWakeEvent` to block. When a condition is modified use `PhSetWakeEvent` to wake waiters. If after calling `PhQueueWakeEvent` it is determined that no blocking should occur, use `PhSetWakeEvent`.
### Exceptions (SEH)
The only method of error handling used in Process Hacker is the return value (`NTSTATUS`, `BOOLEAN`, etc.). Exceptions are used for exceptional situations which cannot easily be recovered from (e.g. a lock acquire function fails to block, or an object has a negative reference count.
Exceptions to this rule include:
* `PhAllocate`, which raises an exception if it fails to allocate. Checking the return value of each allocation to increase reliability is not worth the extra effort involved, as failed allocations are very rare.
* `PhProbeAddress`, which raises an exception if an address lies outside of a specified range. Raising an exception makes it possible to conduct multiple checks in one SEH block.
* `STATUS_NOT_IMPLEMENTED` exceptions triggered by code paths which should not be reached, purely due to programmer error. `assert(FALSE)` could also be used in this case.
### Memory management
Use `PhAllocate`/`PhFree` to allocate/free memory. For complex objects, use the reference counting system.
There is semi-automatic reference counting available in the form of auto-dereference pools (similar to Apple's `NSAutoreleasePool`s). Use the `PhAutoDereferenceObject` to add an object to the thread's pool, and the object will be dereferenced at an unspecified time in the future. However, the object is guaranteed to not be dereferenced while the current function is executing.
Referencing an object is necessary whenever a pointer to the object is stored in a globally visible location or passed to another thread. In most other cases, referencing is not necessary.
All objects passed to functions must have a guaranteed reference for the duration of that call. One mistake is to keep a reference which could be destroyed in a window procedure, and to use that reference implicitly inside the window procedure. Messages can still be pumped (e.g. dialog boxes) while the window procedure is executing, so the window procedure must reference the object as soon as possible.
### Names (2)
#### Object creation/deletion
* Allocate means allocate memory without initialization.
* Create means allocate memory for an object and initialize the object.
* Free can be used for objects created with Allocate or Create functions.
* Destroy can also be used for objects created with Create functions.
* Initialize means initialize an object with caller-supplied storage.
* Delete is paired with Initialize and does not free the object as it was allocated by the caller.
* Create is used when objects are being created through the reference counting system.
Examples:
* `PhAllocateFromFreeList`/`PhFreeToFreeList`
* `PhCreateFileDialog`/`PhFreeFileDialog`
* `PhInitializeWorkQueue`/`PhDeleteWorkQueue`
* `PhCreateString`/`PhDereferenceObject`
#### Element counts
* Length specifies the length in bytes. E.g. `PhCreateString` requires the length to be specified in bytes.
* Count specifies the length in elements. E.g. `PhSubstring` requires the length to be specified in characters.
* Index specifies the index in elements. E.g. `PhSubstring` requires the index to be specified in characters.
When null terminated strings are being written to output, the return count, if any, must be specified as the number of characters written including the null terminator.
### Strings
Strings use the `PH_STRING` type, managed by reference counting. To create a string object from a null-terminated string:
```
PPH_STRING myString = PhCreateString(L"My string");
wprintf(
L"My string is \"%s\", and uses %Iu bytes.\n",
myString->Buffer,
myString->Length
);
```
All string objects have an embedded length (always in bytes), and the string is additionally null-terminated for compatibility reasons.
String objects must be treated as immutable unless a string object is created and modified before the pointer is shared with any other functions or stored in any global variables. This exception applies only when creating a string using `PhCreateString` or `PhCreateStringEx`.
Strings can be concatenated with `PhConcatStrings`:
```
PPH_STRING newString;
newString = PhConcatStrings(
4,
L"My first string, ",
L"My second string, ",
aStringFromSomewhere,
L"My fourth string."
);
```
Another version concatenates two strings:
```
PPH_STRING newString;
newString = PhConcatStrings2(
L"My first string, ",
L"My second string."
);
```
Strings can be formatted:
```
PPH_STRING newString;
newString = PhFormatString(
L"%d: %s, %#x",
100,
L"test",
0xff
);
```
### Tips
* Use !! to "cast" to a boolean.

View File

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Win8 Debug|Win32">
<Configuration>Win8 Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|Win32">
<Configuration>Win8 Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Debug|x64">
<Configuration>Win8 Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Win8 Release|x64">
<Configuration>Win8 Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F4853009-C5D2-4A25-BE4D-BB0D9F84E2FF}</ProjectGuid>
<TemplateGuid>{dd38f7fc-d7bd-488b-9242-7d8754cde80d}</TemplateGuid>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration>Win8 Debug</Configuration>
<Platform Condition="'$(Platform)' == ''">Win32</Platform>
</PropertyGroup>
<PropertyGroup Label="Globals">
<RootNamespace>KProcessHacker</RootNamespace>
<VCTargetsPath Condition="'$(VCTargetsPath11)' != '' and '$(VisualStudioVersion)' == '11.0'">$(VCTargetsPath11)</VCTargetsPath>
</PropertyGroup>
<PropertyGroup Label="PropertySheets">
<PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
<DriverType>WDM</DriverType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'" Label="Configuration">
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">
<OutDir>$(ProjectDir)bin\$(Configuration) $(PlatformArchitecture)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Configuration) $(PlatformArchitecture)\</IntDir>
<TargetName>kprocesshacker</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">
<OutDir>$(ProjectDir)bin\$(Configuration) $(PlatformArchitecture)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Configuration) $(PlatformArchitecture)\</IntDir>
<TargetName>kprocesshacker</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
<OutDir>$(ProjectDir)bin\$(Configuration) $(PlatformArchitecture)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Configuration) $(PlatformArchitecture)\</IntDir>
<TargetName>kprocesshacker</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
<OutDir>$(ProjectDir)bin\$(Configuration) $(PlatformArchitecture)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Configuration) $(PlatformArchitecture)\</IntDir>
<TargetName>kprocesshacker</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>../phnt/include;../phlib/include;include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>KPH_CONFIG_CLEAN;_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>../phnt/include;../phlib/include;include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>KPH_CONFIG_CLEAN;_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>../phnt/include;../phlib/include;include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>KPH_CONFIG_CLEAN;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>../phnt/include;../phlib/include;include;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>KPH_CONFIG_CLEAN;_WIN64;_AMD64_;AMD64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<FilesToPackage Include="$(TargetPath)" />
<FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="devctrl.c" />
<ClCompile Include="dyndata.c" />
<ClCompile Include="dynimp.c" />
<ClCompile Include="main.c" />
<ClCompile Include="object.c" />
<ClCompile Include="process.c" />
<ClCompile Include="qrydrv.c" />
<ClCompile Include="thread.c" />
<ClCompile Include="vm.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resource.rc" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\dyndata.h" />
<ClInclude Include="include\kph.h" />
<ClInclude Include="include\ntfill.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,66 @@
<?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;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Driver Files">
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
<Extensions>inf;inv;inx;mof;mc;</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="devctrl.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dyndata.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dynimp.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="object.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="process.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="qrydrv.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thread.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="vm.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resource.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\dyndata.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\kph.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\ntfill.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
!INCLUDE $(NTMAKEENV)\makefile.def

View File

@ -0,0 +1,7 @@
!IF 0
This builds a clean version of KProcessHacker suitable for driver signing.
!ENDIF
!include ..\sources.inc

566
KProcessHacker/devctrl.c Normal file
View File

@ -0,0 +1,566 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
NTSTATUS KphDispatchDeviceControl(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION stackLocation;
PFILE_OBJECT fileObject;
PKPH_CLIENT client;
PVOID originalInput;
ULONG inputLength;
ULONG ioControlCode;
KPROCESSOR_MODE accessMode;
UCHAR capturedInput[16 * sizeof(ULONG_PTR)];
PVOID capturedInputPointer;
#define VERIFY_INPUT_LENGTH \
do { \
/* Ensure at compile time that our local buffer fits this particular call. */ \
C_ASSERT(sizeof(*input) <= sizeof(capturedInput)); \
\
if (inputLength != sizeof(*input)) \
{ \
status = STATUS_INFO_LENGTH_MISMATCH; \
goto ControlEnd; \
} \
} while (0)
stackLocation = IoGetCurrentIrpStackLocation(Irp);
fileObject = stackLocation->FileObject;
client = fileObject->FsContext;
originalInput = stackLocation->Parameters.DeviceIoControl.Type3InputBuffer;
inputLength = stackLocation->Parameters.DeviceIoControl.InputBufferLength;
ioControlCode = stackLocation->Parameters.DeviceIoControl.IoControlCode;
accessMode = Irp->RequestorMode;
// Make sure we have a client object.
if (!client)
{
status = STATUS_INTERNAL_ERROR;
goto ControlEnd;
}
// Enforce signature requirement if necessary.
if ((ioControlCode != KPH_GETFEATURES && ioControlCode != KPH_VERIFYCLIENT) &&
(KphParameters.SecurityLevel == KphSecuritySignatureCheck ||
KphParameters.SecurityLevel == KphSecuritySignatureAndPrivilegeCheck) &&
!client->VerificationSucceeded)
{
status = STATUS_ACCESS_DENIED;
goto ControlEnd;
}
// Make sure we actually have input if the input length is non-zero.
if (inputLength != 0 && !originalInput)
{
status = STATUS_INVALID_BUFFER_SIZE;
goto ControlEnd;
}
// Make sure the caller isn't giving us a huge buffer. If they are, it can't be correct because
// we have a compile-time check that makes sure our buffer can store the arguments for all the
// calls.
if (inputLength > sizeof(capturedInput))
{
status = STATUS_INVALID_BUFFER_SIZE;
goto ControlEnd;
}
// Probe and capture the input buffer.
if (accessMode != KernelMode)
{
__try
{
ProbeForRead(originalInput, inputLength, sizeof(UCHAR));
memcpy(capturedInput, originalInput, inputLength);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
goto ControlEnd;
}
}
else
{
memcpy(capturedInput, originalInput, inputLength);
}
capturedInputPointer = capturedInput; // avoid casting below
switch (ioControlCode)
{
case KPH_GETFEATURES:
{
struct
{
PULONG Features;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiGetFeatures(
input->Features,
accessMode
);
}
break;
case KPH_VERIFYCLIENT:
{
struct
{
PVOID CodeAddress;
PVOID Signature;
ULONG SignatureSize;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
if (accessMode == UserMode)
{
status = KpiVerifyClient(
input->CodeAddress,
input->Signature,
input->SignatureSize,
client
);
}
else
{
status = STATUS_UNSUCCESSFUL;
}
}
break;
case KPH_RETRIEVEKEY:
{
struct
{
KPH_KEY_LEVEL KeyLevel;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
if (accessMode == UserMode)
{
status = KphRetrieveKeyViaApc(
client,
input->KeyLevel,
Irp
);
}
else
{
status = STATUS_UNSUCCESSFUL;
}
}
break;
case KPH_OPENPROCESS:
{
struct
{
PHANDLE ProcessHandle;
ACCESS_MASK DesiredAccess;
PCLIENT_ID ClientId;
KPH_KEY Key;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenProcess(
input->ProcessHandle,
input->DesiredAccess,
input->ClientId,
input->Key,
client,
accessMode
);
}
break;
case KPH_OPENPROCESSTOKEN:
{
struct
{
HANDLE ProcessHandle;
ACCESS_MASK DesiredAccess;
PHANDLE TokenHandle;
KPH_KEY Key;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenProcessToken(
input->ProcessHandle,
input->DesiredAccess,
input->TokenHandle,
input->Key,
client,
accessMode
);
}
break;
case KPH_OPENPROCESSJOB:
{
struct
{
HANDLE ProcessHandle;
ACCESS_MASK DesiredAccess;
PHANDLE JobHandle;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenProcessJob(
input->ProcessHandle,
input->DesiredAccess,
input->JobHandle,
accessMode
);
}
break;
case KPH_TERMINATEPROCESS:
{
struct
{
HANDLE ProcessHandle;
NTSTATUS ExitStatus;
KPH_KEY Key;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiTerminateProcess(
input->ProcessHandle,
input->ExitStatus,
input->Key,
client,
accessMode
);
}
break;
case KPH_READVIRTUALMEMORYUNSAFE:
{
struct
{
HANDLE ProcessHandle;
PVOID BaseAddress;
PVOID Buffer;
SIZE_T BufferSize;
PSIZE_T NumberOfBytesRead;
KPH_KEY Key;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiReadVirtualMemoryUnsafe(
input->ProcessHandle,
input->BaseAddress,
input->Buffer,
input->BufferSize,
input->NumberOfBytesRead,
input->Key,
client,
accessMode
);
}
break;
case KPH_QUERYINFORMATIONPROCESS:
{
struct
{
HANDLE ProcessHandle;
KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
PVOID ProcessInformation;
ULONG ProcessInformationLength;
PULONG ReturnLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiQueryInformationProcess(
input->ProcessHandle,
input->ProcessInformationClass,
input->ProcessInformation,
input->ProcessInformationLength,
input->ReturnLength,
accessMode
);
}
break;
case KPH_SETINFORMATIONPROCESS:
{
struct
{
HANDLE ProcessHandle;
KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass;
PVOID ProcessInformation;
ULONG ProcessInformationLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiSetInformationProcess(
input->ProcessHandle,
input->ProcessInformationClass,
input->ProcessInformation,
input->ProcessInformationLength,
accessMode
);
}
break;
case KPH_OPENTHREAD:
{
struct
{
PHANDLE ThreadHandle;
ACCESS_MASK DesiredAccess;
PCLIENT_ID ClientId;
KPH_KEY Key;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenThread(
input->ThreadHandle,
input->DesiredAccess,
input->ClientId,
input->Key,
client,
accessMode
);
}
break;
case KPH_OPENTHREADPROCESS:
{
struct
{
HANDLE ThreadHandle;
ACCESS_MASK DesiredAccess;
PHANDLE ProcessHandle;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenThreadProcess(
input->ThreadHandle,
input->DesiredAccess,
input->ProcessHandle,
accessMode
);
}
break;
case KPH_CAPTURESTACKBACKTRACETHREAD:
{
struct
{
HANDLE ThreadHandle;
ULONG FramesToSkip;
ULONG FramesToCapture;
PVOID *BackTrace;
PULONG CapturedFrames;
PULONG BackTraceHash;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiCaptureStackBackTraceThread(
input->ThreadHandle,
input->FramesToSkip,
input->FramesToCapture,
input->BackTrace,
input->CapturedFrames,
input->BackTraceHash,
accessMode
);
}
break;
case KPH_QUERYINFORMATIONTHREAD:
{
struct
{
HANDLE ThreadHandle;
KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
PVOID ThreadInformation;
ULONG ThreadInformationLength;
PULONG ReturnLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiQueryInformationThread(
input->ThreadHandle,
input->ThreadInformationClass,
input->ThreadInformation,
input->ThreadInformationLength,
input->ReturnLength,
accessMode
);
}
break;
case KPH_SETINFORMATIONTHREAD:
{
struct
{
HANDLE ThreadHandle;
KPH_THREAD_INFORMATION_CLASS ThreadInformationClass;
PVOID ThreadInformation;
ULONG ThreadInformationLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiSetInformationThread(
input->ThreadHandle,
input->ThreadInformationClass,
input->ThreadInformation,
input->ThreadInformationLength,
accessMode
);
}
break;
case KPH_ENUMERATEPROCESSHANDLES:
{
struct
{
HANDLE ProcessHandle;
PVOID Buffer;
ULONG BufferLength;
PULONG ReturnLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiEnumerateProcessHandles(
input->ProcessHandle,
input->Buffer,
input->BufferLength,
input->ReturnLength,
accessMode
);
}
break;
case KPH_QUERYINFORMATIONOBJECT:
{
struct
{
HANDLE ProcessHandle;
HANDLE Handle;
KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
PVOID ObjectInformation;
ULONG ObjectInformationLength;
PULONG ReturnLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiQueryInformationObject(
input->ProcessHandle,
input->Handle,
input->ObjectInformationClass,
input->ObjectInformation,
input->ObjectInformationLength,
input->ReturnLength,
accessMode
);
}
break;
case KPH_SETINFORMATIONOBJECT:
{
struct
{
HANDLE ProcessHandle;
HANDLE Handle;
KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass;
PVOID ObjectInformation;
ULONG ObjectInformationLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiSetInformationObject(
input->ProcessHandle,
input->Handle,
input->ObjectInformationClass,
input->ObjectInformation,
input->ObjectInformationLength,
accessMode
);
}
break;
case KPH_OPENDRIVER:
{
struct
{
PHANDLE DriverHandle;
ACCESS_MASK DesiredAccess;
POBJECT_ATTRIBUTES ObjectAttributes;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiOpenDriver(
input->DriverHandle,
input->DesiredAccess,
input->ObjectAttributes,
accessMode
);
}
break;
case KPH_QUERYINFORMATIONDRIVER:
{
struct
{
HANDLE DriverHandle;
DRIVER_INFORMATION_CLASS DriverInformationClass;
PVOID DriverInformation;
ULONG DriverInformationLength;
PULONG ReturnLength;
} *input = capturedInputPointer;
VERIFY_INPUT_LENGTH;
status = KpiQueryInformationDriver(
input->DriverHandle,
input->DriverInformationClass,
input->DriverInformation,
input->DriverInformationLength,
input->ReturnLength,
accessMode
);
}
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
ControlEnd:
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

1
KProcessHacker/dirs Normal file
View File

@ -0,0 +1 @@
DIRS=clean

167
KProcessHacker/dyndata.c Normal file
View File

@ -0,0 +1,167 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
#define _DYNDATA_PRIVATE
#include <dyndata.h>
#define C_2sTo4(x) ((unsigned int)(signed short)(x))
NTSTATUS KphpLoadDynamicConfiguration(
__in PVOID Buffer,
__in ULONG Length
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KphDynamicDataInitialization)
#pragma alloc_text(PAGE, KphReadDynamicDataParameters)
#pragma alloc_text(PAGE, KphpLoadDynamicConfiguration)
#endif
NTSTATUS KphDynamicDataInitialization(
VOID
)
{
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
// Get Windows version information.
KphDynOsVersionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
status = RtlGetVersion((PRTL_OSVERSIONINFOW)&KphDynOsVersionInfo);
return status;
}
NTSTATUS KphReadDynamicDataParameters(
__in_opt HANDLE KeyHandle
)
{
NTSTATUS status;
UNICODE_STRING valueName;
PKEY_VALUE_PARTIAL_INFORMATION info;
ULONG resultLength;
PAGED_CODE();
if (!KeyHandle)
return STATUS_UNSUCCESSFUL;
RtlInitUnicodeString(&valueName, L"DynamicConfiguration");
status = ZwQueryValueKey(
KeyHandle,
&valueName,
KeyValuePartialInformation,
NULL,
0,
&resultLength
);
if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL)
{
// Unexpected status; fail now.
return STATUS_UNSUCCESSFUL;
}
info = ExAllocatePoolWithTag(PagedPool, resultLength, 'ThpK');
if (!info)
return STATUS_INSUFFICIENT_RESOURCES;
status = ZwQueryValueKey(
KeyHandle,
&valueName,
KeyValuePartialInformation,
info,
resultLength,
&resultLength
);
if (NT_SUCCESS(status))
{
if (info->Type == REG_BINARY)
status = KphpLoadDynamicConfiguration(info->Data, info->DataLength);
else
status = STATUS_OBJECT_TYPE_MISMATCH;
if (!NT_SUCCESS(status))
dprintf("Unable to load dynamic configuration: 0x%x\n", status);
}
ExFreePoolWithTag(info, 'ThpK');
return status;
}
NTSTATUS KphpLoadDynamicConfiguration(
__in PVOID Buffer,
__in ULONG Length
)
{
PKPH_DYN_CONFIGURATION config;
ULONG i;
PKPH_DYN_PACKAGE package;
PAGED_CODE();
config = Buffer;
if (Length < FIELD_OFFSET(KPH_DYN_CONFIGURATION, Packages))
return STATUS_INVALID_PARAMETER;
if (config->Version != KPH_DYN_CONFIGURATION_VERSION)
return STATUS_INVALID_PARAMETER;
if (config->NumberOfPackages > KPH_DYN_MAXIMUM_PACKAGES)
return STATUS_INVALID_PARAMETER;
if (Length < FIELD_OFFSET(KPH_DYN_CONFIGURATION, Packages) + config->NumberOfPackages * sizeof(KPH_DYN_PACKAGE))
return STATUS_INVALID_PARAMETER;
dprintf("Loading dynamic configuration with %u package(s)\n", config->NumberOfPackages);
for (i = 0; i < config->NumberOfPackages; i++)
{
package = &config->Packages[i];
if (package->MajorVersion == KphDynOsVersionInfo.dwMajorVersion &&
package->MinorVersion == KphDynOsVersionInfo.dwMinorVersion &&
(package->ServicePackMajor == (USHORT)-1 || package->ServicePackMajor == KphDynOsVersionInfo.wServicePackMajor) &&
(package->BuildNumber == (USHORT)-1 || package->BuildNumber == KphDynOsVersionInfo.dwBuildNumber))
{
dprintf("Found matching package at index %u for Windows %u.%u\n", i, package->MajorVersion, package->MinorVersion);
KphDynNtVersion = package->ResultingNtVersion;
KphDynEgeGuid = C_2sTo4(package->StructData.EgeGuid);
KphDynEpObjectTable = C_2sTo4(package->StructData.EpObjectTable);
KphDynEreGuidEntry = C_2sTo4(package->StructData.EreGuidEntry);
KphDynHtHandleContentionEvent = C_2sTo4(package->StructData.HtHandleContentionEvent);
KphDynOtName = C_2sTo4(package->StructData.OtName);
KphDynOtIndex = C_2sTo4(package->StructData.OtIndex);
KphDynObDecodeShift = C_2sTo4(package->StructData.ObDecodeShift);
KphDynObAttributesShift = C_2sTo4(package->StructData.ObAttributesShift);
return STATUS_SUCCESS;
}
}
return STATUS_NOT_FOUND;
}

60
KProcessHacker/dynimp.c Normal file
View File

@ -0,0 +1,60 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
#include <dyndata.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KphGetSystemRoutineAddress)
#pragma alloc_text(PAGE, KphDynamicImport)
#endif
/**
* Dynamically imports routines.
*/
VOID KphDynamicImport(
VOID
)
{
PAGED_CODE();
NOTHING;
}
/**
* Retrieves the address of a function exported by NTOS or HAL.
*
* \param SystemRoutineName The name of the function.
*
* \return The address of the function, or NULL if the function could
* not be found.
*/
PVOID KphGetSystemRoutineAddress(
__in PWSTR SystemRoutineName
)
{
UNICODE_STRING systemRoutineName;
PAGED_CODE();
RtlInitUnicodeString(&systemRoutineName, SystemRoutineName);
return MmGetSystemRoutineAddress(&systemRoutineName);
}

View File

@ -0,0 +1,47 @@
#ifndef DYNDATA_H
#define DYNDATA_H
#ifdef EXT
#undef EXT
#endif
#ifdef _DYNDATA_PRIVATE
#define EXT
#define OFFDEFAULT = -1
#else
#define EXT extern
#define OFFDEFAULT
#endif
EXT ULONG KphDynNtVersion;
EXT RTL_OSVERSIONINFOEXW KphDynOsVersionInfo;
// Structures
// Ege: ETW_GUID_ENTRY
// Ep: EPROCESS
// Ere: ETW_REG_ENTRY
// Et: ETHREAD
// Ht: HANDLE_TABLE
// Oh: OBJECT_HEADER
// Ot: OBJECT_TYPE
// Oti: OBJECT_TYPE_INITIALIZER, offset measured from an OBJECT_TYPE
// ObDecodeShift: shift value in ObpDecodeObject
// ObAttributesShift: shift value in ObpGetHandleAttributes
EXT ULONG KphDynEgeGuid OFFDEFAULT;
EXT ULONG KphDynEpObjectTable OFFDEFAULT;
EXT ULONG KphDynEreGuidEntry OFFDEFAULT;
EXT ULONG KphDynHtHandleContentionEvent OFFDEFAULT;
EXT ULONG KphDynOtName OFFDEFAULT;
EXT ULONG KphDynOtIndex OFFDEFAULT;
EXT ULONG KphDynObDecodeShift OFFDEFAULT;
EXT ULONG KphDynObAttributesShift OFFDEFAULT;
NTSTATUS KphDynamicDataInitialization(
VOID
);
NTSTATUS KphReadDynamicDataParameters(
__in_opt HANDLE KeyHandle
);
#endif

View File

@ -0,0 +1,365 @@
#ifndef KPH_H
#define KPH_H
#include <ntifs.h>
#define PHNT_MODE PHNT_MODE_KERNEL
#include <phnt.h>
#include <ntfill.h>
#include <bcrypt.h>
#include <kphapi.h>
// Debugging
#ifdef DBG
#define dprintf(Format, ...) DbgPrint("KProcessHacker: " Format, __VA_ARGS__)
#else
#define dprintf
#endif
typedef struct _KPH_CLIENT
{
struct
{
ULONG VerificationPerformed : 1;
ULONG VerificationSucceeded : 1;
ULONG KeysGenerated : 1;
ULONG SpareBits : 29;
};
FAST_MUTEX StateMutex;
NTSTATUS VerificationStatus;
PVOID VerifiedProcess; // EPROCESS (for equality checking only - do not access contents)
HANDLE VerifiedProcessId;
PVOID VerifiedRangeBase;
SIZE_T VerifiedRangeSize;
// Level 1 and 2 secret keys
FAST_MUTEX KeyBackoffMutex;
KPH_KEY L1Key;
KPH_KEY L2Key;
} KPH_CLIENT, *PKPH_CLIENT;
typedef struct _KPH_PARAMETERS
{
KPH_SECURITY_LEVEL SecurityLevel;
} KPH_PARAMETERS, *PKPH_PARAMETERS;
// main
extern ULONG KphFeatures;
extern KPH_PARAMETERS KphParameters;
NTSTATUS KpiGetFeatures(
__out PULONG Features,
__in KPROCESSOR_MODE AccessMode
);
// devctrl
__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH KphDispatchDeviceControl;
NTSTATUS KphDispatchDeviceControl(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
);
// dynimp
VOID KphDynamicImport(
VOID
);
PVOID KphGetSystemRoutineAddress(
__in PWSTR SystemRoutineName
);
// object
PHANDLE_TABLE KphReferenceProcessHandleTable(
__in PEPROCESS Process
);
VOID KphDereferenceProcessHandleTable(
__in PEPROCESS Process
);
VOID KphUnlockHandleTableEntry(
__in PHANDLE_TABLE HandleTable,
__in PHANDLE_TABLE_ENTRY HandleTableEntry
);
NTSTATUS KpiEnumerateProcessHandles(
__in HANDLE ProcessHandle,
__out_bcount(BufferLength) PVOID Buffer,
__in_opt ULONG BufferLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphQueryNameObject(
__in PVOID Object,
__out_bcount(BufferLength) POBJECT_NAME_INFORMATION Buffer,
__in ULONG BufferLength,
__out PULONG ReturnLength
);
NTSTATUS KphQueryNameFileObject(
__in PFILE_OBJECT FileObject,
__out_bcount(BufferLength) POBJECT_NAME_INFORMATION Buffer,
__in ULONG BufferLength,
__out PULONG ReturnLength
);
NTSTATUS KpiQueryInformationObject(
__in HANDLE ProcessHandle,
__in HANDLE Handle,
__in KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
__out_bcount(ObjectInformationLength) PVOID ObjectInformation,
__in ULONG ObjectInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiSetInformationObject(
__in HANDLE ProcessHandle,
__in HANDLE Handle,
__in KPH_OBJECT_INFORMATION_CLASS ObjectInformationClass,
__in_bcount(ObjectInformationLength) PVOID ObjectInformation,
__in ULONG ObjectInformationLength,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphOpenNamedObject(
__out PHANDLE ObjectHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode
);
// process
NTSTATUS KpiOpenProcess(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in PCLIENT_ID ClientId,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiOpenProcessToken(
__in HANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE TokenHandle,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiOpenProcessJob(
__in HANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE JobHandle,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiTerminateProcess(
__in HANDLE ProcessHandle,
__in NTSTATUS ExitStatus,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiQueryInformationProcess(
__in HANDLE ProcessHandle,
__in KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiSetInformationProcess(
__in HANDLE ProcessHandle,
__in KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
__in_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__in KPROCESSOR_MODE AccessMode
);
// qrydrv
NTSTATUS KpiOpenDriver(
__out PHANDLE DriverHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiQueryInformationDriver(
__in HANDLE DriverHandle,
__in DRIVER_INFORMATION_CLASS DriverInformationClass,
__out_bcount(DriverInformationLength) PVOID DriverInformation,
__in ULONG DriverInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
);
// thread
NTSTATUS KpiOpenThread(
__out PHANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__in PCLIENT_ID ClientId,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiOpenThreadProcess(
__in HANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE ProcessHandle,
__in KPROCESSOR_MODE AccessMode
);
ULONG KphCaptureStackBackTrace(
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__in_opt ULONG Flags,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG BackTraceHash
);
NTSTATUS KphCaptureStackBackTraceThread(
__in PETHREAD Thread,
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG CapturedFrames,
__out_opt PULONG BackTraceHash,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiCaptureStackBackTraceThread(
__in HANDLE ThreadHandle,
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG CapturedFrames,
__out_opt PULONG BackTraceHash,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiQueryInformationThread(
__in HANDLE ThreadHandle,
__in KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
__out_bcount(ProcessInformationLength) PVOID ThreadInformation,
__in ULONG ThreadInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
);
NTSTATUS KpiSetInformationThread(
__in HANDLE ThreadHandle,
__in KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
__in_bcount(ThreadInformationLength) PVOID ThreadInformation,
__in ULONG ThreadInformationLength,
__in KPROCESSOR_MODE AccessMode
);
// util
VOID KphFreeCapturedUnicodeString(
__in PUNICODE_STRING CapturedUnicodeString
);
NTSTATUS KphCaptureUnicodeString(
__in PUNICODE_STRING UnicodeString,
__out PUNICODE_STRING CapturedUnicodeString
);
NTSTATUS KphEnumerateSystemModules(
__out PRTL_PROCESS_MODULES *Modules
);
NTSTATUS KphValidateAddressForSystemModules(
__in PVOID Address,
__in SIZE_T Length
);
NTSTATUS KphGetProcessMappedFileName(
__in HANDLE ProcessHandle,
__in PVOID BaseAddress,
__out PUNICODE_STRING *FileName
);
// verify
NTSTATUS KphHashFile(
__in PUNICODE_STRING FileName,
__out PVOID *Hash,
__out PULONG HashSize
);
NTSTATUS KphVerifyFile(
__in PUNICODE_STRING FileName,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize
);
VOID KphVerifyClient(
__inout PKPH_CLIENT Client,
__in PVOID CodeAddress,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize
);
NTSTATUS KpiVerifyClient(
__in PVOID CodeAddress,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize,
__in PKPH_CLIENT Client
);
VOID KphGenerateKeysClient(
__inout PKPH_CLIENT Client
);
NTSTATUS KphRetrieveKeyViaApc(
__inout PKPH_CLIENT Client,
__in KPH_KEY_LEVEL KeyLevel,
__inout PIRP Irp
);
NTSTATUS KphValidateKey(
__in KPH_KEY_LEVEL RequiredKeyLevel,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
// vm
NTSTATUS KphCopyVirtualMemory(
__in PEPROCESS FromProcess,
__in PVOID FromAddress,
__in PEPROCESS ToProcess,
__in PVOID ToAddress,
__in SIZE_T BufferLength,
__in KPROCESSOR_MODE AccessMode,
__out PSIZE_T ReturnLength
);
NTSTATUS KpiReadVirtualMemoryUnsafe(
__in_opt HANDLE ProcessHandle,
__in PVOID BaseAddress,
__out_bcount(BufferSize) PVOID Buffer,
__in SIZE_T BufferSize,
__out_opt PSIZE_T NumberOfBytesRead,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
);
#endif

View File

@ -0,0 +1,351 @@
#ifndef NTFILL_H
#define NTFILL_H
extern ULONG KphDynNtVersion;
extern ULONG KphDynObDecodeShift;
extern ULONG KphDynObAttributesShift;
// EX
typedef struct _EX_PUSH_LOCK_WAIT_BLOCK *PEX_PUSH_LOCK_WAIT_BLOCK;
NTKERNELAPI
VOID
FASTCALL
ExfUnblockPushLock(
__inout PEX_PUSH_LOCK PushLock,
__inout_opt PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock
);
typedef struct _HANDLE_TABLE_ENTRY
{
union
{
PVOID Object;
ULONG ObAttributes;
ULONG_PTR Value;
};
union
{
ACCESS_MASK GrantedAccess;
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
typedef struct _HANDLE_TABLE HANDLE_TABLE, *PHANDLE_TABLE;
typedef BOOLEAN (NTAPI *PEX_ENUM_HANDLE_CALLBACK_61)(
__inout PHANDLE_TABLE_ENTRY HandleTableEntry,
__in HANDLE Handle,
__in PVOID Context
);
// since WIN8
typedef BOOLEAN (NTAPI *PEX_ENUM_HANDLE_CALLBACK)(
__in PHANDLE_TABLE HandleTable,
__inout PHANDLE_TABLE_ENTRY HandleTableEntry,
__in HANDLE Handle,
__in PVOID Context
);
NTKERNELAPI
BOOLEAN
NTAPI
ExEnumHandleTable(
__in PHANDLE_TABLE HandleTable,
__in PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
__inout PVOID Context,
__out_opt PHANDLE Handle
);
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__out_bcount_opt(SystemInformationLength) PVOID SystemInformation,
__in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength
);
// IO
extern POBJECT_TYPE *IoDriverObjectType;
// KE
typedef enum _KAPC_ENVIRONMENT
{
OriginalApcEnvironment,
AttachedApcEnvironment,
CurrentApcEnvironment,
InsertApcEnvironment
} KAPC_ENVIRONMENT, *PKAPC_ENVIRONMENT;
typedef VOID (NTAPI *PKNORMAL_ROUTINE)(
__in PVOID NormalContext,
__in PVOID SystemArgument1,
__in PVOID SystemArgument2
);
typedef VOID KKERNEL_ROUTINE(
__in PRKAPC Apc,
__inout PKNORMAL_ROUTINE *NormalRoutine,
__inout PVOID *NormalContext,
__inout PVOID *SystemArgument1,
__inout PVOID *SystemArgument2
);
typedef KKERNEL_ROUTINE (NTAPI *PKKERNEL_ROUTINE);
typedef VOID (NTAPI *PKRUNDOWN_ROUTINE)(
__in PRKAPC Apc
);
NTKERNELAPI
VOID
NTAPI
KeInitializeApc(
__out PRKAPC Apc,
__in PRKTHREAD Thread,
__in KAPC_ENVIRONMENT Environment,
__in PKKERNEL_ROUTINE KernelRoutine,
__in_opt PKRUNDOWN_ROUTINE RundownRoutine,
__in_opt PKNORMAL_ROUTINE NormalRoutine,
__in_opt KPROCESSOR_MODE ProcessorMode,
__in_opt PVOID NormalContext
);
NTKERNELAPI
BOOLEAN
NTAPI
KeInsertQueueApc(
__inout PRKAPC Apc,
__in_opt PVOID SystemArgument1,
__in_opt PVOID SystemArgument2,
__in KPRIORITY Increment
);
// MM
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwQueryVirtualMemory(
__in HANDLE ProcessHandle,
__in PVOID BaseAddress,
__in MEMORY_INFORMATION_CLASS MemoryInformationClass,
__out_bcount(MemoryInformationLength) PVOID MemoryInformation,
__in SIZE_T MemoryInformationLength,
__out_opt PSIZE_T ReturnLength
);
// OB
// These definitions are no longer correct, but they produce correct results.
#define OBJ_PROTECT_CLOSE 0x00000001
#define OBJ_HANDLE_ATTRIBUTES (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
// This attribute is now stored in the GrantedAccess field.
#define ObpAccessProtectCloseBit 0x2000000
#define ObpDecodeGrantedAccess(Access) \
((Access) & ~ObpAccessProtectCloseBit)
FORCEINLINE PVOID ObpDecodeObject(PVOID Object)
{
#ifdef _M_X64
if (KphDynNtVersion >= PHNT_WIN8)
{
if (KphDynObDecodeShift != -1)
return (PVOID)(((LONG_PTR)Object >> KphDynObDecodeShift) & ~(ULONG_PTR)0xf);
else
return NULL;
}
else
{
return (PVOID)((ULONG_PTR)Object & ~OBJ_HANDLE_ATTRIBUTES);
}
#else
return (PVOID)((ULONG_PTR)Object & ~OBJ_HANDLE_ATTRIBUTES);
#endif
}
FORCEINLINE ULONG ObpGetHandleAttributes(PHANDLE_TABLE_ENTRY HandleTableEntry)
{
#ifdef _M_X64
if (KphDynNtVersion >= PHNT_WIN8)
{
if (KphDynObAttributesShift != -1)
return (ULONG)(HandleTableEntry->Value >> KphDynObAttributesShift) & 0x3;
else
return 0;
}
else
{
return (HandleTableEntry->ObAttributes & (OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)) |
((HandleTableEntry->GrantedAccess & ObpAccessProtectCloseBit) ? OBJ_PROTECT_CLOSE : 0);
}
#else
return (HandleTableEntry->ObAttributes & (OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)) |
((HandleTableEntry->GrantedAccess & ObpAccessProtectCloseBit) ? OBJ_PROTECT_CLOSE : 0);
#endif
}
typedef struct _OBJECT_CREATE_INFORMATION OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION;
// This is incorrect as of Windows 8.1, but the size of the structure is still correct.
typedef struct _OBJECT_HEADER
{
LONG PointerCount;
union
{
LONG HandleCount;
PVOID NextToFree;
};
POBJECT_TYPE Type;
UCHAR NameInfoOffset;
UCHAR HandleInfoOffset;
UCHAR QuotaInfoOffset;
UCHAR Flags;
union
{
POBJECT_CREATE_INFORMATION ObjectCreateInfo;
PVOID QuotaBlockCharged;
};
PVOID SecurityDescriptor;
QUAD Body;
} OBJECT_HEADER, *POBJECT_HEADER;
#define OBJECT_TO_OBJECT_HEADER(Object) CONTAINING_RECORD((Object), OBJECT_HEADER, Body)
NTKERNELAPI
POBJECT_TYPE
NTAPI
ObGetObjectType(
__in PVOID Object
);
NTKERNELAPI
NTSTATUS
NTAPI
ObOpenObjectByName(
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE PreviousMode,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in PVOID ParseContext,
__out PHANDLE Handle
);
NTKERNELAPI
NTSTATUS
NTAPI
ObSetHandleAttributes(
__in HANDLE Handle,
__in POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
__in KPROCESSOR_MODE PreviousMode
);
NTKERNELAPI
NTSTATUS
ObCloseHandle(
__in HANDLE Handle,
__in KPROCESSOR_MODE PreviousMode
);
// PS
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwQueryInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwSetInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__in_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
ZwQueryInformationThread(
__in HANDLE ThreadHandle,
__in THREADINFOCLASS ThreadInformationClass,
__out_bcount(ThreadInformationLength) PVOID ThreadInformation,
__in ULONG ThreadInformationLength,
__out_opt PULONG ReturnLength
);
NTKERNELAPI
NTSTATUS
NTAPI
PsLookupProcessThreadByCid(
__in PCLIENT_ID ClientId,
__out_opt PEPROCESS *Process,
__out PETHREAD *Thread
);
NTKERNELAPI
PVOID
NTAPI
PsGetThreadWin32Thread(
__in PETHREAD Thread
);
typedef struct _EJOB *PEJOB;
extern POBJECT_TYPE *PsJobType;
NTKERNELAPI
PEJOB
NTAPI
PsGetProcessJob(
__in PEPROCESS Process
);
NTKERNELAPI
NTSTATUS
NTAPI
PsAcquireProcessExitSynchronization(
__in PEPROCESS Process
);
NTKERNELAPI
VOID
NTAPI
PsReleaseProcessExitSynchronization(
__in PEPROCESS Process
);
// RTL
// Sensible limit that may or may not correspond to the actual Windows value.
#define MAX_STACK_DEPTH 256
#define RTL_WALK_USER_MODE_STACK 0x00000001
#define RTL_WALK_VALID_FLAGS 0x00000001
NTSYSAPI
ULONG
NTAPI
RtlWalkFrameChain(
__out PVOID *Callers,
__in ULONG Count,
__in ULONG Flags
);
#endif

356
KProcessHacker/main.c Normal file
View File

@ -0,0 +1,356 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
#include <dyndata.h>
DRIVER_INITIALIZE DriverEntry;
DRIVER_UNLOAD DriverUnload;
__drv_dispatchType(IRP_MJ_CREATE) DRIVER_DISPATCH KphDispatchCreate;
__drv_dispatchType(IRP_MJ_CLOSE) DRIVER_DISPATCH KphDispatchClose;
ULONG KphpReadIntegerParameter(
__in_opt HANDLE KeyHandle,
__in PUNICODE_STRING ValueName,
__in ULONG DefaultValue
);
NTSTATUS KphpReadDriverParameters(
__in PUNICODE_STRING RegistryPath
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DriverEntry)
#pragma alloc_text(PAGE, DriverUnload)
#pragma alloc_text(PAGE, KphpReadIntegerParameter)
#pragma alloc_text(PAGE, KphpReadDriverParameters)
#pragma alloc_text(PAGE, KpiGetFeatures)
#endif
PDRIVER_OBJECT KphDriverObject;
PDEVICE_OBJECT KphDeviceObject;
ULONG KphFeatures;
KPH_PARAMETERS KphParameters;
NTSTATUS DriverEntry(
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
UNICODE_STRING deviceName;
PDEVICE_OBJECT deviceObject;
PAGED_CODE();
KphDriverObject = DriverObject;
if (!NT_SUCCESS(status = KphDynamicDataInitialization()))
return status;
KphDynamicImport();
if (!NT_SUCCESS(status = KphpReadDriverParameters(RegistryPath)))
return status;
// Create the device.
RtlInitUnicodeString(&deviceName, KPH_DEVICE_NAME);
status = IoCreateDevice(
DriverObject,
0,
&deviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&deviceObject
);
if (!NT_SUCCESS(status))
return status;
KphDeviceObject = deviceObject;
// Set up I/O.
DriverObject->MajorFunction[IRP_MJ_CREATE] = KphDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KphDispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = KphDispatchDeviceControl;
DriverObject->DriverUnload = DriverUnload;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
dprintf("Driver loaded\n");
return status;
}
VOID DriverUnload(
__in PDRIVER_OBJECT DriverObject
)
{
PAGED_CODE();
IoDeleteDevice(KphDeviceObject);
dprintf("Driver unloaded\n");
}
NTSTATUS KphDispatchCreate(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stackLocation;
PFILE_OBJECT fileObject;
PIO_SECURITY_CONTEXT securityContext;
PKPH_CLIENT client;
stackLocation = IoGetCurrentIrpStackLocation(Irp);
fileObject = stackLocation->FileObject;
securityContext = stackLocation->Parameters.Create.SecurityContext;
dprintf("Client (PID %Iu) is connecting\n", PsGetCurrentProcessId());
if (KphParameters.SecurityLevel == KphSecurityPrivilegeCheck ||
KphParameters.SecurityLevel == KphSecuritySignatureAndPrivilegeCheck)
{
UCHAR requiredPrivilegesBuffer[FIELD_OFFSET(PRIVILEGE_SET, Privilege) + sizeof(LUID_AND_ATTRIBUTES)];
PPRIVILEGE_SET requiredPrivileges;
// Check for SeDebugPrivilege.
requiredPrivileges = (PPRIVILEGE_SET)requiredPrivilegesBuffer;
requiredPrivileges->PrivilegeCount = 1;
requiredPrivileges->Control = PRIVILEGE_SET_ALL_NECESSARY;
requiredPrivileges->Privilege[0].Luid.LowPart = SE_DEBUG_PRIVILEGE;
requiredPrivileges->Privilege[0].Luid.HighPart = 0;
requiredPrivileges->Privilege[0].Attributes = 0;
if (!SePrivilegeCheck(
requiredPrivileges,
&securityContext->AccessState->SubjectSecurityContext,
Irp->RequestorMode
))
{
status = STATUS_PRIVILEGE_NOT_HELD;
dprintf("Client (PID %Iu) was rejected\n", PsGetCurrentProcessId());
}
}
if (NT_SUCCESS(status))
{
client = ExAllocatePoolWithTag(PagedPool, sizeof(KPH_CLIENT), 'ChpK');
if (client)
{
memset(client, 0, sizeof(KPH_CLIENT));
ExInitializeFastMutex(&client->StateMutex);
ExInitializeFastMutex(&client->KeyBackoffMutex);
fileObject->FsContext = client;
}
else
{
dprintf("Unable to allocate memory for client (PID %Iu)\n", PsGetCurrentProcessId());
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS KphDispatchClose(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION stackLocation;
PFILE_OBJECT fileObject;
PKPH_CLIENT client;
stackLocation = IoGetCurrentIrpStackLocation(Irp);
fileObject = stackLocation->FileObject;
client = fileObject->FsContext;
if (client)
{
ExFreePoolWithTag(client, 'ChpK');
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/**
* Reads an integer (REG_DWORD) parameter from the registry.
*
* \param KeyHandle A handle to the Parameters key. If NULL, the function
* fails immediately and returns \a DefaultValue.
* \param ValueName The name of the parameter.
* \param DefaultValue The value that is returned if the function fails
* to retrieve the parameter from the registry.
*
* \return The parameter value, or \a DefaultValue if the function failed.
*/
ULONG KphpReadIntegerParameter(
__in_opt HANDLE KeyHandle,
__in PUNICODE_STRING ValueName,
__in ULONG DefaultValue
)
{
NTSTATUS status;
UCHAR buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
PKEY_VALUE_PARTIAL_INFORMATION info;
ULONG resultLength;
PAGED_CODE();
if (!KeyHandle)
return DefaultValue;
info = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
status = ZwQueryValueKey(
KeyHandle,
ValueName,
KeyValuePartialInformation,
info,
sizeof(buffer),
&resultLength
);
if (info->Type != REG_DWORD)
status = STATUS_OBJECT_TYPE_MISMATCH;
if (!NT_SUCCESS(status))
{
dprintf("Unable to query parameter %.*S: 0x%x\n", ValueName->Length / sizeof(WCHAR), ValueName->Buffer, status);
return DefaultValue;
}
return *(PULONG)info->Data;
}
/**
* Reads the driver parameters.
*
* \param RegistryPath The registry path of the driver.
*/
NTSTATUS KphpReadDriverParameters(
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
HANDLE parametersKeyHandle;
UNICODE_STRING parametersString;
UNICODE_STRING parametersKeyName;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING valueName;
PAGED_CODE();
// Open the Parameters key.
RtlInitUnicodeString(&parametersString, L"\\Parameters");
parametersKeyName.Length = RegistryPath->Length + parametersString.Length;
parametersKeyName.MaximumLength = parametersKeyName.Length;
parametersKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, parametersKeyName.MaximumLength, 'ThpK');
if (!parametersKeyName.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
memcpy(parametersKeyName.Buffer, RegistryPath->Buffer, RegistryPath->Length);
memcpy(&parametersKeyName.Buffer[RegistryPath->Length / sizeof(WCHAR)], parametersString.Buffer, parametersString.Length);
InitializeObjectAttributes(
&objectAttributes,
&parametersKeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
status = ZwOpenKey(
&parametersKeyHandle,
KEY_READ,
&objectAttributes
);
ExFreePoolWithTag(parametersKeyName.Buffer, 'ThpK');
if (!NT_SUCCESS(status))
{
dprintf("Unable to open Parameters key: 0x%x\n", status);
status = STATUS_SUCCESS;
parametersKeyHandle = NULL;
// Continue so we can set up defaults.
}
// Read in the parameters.
RtlInitUnicodeString(&valueName, L"SecurityLevel");
KphParameters.SecurityLevel = KphpReadIntegerParameter(parametersKeyHandle, &valueName, KphSecurityPrivilegeCheck);
KphReadDynamicDataParameters(parametersKeyHandle);
if (parametersKeyHandle)
ZwClose(parametersKeyHandle);
return status;
}
NTSTATUS KpiGetFeatures(
__out PULONG Features,
__in KPROCESSOR_MODE AccessMode
)
{
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(Features, sizeof(ULONG), sizeof(ULONG));
*Features = KphFeatures;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
else
{
*Features = KphFeatures;
}
return STATUS_SUCCESS;
}

1295
KProcessHacker/object.c Normal file

File diff suppressed because it is too large Load Diff

570
KProcessHacker/process.c Normal file
View File

@ -0,0 +1,570 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
#include <dyndata.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KpiOpenProcess)
#pragma alloc_text(PAGE, KpiOpenProcessToken)
#pragma alloc_text(PAGE, KpiOpenProcessJob)
#pragma alloc_text(PAGE, KpiTerminateProcess)
#pragma alloc_text(PAGE, KpiQueryInformationProcess)
#pragma alloc_text(PAGE, KpiSetInformationProcess)
#endif
/**
* Opens a process.
*
* \param ProcessHandle A variable which receives the process handle.
* \param DesiredAccess The desired access to the process.
* \param ClientId The identifier of a process or thread. If \a UniqueThread is present, the process
* of the identified thread will be opened. If \a UniqueProcess is present, the identified process
* will be opened.
* \param Key An access key.
* \li If a L2 key is provided, no access checks are performed.
* \li If a L1 key is provided, only read access is permitted but no additional access checks are
* performed.
* \li If no valid key is provided, the function fails.
* \param Client The client that initiated the request.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiOpenProcess(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in PCLIENT_ID ClientId,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
CLIENT_ID clientId;
PEPROCESS process;
PETHREAD thread;
KPH_KEY_LEVEL requiredKeyLevel;
HANDLE processHandle;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(ProcessHandle, sizeof(HANDLE), sizeof(HANDLE));
ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
clientId = *ClientId;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
else
{
clientId = *ClientId;
}
// Use the thread ID if it was specified.
if (clientId.UniqueThread)
{
status = PsLookupProcessThreadByCid(&clientId, &process, &thread);
if (NT_SUCCESS(status))
{
// We don't actually need the thread.
ObDereferenceObject(thread);
}
}
else
{
status = PsLookupProcessByProcessId(clientId.UniqueProcess, &process);
}
if (!NT_SUCCESS(status))
return status;
requiredKeyLevel = KphKeyLevel1;
if ((DesiredAccess & KPH_PROCESS_READ_ACCESS) != DesiredAccess)
requiredKeyLevel = KphKeyLevel2;
if (NT_SUCCESS(status = KphValidateKey(requiredKeyLevel, Key, Client, AccessMode)))
{
// Always open in KernelMode to skip ordinary access checks.
status = ObOpenObjectByPointer(
process,
0,
NULL,
DesiredAccess,
*PsProcessType,
KernelMode,
&processHandle
);
}
ObDereferenceObject(process);
if (NT_SUCCESS(status))
{
if (AccessMode != KernelMode)
{
__try
{
*ProcessHandle = processHandle;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
*ProcessHandle = processHandle;
}
}
return status;
}
/**
* Opens the token of a process.
*
* \param ProcessHandle A handle to a process.
* \param DesiredAccess The desired access to the token.
* \param TokenHandle A variable which receives the token handle.
* \param Key An access key.
* \li If a L2 key is provided, no access checks are performed.
* \li If a L1 key is provided, only read access is permitted but no additional access checks are
* performed.
* \li If no valid key is provided, the function fails.
* \param Client The client that initiated the request.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiOpenProcessToken(
__in HANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE TokenHandle,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
PACCESS_TOKEN primaryToken;
KPH_KEY_LEVEL requiredKeyLevel;
HANDLE tokenHandle;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(TokenHandle, sizeof(HANDLE), sizeof(HANDLE));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ProcessHandle,
0,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (!NT_SUCCESS(status))
return status;
if (primaryToken = PsReferencePrimaryToken(process))
{
requiredKeyLevel = KphKeyLevel1;
if ((DesiredAccess & KPH_TOKEN_READ_ACCESS) != DesiredAccess)
requiredKeyLevel = KphKeyLevel2;
if (NT_SUCCESS(status = KphValidateKey(requiredKeyLevel, Key, Client, AccessMode)))
{
status = ObOpenObjectByPointer(
primaryToken,
0,
NULL,
DesiredAccess,
*SeTokenObjectType,
KernelMode,
&tokenHandle
);
}
PsDereferencePrimaryToken(primaryToken);
}
else
{
status = STATUS_NO_TOKEN;
}
ObDereferenceObject(process);
if (NT_SUCCESS(status))
{
if (AccessMode != KernelMode)
{
__try
{
*TokenHandle = tokenHandle;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
*TokenHandle = tokenHandle;
}
}
return status;
}
/**
* Opens the job object of a process.
*
* \param ProcessHandle A handle to a process.
* \param DesiredAccess The desired access to the job.
* \param JobHandle A variable which receives the job object handle.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiOpenProcessJob(
__in HANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE JobHandle,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
PEJOB job;
HANDLE jobHandle = NULL;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(JobHandle, sizeof(HANDLE), sizeof(HANDLE));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ProcessHandle,
0,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (!NT_SUCCESS(status))
return status;
job = PsGetProcessJob(process);
if (job)
{
status = ObOpenObjectByPointer(
job,
0,
NULL,
DesiredAccess,
*PsJobType,
AccessMode,
&jobHandle
);
}
else
{
status = STATUS_NOT_FOUND;
}
ObDereferenceObject(process);
if (NT_SUCCESS(status))
{
if (AccessMode != KernelMode)
{
__try
{
*JobHandle = jobHandle;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
*JobHandle = jobHandle;
}
}
return status;
}
/**
* Terminates a process.
*
* \param ProcessHandle A handle to a process.
* \param ExitStatus A status value which indicates why the process is being terminated.
* \param Key An access key.
* \li If a L2 key is provided, no access checks are performed.
* \li If no valid L2 key is provided, the function fails.
* \param Client The client that initiated the request.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiTerminateProcess(
__in HANDLE ProcessHandle,
__in NTSTATUS ExitStatus,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
PAGED_CODE();
if (!NT_SUCCESS(status = KphValidateKey(KphKeyLevel2, Key, Client, AccessMode)))
return status;
status = ObReferenceObjectByHandle(
ProcessHandle,
0,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (!NT_SUCCESS(status))
return status;
if (process != PsGetCurrentProcess())
{
HANDLE newProcessHandle;
// Re-open the process to get a kernel handle.
if (NT_SUCCESS(status = ObOpenObjectByPointer(
process,
OBJ_KERNEL_HANDLE,
NULL,
PROCESS_TERMINATE,
*PsProcessType,
KernelMode,
&newProcessHandle
)))
{
status = ZwTerminateProcess(newProcessHandle, ExitStatus);
ZwClose(newProcessHandle);
}
}
else
{
status = STATUS_CANT_TERMINATE_SELF;
}
ObDereferenceObject(process);
return status;
}
/**
* Queries process information.
*
* \param ProcessHandle A handle to a process.
* \param ProcessInformationClass The type of information to query.
* \param ProcessInformation The buffer in which the information will be stored.
* \param ProcessInformationLength The number of bytes available in \a ProcessInformation.
* \param ReturnLength A variable which receives the number of bytes required to be available in
* \a ProcessInformation.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiQueryInformationProcess(
__in HANDLE ProcessHandle,
__in KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
__out_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
ULONG returnLength;
PAGED_CODE();
if (AccessMode != KernelMode)
{
ULONG alignment;
switch (ProcessInformationClass)
{
default:
alignment = sizeof(ULONG);
break;
}
__try
{
ProbeForWrite(ProcessInformation, ProcessInformationLength, alignment);
if (ReturnLength)
ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ProcessHandle,
PROCESS_QUERY_INFORMATION,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (!NT_SUCCESS(status))
return status;
switch (ProcessInformationClass)
{
default:
status = STATUS_INVALID_INFO_CLASS;
returnLength = 0;
break;
}
ObDereferenceObject(process);
if (ReturnLength)
{
if (AccessMode != KernelMode)
{
__try
{
*ReturnLength = returnLength;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
NOTHING;
}
}
else
{
*ReturnLength = returnLength;
}
}
return status;
}
/**
* Sets process information.
*
* \param ProcessHandle A handle to a process.
* \param ProcessInformationClass The type of information to set.
* \param ProcessInformation A buffer which contains the information to set.
* \param ProcessInformationLength The number of bytes present in \a ProcessInformation.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiSetInformationProcess(
__in HANDLE ProcessHandle,
__in KPH_PROCESS_INFORMATION_CLASS ProcessInformationClass,
__in_bcount(ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
PAGED_CODE();
if (AccessMode != KernelMode)
{
ULONG alignment;
switch (ProcessInformationClass)
{
default:
alignment = sizeof(ULONG);
break;
}
__try
{
ProbeForRead(ProcessInformation, ProcessInformationLength, alignment);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ProcessHandle,
PROCESS_SET_INFORMATION,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (!NT_SUCCESS(status))
return status;
switch (ProcessInformationClass)
{
default:
status = STATUS_INVALID_INFO_CLASS;
break;
}
ObDereferenceObject(process);
return status;
}

238
KProcessHacker/qrydrv.c Normal file
View File

@ -0,0 +1,238 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
VOID KphpCopyInfoUnicodeString(
__out PVOID Information,
__in_opt PUNICODE_STRING UnicodeString
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KpiOpenDriver)
#pragma alloc_text(PAGE, KpiQueryInformationDriver)
#pragma alloc_text(PAGE, KphpCopyInfoUnicodeString)
#endif
NTSTATUS KpiOpenDriver(
__out PHANDLE DriverHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in KPROCESSOR_MODE AccessMode
)
{
PAGED_CODE();
return KphOpenNamedObject(
DriverHandle,
DesiredAccess,
ObjectAttributes,
*IoDriverObjectType,
AccessMode
);
}
NTSTATUS KpiQueryInformationDriver(
__in HANDLE DriverHandle,
__in DRIVER_INFORMATION_CLASS DriverInformationClass,
__out_bcount(DriverInformationLength) PVOID DriverInformation,
__in ULONG DriverInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
PDRIVER_OBJECT driverObject;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(DriverInformation, DriverInformationLength, 1);
if (ReturnLength)
ProbeForWrite(ReturnLength, sizeof(ULONG), 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
DriverHandle,
0,
*IoDriverObjectType,
AccessMode,
&driverObject,
NULL
);
if (!NT_SUCCESS(status))
return status;
__try
{
switch (DriverInformationClass)
{
// Basic information such as flags, driver base and driver size.
case DriverBasicInformation:
{
if (DriverInformationLength == sizeof(DRIVER_BASIC_INFORMATION))
{
PDRIVER_BASIC_INFORMATION basicInfo;
basicInfo = (PDRIVER_BASIC_INFORMATION)DriverInformation;
basicInfo->Flags = driverObject->Flags;
basicInfo->DriverStart = driverObject->DriverStart;
basicInfo->DriverSize = driverObject->DriverSize;
}
else
{
status = STATUS_INFO_LENGTH_MISMATCH;
}
if (ReturnLength)
*ReturnLength = sizeof(DRIVER_BASIC_INFORMATION);
}
break;
// The name of the driver - e.g. \Driver\Null.
case DriverNameInformation:
{
if (DriverInformation)
{
/* Check buffer length. */
if (sizeof(UNICODE_STRING) + driverObject->DriverName.Length <=
DriverInformationLength)
{
KphpCopyInfoUnicodeString(
DriverInformation,
&driverObject->DriverName
);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
}
}
if (ReturnLength)
*ReturnLength = sizeof(UNICODE_STRING) + driverObject->DriverName.Length;
}
break;
// The name of the driver's service key - e.g. \REGISTRY\...
case DriverServiceKeyNameInformation:
{
if (driverObject->DriverExtension)
{
if (DriverInformation)
{
if (sizeof(UNICODE_STRING) +
driverObject->DriverExtension->ServiceKeyName.Length <=
DriverInformationLength)
{
KphpCopyInfoUnicodeString(
DriverInformation,
&driverObject->DriverExtension->ServiceKeyName
);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
}
}
if (ReturnLength)
{
*ReturnLength = sizeof(UNICODE_STRING) +
driverObject->DriverExtension->ServiceKeyName.Length;
}
}
else
{
if (DriverInformation)
{
if (sizeof(UNICODE_STRING) <= DriverInformationLength)
{
// Zero the information buffer.
KphpCopyInfoUnicodeString(
DriverInformation,
NULL
);
}
else
{
status = STATUS_BUFFER_TOO_SMALL;
}
}
if (ReturnLength)
*ReturnLength = sizeof(UNICODE_STRING);
}
}
break;
default:
{
status = STATUS_INVALID_INFO_CLASS;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
ObDereferenceObject(driverObject);
return status;
}
VOID KphpCopyInfoUnicodeString(
__out PVOID Information,
__in_opt PUNICODE_STRING UnicodeString
)
{
PUNICODE_STRING targetUnicodeString = Information;
PWCHAR targetBuffer;
PAGED_CODE();
if (UnicodeString)
{
targetBuffer = (PWCHAR)((PCHAR)Information + sizeof(UNICODE_STRING));
targetUnicodeString->Length = UnicodeString->Length;
targetUnicodeString->MaximumLength = UnicodeString->Length;
targetUnicodeString->Buffer = targetBuffer;
memcpy(targetBuffer, UnicodeString->Buffer, UnicodeString->Length);
}
else
{
targetUnicodeString->Length = 0;
targetUnicodeString->MaximumLength = 0;
targetUnicodeString->Buffer = NULL;
}
}

View File

@ -0,0 +1,53 @@
#include <windows.h>
#define VER_COMMA 3,0,0,0
#define VER_STR "3.0\0"
#define VER_FILEVERSION VER_COMMA
#define VER_FILEVERSION_STR VER_STR
#define VER_PRODUCTVERSION VER_COMMA
#define VER_PRODUCTVERSION_STR VER_STR
#ifndef DEBUG
#define VER_DEBUG 0
#else
#define VER_DEBUG VS_FF_DEBUG
#endif
#define VER_PRIVATEBUILD 0
#define VER_PRERELEASE 0
#define VER_COMPANYNAME_STR "wj32\0"
#define VER_FILEDESCRIPTION_STR "KProcessHacker\0"
#define VER_LEGALCOPYRIGHT_STR "Licensed under the GNU GPL, v3.\0"
#define VER_ORIGINALFILENAME_STR "kprocesshacker.sys\0"
#define VER_PRODUCTNAME_STR "KProcessHacker\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS (VER_PRIVATEBUILD | VER_PRERELEASE | VER_DEBUG)
FILEOS VOS__WINDOWS32
FILETYPE VFT_DRV
FILESUBTYPE VFT2_DRV_SYSTEM
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
VALUE "ProductName", VER_PRODUCTNAME_STR
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END

7
KProcessHacker/sign.cmd Normal file
View File

@ -0,0 +1,7 @@
@echo off
set PHBASE=..
set SIGN_TIMESTAMP=1
copy bin\i386\kprocesshacker.sys bin-signed\i386\kprocesshacker.sys
copy bin\amd64\kprocesshacker.sys bin-signed\amd64\kprocesshacker.sys
call ..\build\internal\sign.cmd bin-signed\i386\kprocesshacker.sys kmcs
call ..\build\internal\sign.cmd bin-signed\amd64\kprocesshacker.sys kmcs

View File

@ -0,0 +1,28 @@
TARGETTYPE=DRIVER
!IF !DEFINED(TARGETNAME)
TARGETNAME=kprocesshacker
!ENDIF
!IF !DEFINED(TARGETPATH)
TARGETPATH=..\bin
!ENDIF
TARGETLIBS=$(TARGETLIBS) $(DDK_LIB_PATH)\ksecdd.lib
INCLUDES=$(DDK_INC_PATH);..\include;..\..\phnt\include;..\..\phlib\include
LIBS=%BUILD%\lib
SOURCES= \
..\main.c \
..\devctrl.c \
..\dyndata.c \
..\dynimp.c \
..\object.c \
..\process.c \
..\qrydrv.c \
..\thread.c \
..\util.c \
..\verify.c \
..\vm.c \
..\resource.rc

714
KProcessHacker/thread.c Normal file
View File

@ -0,0 +1,714 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
#include <dyndata.h>
typedef struct _CAPTURE_BACKTRACE_THREAD_CONTEXT
{
BOOLEAN Local;
KAPC Apc;
KEVENT CompletedEvent;
ULONG FramesToSkip;
ULONG FramesToCapture;
PVOID *BackTrace;
ULONG CapturedFrames;
ULONG BackTraceHash;
} CAPTURE_BACKTRACE_THREAD_CONTEXT, *PCAPTURE_BACKTRACE_THREAD_CONTEXT;
KKERNEL_ROUTINE KphpCaptureStackBackTraceThreadSpecialApc;
VOID KphpCaptureStackBackTraceThreadSpecialApc(
__in PRKAPC Apc,
__inout PKNORMAL_ROUTINE *NormalRoutine,
__inout PVOID *NormalContext,
__inout PVOID *SystemArgument1,
__inout PVOID *SystemArgument2
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KpiOpenThread)
#pragma alloc_text(PAGE, KpiOpenThreadProcess)
#pragma alloc_text(PAGE, KphCaptureStackBackTraceThread)
#pragma alloc_text(PAGE, KphpCaptureStackBackTraceThreadSpecialApc)
#pragma alloc_text(PAGE, KpiCaptureStackBackTraceThread)
#pragma alloc_text(PAGE, KpiQueryInformationThread)
#pragma alloc_text(PAGE, KpiSetInformationThread)
#endif
/**
* Opens a thread.
*
* \param ThreadHandle A variable which receives the thread handle.
* \param DesiredAccess The desired access to the thread.
* \param ClientId The identifier of a thread. \a UniqueThread must be present. If \a UniqueProcess
* is present, the process of the referenced thread will be checked against this identifier.
* \param Key An access key.
* \li If a L2 key is provided, no access checks are performed.
* \li If a L1 key is provided, only read access is permitted but no additional access checks are
* performed.
* \li If no valid key is provided, the function fails.
* \param Client The client that initiated the request.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiOpenThread(
__out PHANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__in PCLIENT_ID ClientId,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
CLIENT_ID clientId;
PETHREAD thread;
KPH_KEY_LEVEL requiredKeyLevel;
HANDLE threadHandle;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(ThreadHandle, sizeof(HANDLE), sizeof(HANDLE));
ProbeForRead(ClientId, sizeof(CLIENT_ID), sizeof(ULONG));
clientId = *ClientId;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
else
{
clientId = *ClientId;
}
// Use the process ID if it was specified.
if (clientId.UniqueProcess)
{
status = PsLookupProcessThreadByCid(&clientId, NULL, &thread);
}
else
{
status = PsLookupThreadByThreadId(clientId.UniqueThread, &thread);
}
if (!NT_SUCCESS(status))
return status;
requiredKeyLevel = KphKeyLevel1;
if ((DesiredAccess & KPH_THREAD_READ_ACCESS) != DesiredAccess)
requiredKeyLevel = KphKeyLevel2;
if (NT_SUCCESS(status = KphValidateKey(requiredKeyLevel, Key, Client, AccessMode)))
{
// Always open in KernelMode to skip access checks.
status = ObOpenObjectByPointer(
thread,
0,
NULL,
DesiredAccess,
*PsThreadType,
KernelMode,
&threadHandle
);
}
ObDereferenceObject(thread);
if (NT_SUCCESS(status))
{
if (AccessMode != KernelMode)
{
__try
{
*ThreadHandle = threadHandle;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
*ThreadHandle = threadHandle;
}
}
return status;
}
/**
* Opens the process of a thread.
*
* \param ThreadHandle A handle to a thread.
* \param DesiredAccess The desired access to the process.
* \param ProcessHandle A variable which receives the process handle.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiOpenThreadProcess(
__in HANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__out PHANDLE ProcessHandle,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PETHREAD thread;
PEPROCESS process;
HANDLE processHandle;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(ProcessHandle, sizeof(HANDLE), sizeof(HANDLE));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ThreadHandle,
0,
*PsThreadType,
AccessMode,
&thread,
NULL
);
if (!NT_SUCCESS(status))
return status;
process = IoThreadToProcess(thread);
status = ObOpenObjectByPointer(
process,
0,
NULL,
DesiredAccess,
*PsProcessType,
AccessMode,
&processHandle
);
ObDereferenceObject(thread);
if (NT_SUCCESS(status))
{
if (AccessMode != KernelMode)
{
__try
{
*ProcessHandle = processHandle;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
*ProcessHandle = processHandle;
}
}
return status;
}
/**
* Captures a stack trace of the current thread.
*
* \param FramesToSkip The number of frames to skip from the bottom of the stack.
* \param FramesToCapture The number of frames to capture.
* \param Flags A combination of the following:
* \li \c RTL_WALK_USER_MODE_STACK The user-mode stack will be retrieved instead of the kernel-mode
* stack.
* \param BackTrace An array in which the stack trace will be stored.
* \param BackTraceHash A variable which receives a hash of the stack trace.
*
* \return The number of frames captured.
*/
ULONG KphCaptureStackBackTrace(
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__in_opt ULONG Flags,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG BackTraceHash
)
{
PVOID backTrace[MAX_STACK_DEPTH];
ULONG framesFound;
ULONG hash;
ULONG i;
// Skip the current frame (for this function).
FramesToSkip++;
// Ensure that we won't overrun the buffer.
if (FramesToCapture + FramesToSkip > MAX_STACK_DEPTH)
return 0;
// Validate the flags.
if ((Flags & RTL_WALK_VALID_FLAGS) != Flags)
return 0;
// Walk the stack.
framesFound = RtlWalkFrameChain(
backTrace,
FramesToCapture + FramesToSkip,
Flags
);
// Return nothing if we found fewer frames than we wanted to skip.
if (framesFound <= FramesToSkip)
return 0;
// Copy over the stack trace. At the same time we calculate the stack trace hash by summing the
// addresses.
for (i = 0, hash = 0; i < FramesToCapture; i++)
{
if (FramesToSkip + i >= framesFound)
break;
BackTrace[i] = backTrace[FramesToSkip + i];
hash += PtrToUlong(BackTrace[i]);
}
if (BackTraceHash)
*BackTraceHash = hash;
return i;
}
/**
* Captures the stack trace of a thread.
*
* \param Thread The thread to capture the stack trace of.
* \param FramesToSkip The number of frames to skip from the bottom of the stack.
* \param FramesToCapture The number of frames to capture.
* \param BackTrace An array in which the stack trace will be stored.
* \param CapturedFrames A variable which receives the number of frames captured.
* \param BackTraceHash A variable which receives a hash of the stack trace.
* \param AccessMode The mode in which to perform access checks.
*
* \return The number of frames captured.
*/
NTSTATUS KphCaptureStackBackTraceThread(
__in PETHREAD Thread,
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG CapturedFrames,
__out_opt PULONG BackTraceHash,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
CAPTURE_BACKTRACE_THREAD_CONTEXT context;
ULONG backTraceSize;
PVOID *backTrace;
PAGED_CODE();
// Make sure the caller didn't request too many frames. This also restricts the amount of memory
// we will try to allocate later.
if (FramesToCapture > MAX_STACK_DEPTH)
return STATUS_INVALID_PARAMETER_3;
backTraceSize = FramesToCapture * sizeof(PVOID);
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(BackTrace, backTraceSize, sizeof(PVOID));
if (CapturedFrames)
ProbeForWrite(CapturedFrames, sizeof(ULONG), sizeof(ULONG));
if (BackTraceHash)
ProbeForWrite(BackTraceHash, sizeof(ULONG), sizeof(ULONG));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
// If the caller doesn't want to capture anything, return immediately.
if (backTraceSize == 0)
{
if (AccessMode != KernelMode)
{
__try
{
if (CapturedFrames)
*CapturedFrames = 0;
if (BackTraceHash)
*BackTraceHash = 0;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
if (CapturedFrames)
*CapturedFrames = 0;
if (BackTraceHash)
*BackTraceHash = 0;
}
return status;
}
// Allocate storage for the stack trace.
backTrace = ExAllocatePoolWithTag(NonPagedPool, backTraceSize, 'bhpK');
if (!backTrace)
return STATUS_INSUFFICIENT_RESOURCES;
// Initialize the context structure.
context.FramesToSkip = FramesToSkip;
context.FramesToCapture = FramesToCapture;
context.BackTrace = backTrace;
// Check if we're trying to get a stack trace of the current thread.
// If so, we don't need to insert an APC.
if (Thread == PsGetCurrentThread())
{
PCAPTURE_BACKTRACE_THREAD_CONTEXT contextPtr = &context;
PVOID dummy = NULL;
KIRQL oldIrql;
// Raise the IRQL to APC_LEVEL to simulate an APC environment,
// and call the APC routine directly.
context.Local = TRUE;
KeRaiseIrql(APC_LEVEL, &oldIrql);
KphpCaptureStackBackTraceThreadSpecialApc(
&context.Apc,
NULL,
NULL,
&contextPtr,
&dummy
);
KeLowerIrql(oldIrql);
}
else
{
context.Local = FALSE;
KeInitializeEvent(&context.CompletedEvent, NotificationEvent, FALSE);
KeInitializeApc(
&context.Apc,
(PKTHREAD)Thread,
OriginalApcEnvironment,
KphpCaptureStackBackTraceThreadSpecialApc,
NULL,
NULL,
KernelMode,
NULL
);
if (KeInsertQueueApc(&context.Apc, &context, NULL, 2))
{
// Wait for the APC to complete.
status = KeWaitForSingleObject(
&context.CompletedEvent,
Executive,
KernelMode,
FALSE,
NULL
);
}
else
{
status = STATUS_UNSUCCESSFUL;
}
}
if (NT_SUCCESS(status))
{
ASSERT(context.CapturedFrames <= FramesToCapture);
if (AccessMode != KernelMode)
{
__try
{
memcpy(BackTrace, backTrace, context.CapturedFrames * sizeof(PVOID));
if (CapturedFrames)
*CapturedFrames = context.CapturedFrames;
if (BackTraceHash)
*BackTraceHash = context.BackTraceHash;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
}
}
else
{
memcpy(BackTrace, backTrace, context.CapturedFrames * sizeof(PVOID));
if (CapturedFrames)
*CapturedFrames = context.CapturedFrames;
if (BackTraceHash)
*BackTraceHash = context.BackTraceHash;
}
}
ExFreePoolWithTag(backTrace, 'bhpK');
return status;
}
VOID KphpCaptureStackBackTraceThreadSpecialApc(
__in PRKAPC Apc,
__inout PKNORMAL_ROUTINE *NormalRoutine,
__inout PVOID *NormalContext,
__inout PVOID *SystemArgument1,
__inout PVOID *SystemArgument2
)
{
PCAPTURE_BACKTRACE_THREAD_CONTEXT context = *SystemArgument1;
PAGED_CODE();
context->CapturedFrames = KphCaptureStackBackTrace(
context->FramesToSkip,
context->FramesToCapture,
0,
context->BackTrace,
&context->BackTraceHash
);
if (!context->Local)
{
// Notify the originating thread that we have completed.
KeSetEvent(&context->CompletedEvent, 0, FALSE);
}
}
/**
* Captures the stack trace of a thread.
*
* \param ThreadHandle A handle to the thread to capture the stack trace of.
* \param FramesToSkip The number of frames to skip from the bottom of the stack.
* \param FramesToCapture The number of frames to capture.
* \param BackTrace An array in which the stack trace will be stored.
* \param CapturedFrames A variable which receives the number of frames captured.
* \param BackTraceHash A variable which receives a hash of the stack trace.
* \param AccessMode The mode in which to perform access checks.
*
* \return The number of frames captured.
*/
NTSTATUS KpiCaptureStackBackTraceThread(
__in HANDLE ThreadHandle,
__in ULONG FramesToSkip,
__in ULONG FramesToCapture,
__out_ecount(FramesToCapture) PVOID *BackTrace,
__out_opt PULONG CapturedFrames,
__out_opt PULONG BackTraceHash,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
PETHREAD thread;
PAGED_CODE();
status = ObReferenceObjectByHandle(
ThreadHandle,
0,
*PsThreadType,
AccessMode,
&thread,
NULL
);
if (!NT_SUCCESS(status))
return status;
status = KphCaptureStackBackTraceThread(
thread,
FramesToSkip,
FramesToCapture,
BackTrace,
CapturedFrames,
BackTraceHash,
AccessMode
);
ObDereferenceObject(thread);
return status;
}
/**
* Queries thread information.
*
* \param ThreadHandle A handle to a thread.
* \param ThreadInformationClass The type of information to query.
* \param ThreadInformation The buffer in which the information will be stored.
* \param ThreadInformationLength The number of bytes available in \a ThreadInformation.
* \param ReturnLength A variable which receives the number of bytes required to be available in
* \a ThreadInformation.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiQueryInformationThread(
__in HANDLE ThreadHandle,
__in KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
__out_bcount(ProcessInformationLength) PVOID ThreadInformation,
__in ULONG ThreadInformationLength,
__out_opt PULONG ReturnLength,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PETHREAD thread;
ULONG returnLength;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForWrite(ThreadInformation, ThreadInformationLength, sizeof(ULONG));
if (ReturnLength)
ProbeForWrite(ReturnLength, sizeof(ULONG), sizeof(ULONG));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_QUERY_INFORMATION,
*PsThreadType,
AccessMode,
&thread,
NULL
);
if (!NT_SUCCESS(status))
return status;
switch (ThreadInformationClass)
{
default:
status = STATUS_INVALID_INFO_CLASS;
returnLength = 0;
break;
}
ObDereferenceObject(thread);
if (ReturnLength)
{
if (AccessMode != KernelMode)
{
__try
{
*ReturnLength = returnLength;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
NOTHING;
}
}
else
{
*ReturnLength = returnLength;
}
}
return status;
}
/**
* Sets thread information.
*
* \param ThreadHandle A handle to a thread.
* \param ThreadInformationClass The type of information to set.
* \param ThreadInformation A buffer which contains the information to set.
* \param ThreadInformationLength The number of bytes present in \a ThreadInformation.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiSetInformationThread(
__in HANDLE ThreadHandle,
__in KPH_THREAD_INFORMATION_CLASS ThreadInformationClass,
__in_bcount(ThreadInformationLength) PVOID ThreadInformation,
__in ULONG ThreadInformationLength,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PETHREAD thread;
PAGED_CODE();
if (AccessMode != KernelMode)
{
__try
{
ProbeForRead(ThreadInformation, ThreadInformationLength, sizeof(ULONG));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
status = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
*PsThreadType,
AccessMode,
&thread,
NULL
);
if (!NT_SUCCESS(status))
return status;
switch (ThreadInformationClass)
{
default:
status = STATUS_INVALID_INFO_CLASS;
break;
}
ObDereferenceObject(thread);
return status;
}

272
KProcessHacker/util.c Normal file
View File

@ -0,0 +1,272 @@
/*
* KProcessHacker
*
* Copyright (C) 2016 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 <kph.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KphFreeCapturedUnicodeString)
#pragma alloc_text(PAGE, KphCaptureUnicodeString)
#pragma alloc_text(PAGE, KphEnumerateSystemModules)
#pragma alloc_text(PAGE, KphValidateAddressForSystemModules)
#pragma alloc_text(PAGE, KphGetProcessMappedFileName)
#endif
VOID KphFreeCapturedUnicodeString(
__in PUNICODE_STRING CapturedUnicodeString
)
{
PAGED_CODE();
if (CapturedUnicodeString->Buffer)
ExFreePoolWithTag(CapturedUnicodeString->Buffer, 'UhpK');
}
NTSTATUS KphCaptureUnicodeString(
__in PUNICODE_STRING UnicodeString,
__out PUNICODE_STRING CapturedUnicodeString
)
{
UNICODE_STRING unicodeString;
PWCHAR userBuffer;
PAGED_CODE();
__try
{
ProbeForRead(UnicodeString, sizeof(UNICODE_STRING), sizeof(ULONG));
unicodeString.Length = UnicodeString->Length;
unicodeString.MaximumLength = unicodeString.Length;
unicodeString.Buffer = NULL;
userBuffer = UnicodeString->Buffer;
ProbeForRead(userBuffer, unicodeString.Length, sizeof(WCHAR));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
if (unicodeString.Length & 1)
{
return STATUS_INVALID_PARAMETER;
}
if (unicodeString.Length != 0)
{
unicodeString.Buffer = ExAllocatePoolWithTag(
PagedPool,
unicodeString.Length,
'UhpK'
);
if (!unicodeString.Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
__try
{
memcpy(
unicodeString.Buffer,
userBuffer,
unicodeString.Length
);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KphFreeCapturedUnicodeString(&unicodeString);
return GetExceptionCode();
}
}
*CapturedUnicodeString = unicodeString;
return STATUS_SUCCESS;
}
/**
* Enumerates the modules loaded by the kernel.
*
* \param Modules A variable which receives a pointer to a structure containing information about
* the kernel modules. The structure must be freed with the tag 'ThpK'.
*/
NTSTATUS KphEnumerateSystemModules(
__out PRTL_PROCESS_MODULES *Modules
)
{
NTSTATUS status;
PVOID buffer;
ULONG bufferSize;
ULONG attempts;
PAGED_CODE();
bufferSize = 2048;
attempts = 8;
do
{
buffer = ExAllocatePoolWithTag(PagedPool, bufferSize, 'ThpK');
if (!buffer)
{
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
status = ZwQuerySystemInformation(
SystemModuleInformation,
buffer,
bufferSize,
&bufferSize
);
if (NT_SUCCESS(status))
{
*Modules = buffer;
return status;
}
ExFreePoolWithTag(buffer, 'ThpK');
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
break;
}
} while (--attempts);
return status;
}
/**
* Checks if an address range lies within a kernel module.
*
* \param Address The beginning of the address range.
* \param Length The number of bytes in the address range.
*/
NTSTATUS KphValidateAddressForSystemModules(
__in PVOID Address,
__in SIZE_T Length
)
{
NTSTATUS status;
PRTL_PROCESS_MODULES modules;
ULONG i;
BOOLEAN valid;
PAGED_CODE();
status = KphEnumerateSystemModules(&modules);
if (!NT_SUCCESS(status))
return status;
valid = FALSE;
for (i = 0; i < modules->NumberOfModules; i++)
{
if (
(ULONG_PTR)Address + Length >= (ULONG_PTR)Address &&
(ULONG_PTR)Address >= (ULONG_PTR)modules->Modules[i].ImageBase &&
(ULONG_PTR)Address + Length <= (ULONG_PTR)modules->Modules[i].ImageBase + modules->Modules[i].ImageSize
)
{
dprintf("Validated address 0x%Ix in %s\n", Address, modules->Modules[i].FullPathName);
valid = TRUE;
break;
}
}
ExFreePoolWithTag(modules, 'ThpK');
if (valid)
status = STATUS_SUCCESS;
else
status = STATUS_ACCESS_VIOLATION;
return status;
}
/**
* Gets the file name of a mapped section.
*
* \param ProcessHandle A handle to a process. The handle must have PROCESS_QUERY_INFORMATION
* access.
* \param BaseAddress The base address of the section view.
* \param Modules A variable which receives a pointer to a string containing the file name of the
* section. The structure must be freed with the tag 'ThpK'.
*/
NTSTATUS KphGetProcessMappedFileName(
__in HANDLE ProcessHandle,
__in PVOID BaseAddress,
__out PUNICODE_STRING *FileName
)
{
NTSTATUS status;
PVOID buffer;
SIZE_T bufferSize;
SIZE_T returnLength;
PAGED_CODE();
bufferSize = 0x100;
buffer = ExAllocatePoolWithTag(PagedPool, bufferSize, 'ThpK');
if (!buffer)
return STATUS_INSUFFICIENT_RESOURCES;
status = ZwQueryVirtualMemory(
ProcessHandle,
BaseAddress,
MemoryMappedFilenameInformation,
buffer,
bufferSize,
&returnLength
);
if (status == STATUS_BUFFER_OVERFLOW)
{
ExFreePoolWithTag(buffer, 'ThpK');
bufferSize = returnLength;
buffer = ExAllocatePoolWithTag(PagedPool, bufferSize, 'ThpK');
if (!buffer)
return STATUS_INSUFFICIENT_RESOURCES;
status = ZwQueryVirtualMemory(
ProcessHandle,
BaseAddress,
MemoryMappedFilenameInformation,
buffer,
bufferSize,
&returnLength
);
}
if (!NT_SUCCESS(status))
{
ExFreePoolWithTag(buffer, 'ThpK');
return status;
}
*FileName = buffer;
return status;
}

496
KProcessHacker/verify.c Normal file
View File

@ -0,0 +1,496 @@
/*
* KProcessHacker
*
* Copyright (C) 2016 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 <kph.h>
#define FILE_BUFFER_SIZE (2 * PAGE_SIZE)
#define FILE_MAX_SIZE (32 * 1024 * 1024) // 32 MB
VOID KphpBackoffKey(
__in PKPH_CLIENT Client
);
static UCHAR KphpTrustedPublicKey[] =
{
0x45, 0x43, 0x53, 0x31, 0x20, 0x00, 0x00, 0x00, 0x5f, 0xe8, 0xab, 0xac, 0x01, 0xad, 0x6b, 0x48,
0xfd, 0x84, 0x7f, 0x43, 0x70, 0xb6, 0x57, 0xb0, 0x76, 0xe3, 0x10, 0x07, 0x19, 0xbd, 0x0e, 0xd4,
0x10, 0x5c, 0x1f, 0xfc, 0x40, 0x91, 0xb6, 0xed, 0x94, 0x37, 0x76, 0xb7, 0x86, 0x88, 0xf7, 0x34,
0x12, 0x91, 0xf6, 0x65, 0x23, 0x58, 0xc9, 0xeb, 0x2f, 0xcb, 0x96, 0x13, 0x8f, 0xca, 0x57, 0x7a,
0xd0, 0x7a, 0xbf, 0x22, 0xde, 0xd2, 0x15, 0xfc
};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KphHashFile)
#pragma alloc_text(PAGE, KphVerifyFile)
#pragma alloc_text(PAGE, KphVerifyClient)
#pragma alloc_text(PAGE, KpiVerifyClient)
#pragma alloc_text(PAGE, KphGenerateKeysClient)
#pragma alloc_text(PAGE, KphRetrieveKeyViaApc)
#pragma alloc_text(PAGE, KphValidateKey)
#pragma alloc_text(PAGE, KphpBackoffKey)
#endif
NTSTATUS KphHashFile(
__in PUNICODE_STRING FileName,
__out PVOID *Hash,
__out PULONG HashSize
)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE hashAlgHandle = NULL;
ULONG querySize;
ULONG hashObjectSize;
ULONG hashSize;
PVOID hashObject = NULL;
PVOID hash = NULL;
BCRYPT_HASH_HANDLE hashHandle = NULL;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK iosb;
HANDLE fileHandle = NULL;
FILE_STANDARD_INFORMATION standardInfo;
ULONG remainingBytes;
ULONG bytesToRead;
PVOID buffer = NULL;
PAGED_CODE();
// Open the hash algorithm and allocate memory for the hash object.
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hashAlgHandle, KPH_HASH_ALGORITHM, NULL, 0)))
goto CleanupExit;
if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_OBJECT_LENGTH,
(PUCHAR)&hashObjectSize, sizeof(ULONG), &querySize, 0)))
{
goto CleanupExit;
}
if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_HASH_LENGTH, (PUCHAR)&hashSize,
sizeof(ULONG), &querySize, 0)))
{
goto CleanupExit;
}
if (!(hashObject = ExAllocatePoolWithTag(PagedPool, hashObjectSize, 'vhpK')))
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupExit;
}
if (!(hash = ExAllocatePoolWithTag(PagedPool, hashSize, 'vhpK')))
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupExit;
}
if (!NT_SUCCESS(status = BCryptCreateHash(hashAlgHandle, &hashHandle, hashObject, hashObjectSize,
NULL, 0, 0)))
{
goto CleanupExit;
}
// Open the file and compute the hash.
InitializeObjectAttributes(&objectAttributes, FileName, OBJ_KERNEL_HANDLE, NULL, NULL);
if (!NT_SUCCESS(status = ZwCreateFile(&fileHandle, FILE_GENERIC_READ, &objectAttributes,
&iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0)))
{
goto CleanupExit;
}
if (!NT_SUCCESS(status = ZwQueryInformationFile(fileHandle, &iosb, &standardInfo,
sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation)))
{
goto CleanupExit;
}
if (standardInfo.EndOfFile.QuadPart <= 0)
{
status = STATUS_UNSUCCESSFUL;
goto CleanupExit;
}
if (standardInfo.EndOfFile.QuadPart > FILE_MAX_SIZE)
{
status = STATUS_FILE_TOO_LARGE;
goto CleanupExit;
}
if (!(buffer = ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'vhpK')))
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupExit;
}
remainingBytes = (ULONG)standardInfo.EndOfFile.QuadPart;
while (remainingBytes != 0)
{
bytesToRead = FILE_BUFFER_SIZE;
if (bytesToRead > remainingBytes)
bytesToRead = remainingBytes;
if (!NT_SUCCESS(status = ZwReadFile(fileHandle, NULL, NULL, NULL, &iosb, buffer, bytesToRead,
NULL, NULL)))
{
goto CleanupExit;
}
if ((ULONG)iosb.Information != bytesToRead)
{
status = STATUS_INTERNAL_ERROR;
goto CleanupExit;
}
if (!NT_SUCCESS(status = BCryptHashData(hashHandle, buffer, bytesToRead, 0)))
goto CleanupExit;
remainingBytes -= bytesToRead;
}
if (!NT_SUCCESS(status = BCryptFinishHash(hashHandle, hash, hashSize, 0)))
goto CleanupExit;
if (NT_SUCCESS(status))
{
*Hash = hash;
*HashSize = hashSize;
hash = NULL; // Don't free this in the cleanup section
}
CleanupExit:
if (buffer)
ExFreePoolWithTag(buffer, 'vhpK');
if (fileHandle)
ZwClose(fileHandle);
if (hashHandle)
BCryptDestroyHash(hashHandle);
if (hash)
ExFreePoolWithTag(hash, 'vhpK');
if (hashObject)
ExFreePoolWithTag(hashObject, 'vhpK');
if (hashAlgHandle)
BCryptCloseAlgorithmProvider(hashAlgHandle, 0);
return status;
}
NTSTATUS KphVerifyFile(
__in PUNICODE_STRING FileName,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize
)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE signAlgHandle = NULL;
BCRYPT_KEY_HANDLE keyHandle = NULL;
PVOID hash = NULL;
ULONG hashSize;
PAGED_CODE();
// Import the trusted public key.
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&signAlgHandle, KPH_SIGN_ALGORITHM, NULL, 0)))
goto CleanupExit;
if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, KPH_BLOB_PUBLIC, &keyHandle,
KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0)))
{
goto CleanupExit;
}
// Hash the file.
if (!NT_SUCCESS(status = KphHashFile(FileName, &hash, &hashSize)))
goto CleanupExit;
// Verify the hash.
if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, hash, hashSize, Signature,
SignatureSize, 0)))
{
goto CleanupExit;
}
CleanupExit:
if (hash)
ExFreePoolWithTag(hash, 'vhpK');
if (keyHandle)
BCryptDestroyKey(keyHandle);
if (signAlgHandle)
BCryptCloseAlgorithmProvider(signAlgHandle, 0);
return status;
}
VOID KphVerifyClient(
__inout PKPH_CLIENT Client,
__in PVOID CodeAddress,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize
)
{
NTSTATUS status;
PUNICODE_STRING processFileName = NULL;
MEMORY_BASIC_INFORMATION memoryBasicInfo;
PUNICODE_STRING mappedFileName = NULL;
PAGED_CODE();
if (Client->VerificationPerformed)
return;
if ((ULONG_PTR)CodeAddress > (ULONG_PTR)MmHighestUserAddress)
{
status = STATUS_ACCESS_VIOLATION;
goto CleanupExit;
}
if (!NT_SUCCESS(status = SeLocateProcessImageName(PsGetCurrentProcess(), &processFileName)))
goto CleanupExit;
if (!NT_SUCCESS(status = ZwQueryVirtualMemory(NtCurrentProcess(), CodeAddress,
MemoryBasicInformation, &memoryBasicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL)))
{
goto CleanupExit;
}
if (memoryBasicInfo.Type != MEM_IMAGE || memoryBasicInfo.State != MEM_COMMIT)
{
status = STATUS_INVALID_PARAMETER;
goto CleanupExit;
}
if (!NT_SUCCESS(status = KphGetProcessMappedFileName(NtCurrentProcess(), CodeAddress,
&mappedFileName)))
{
goto CleanupExit;
}
if (!RtlEqualUnicodeString(processFileName, mappedFileName, TRUE))
{
status = STATUS_INVALID_PARAMETER;
goto CleanupExit;
}
status = KphVerifyFile(processFileName, Signature, SignatureSize);
CleanupExit:
if (mappedFileName)
ExFreePoolWithTag(mappedFileName, 'ThpK');
if (processFileName)
ExFreePool(processFileName);
ExAcquireFastMutex(&Client->StateMutex);
if (NT_SUCCESS(status))
{
Client->VerifiedProcess = PsGetCurrentProcess();
Client->VerifiedProcessId = PsGetCurrentProcessId();
Client->VerifiedRangeBase = memoryBasicInfo.BaseAddress;
Client->VerifiedRangeSize = memoryBasicInfo.RegionSize;
}
Client->VerificationStatus = status;
MemoryBarrier();
Client->VerificationSucceeded = NT_SUCCESS(status);
Client->VerificationPerformed = TRUE;
ExReleaseFastMutex(&Client->StateMutex);
}
NTSTATUS KpiVerifyClient(
__in PVOID CodeAddress,
__in_bcount(SignatureSize) PUCHAR Signature,
__in ULONG SignatureSize,
__in PKPH_CLIENT Client
)
{
PUCHAR signature;
PAGED_CODE();
__try
{
ProbeForRead(Signature, SignatureSize, 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
if (SignatureSize > KPH_SIGNATURE_MAX_SIZE)
return STATUS_INVALID_PARAMETER_3;
signature = ExAllocatePoolWithTag(PagedPool, SignatureSize, 'ThpK');
if (!signature)
return STATUS_INSUFFICIENT_RESOURCES;
__try
{
memcpy(signature, Signature, SignatureSize);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
ExFreePoolWithTag(signature, 'ThpK');
return GetExceptionCode();
}
KphVerifyClient(Client, CodeAddress, Signature, SignatureSize);
ExFreePoolWithTag(signature, 'ThpK');
return Client->VerificationStatus;
}
VOID KphGenerateKeysClient(
__inout PKPH_CLIENT Client
)
{
ULONGLONG interruptTime;
ULONG seed;
KPH_KEY l1Key;
KPH_KEY l2Key;
PAGED_CODE();
if (Client->KeysGenerated)
return;
interruptTime = KeQueryInterruptTime();
seed = (ULONG)(interruptTime >> 32) | (ULONG)interruptTime | PtrToUlong(Client);
l1Key = RtlRandomEx(&seed) | 0x80000000; // Make sure the key is nonzero
do
{
l2Key = RtlRandomEx(&seed) | 0x80000000;
} while (l2Key == l1Key);
ExAcquireFastMutex(&Client->StateMutex);
if (!Client->KeysGenerated)
{
Client->L1Key = l1Key;
Client->L2Key = l2Key;
MemoryBarrier();
Client->KeysGenerated = TRUE;
}
ExReleaseFastMutex(&Client->StateMutex);
}
NTSTATUS KphRetrieveKeyViaApc(
__inout PKPH_CLIENT Client,
__in KPH_KEY_LEVEL KeyLevel,
__inout PIRP Irp
)
{
PIO_APC_ROUTINE userApcRoutine;
KPH_KEY key;
PAGED_CODE();
if (!Client->VerificationSucceeded)
return STATUS_ACCESS_DENIED;
MemoryBarrier();
if (PsGetCurrentProcess() != Client->VerifiedProcess ||
PsGetCurrentProcessId() != Client->VerifiedProcessId)
{
return STATUS_ACCESS_DENIED;
}
userApcRoutine = Irp->Overlay.AsynchronousParameters.UserApcRoutine;
if (!userApcRoutine)
return STATUS_INVALID_PARAMETER;
if ((ULONG_PTR)userApcRoutine < (ULONG_PTR)Client->VerifiedRangeBase ||
(ULONG_PTR)userApcRoutine >= (ULONG_PTR)Client->VerifiedRangeBase + Client->VerifiedRangeSize)
{
return STATUS_ACCESS_DENIED;
}
KphGenerateKeysClient(Client);
switch (KeyLevel)
{
case KphKeyLevel1:
key = Client->L1Key;
break;
case KphKeyLevel2:
key = Client->L2Key;
break;
default:
return STATUS_INVALID_PARAMETER;
}
Irp->Overlay.AsynchronousParameters.UserApcContext = UlongToPtr(key);
return STATUS_SUCCESS;
}
NTSTATUS KphValidateKey(
__in KPH_KEY_LEVEL RequiredKeyLevel,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
PAGED_CODE();
if (AccessMode == KernelMode)
return STATUS_SUCCESS;
if (Key && Client->VerificationSucceeded && Client->KeysGenerated)
{
MemoryBarrier();
switch (RequiredKeyLevel)
{
case KphKeyLevel1:
if (Key == Client->L1Key || Key == Client->L2Key)
return STATUS_SUCCESS;
else
KphpBackoffKey(Client);
break;
case KphKeyLevel2:
if (Key == Client->L2Key)
return STATUS_SUCCESS;
else
KphpBackoffKey(Client);
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
return STATUS_ACCESS_DENIED;
}
VOID KphpBackoffKey(
__in PKPH_CLIENT Client
)
{
LARGE_INTEGER backoffTime;
PAGED_CODE();
// Serialize to make it impossible for a single client to bypass the backoff by creating
// multiple threads.
ExAcquireFastMutex(&Client->KeyBackoffMutex);
backoffTime.QuadPart = -KPH_KEY_BACKOFF_TIME;
KeDelayExecutionThread(KernelMode, FALSE, &backoffTime);
ExReleaseFastMutex(&Client->KeyBackoffMutex);
}

449
KProcessHacker/vm.c Normal file
View File

@ -0,0 +1,449 @@
/*
* KProcessHacker
*
* Copyright (C) 2010-2016 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 <kph.h>
ULONG KphpGetCopyExceptionInfo(
__in PEXCEPTION_POINTERS ExceptionInfo,
__out PBOOLEAN HaveBadAddress,
__out PULONG_PTR BadAddress
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, KphCopyVirtualMemory)
#pragma alloc_text(PAGE, KpiReadVirtualMemoryUnsafe)
#endif
#define KPH_STACK_COPY_BYTES 0x200
#define KPH_POOL_COPY_BYTES 0x10000
#define KPH_MAPPED_COPY_PAGES 14
#define KPH_POOL_COPY_THRESHOLD 0x3ff
ULONG KphpGetCopyExceptionInfo(
__in PEXCEPTION_POINTERS ExceptionInfo,
__out PBOOLEAN HaveBadAddress,
__out PULONG_PTR BadAddress
)
{
PEXCEPTION_RECORD exceptionRecord;
*HaveBadAddress = FALSE;
exceptionRecord = ExceptionInfo->ExceptionRecord;
if ((exceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) ||
(exceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) ||
(exceptionRecord->ExceptionCode == STATUS_IN_PAGE_ERROR))
{
if (exceptionRecord->NumberParameters > 1)
{
/* We have the address. */
*HaveBadAddress = TRUE;
*BadAddress = exceptionRecord->ExceptionInformation[1];
}
}
return EXCEPTION_EXECUTE_HANDLER;
}
/**
* Copies memory from one process to another.
*
* \param FromProcess The source process.
* \param FromAddress The source address.
* \param ToProcess The target process.
* \param ToAddress The target address.
* \param BufferLength The number of bytes to copy.
* \param AccessMode The mode in which to perform access checks.
* \param ReturnLength A variable which receives the number of bytes copied.
*/
NTSTATUS KphCopyVirtualMemory(
__in PEPROCESS FromProcess,
__in PVOID FromAddress,
__in PEPROCESS ToProcess,
__in PVOID ToAddress,
__in SIZE_T BufferLength,
__in KPROCESSOR_MODE AccessMode,
__out PSIZE_T ReturnLength
)
{
UCHAR stackBuffer[KPH_STACK_COPY_BYTES];
PVOID buffer;
PFN_NUMBER mdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + KPH_MAPPED_COPY_PAGES + 1];
PMDL mdl = (PMDL)mdlBuffer;
PVOID mappedAddress;
SIZE_T mappedTotalSize;
SIZE_T blockSize;
SIZE_T stillToCopy;
KAPC_STATE apcState;
PVOID sourceAddress;
PVOID targetAddress;
BOOLEAN doMappedCopy;
BOOLEAN pagesLocked;
BOOLEAN copyingToTarget = FALSE;
BOOLEAN probing = FALSE;
BOOLEAN mapping = FALSE;
BOOLEAN haveBadAddress;
ULONG_PTR badAddress;
PAGED_CODE();
sourceAddress = FromAddress;
targetAddress = ToAddress;
// We don't check if buffer == NULL when freeing. If buffer doesn't need to be freed, set to
// stackBuffer, not NULL.
buffer = stackBuffer;
mappedTotalSize = (KPH_MAPPED_COPY_PAGES - 2) * PAGE_SIZE;
if (mappedTotalSize > BufferLength)
mappedTotalSize = BufferLength;
stillToCopy = BufferLength;
blockSize = mappedTotalSize;
while (stillToCopy)
{
// If we're at the last copy block, copy the remaining bytes instead of the whole block
// size.
if (blockSize > stillToCopy)
blockSize = stillToCopy;
// Choose the best method based on the number of bytes left to copy.
if (blockSize > KPH_POOL_COPY_THRESHOLD)
{
doMappedCopy = TRUE;
}
else
{
doMappedCopy = FALSE;
if (blockSize <= KPH_STACK_COPY_BYTES)
{
if (buffer != stackBuffer)
ExFreePoolWithTag(buffer, 'ChpK');
buffer = stackBuffer;
}
else
{
// Don't allocate the buffer if we've done so already. Note that the block size
// never increases, so this allocation will always be OK.
if (buffer == stackBuffer)
{
// Keep trying to allocate a buffer.
while (TRUE)
{
buffer = ExAllocatePoolWithTag(NonPagedPool, blockSize, 'ChpK');
// Stop trying if we got a buffer.
if (buffer)
break;
blockSize /= 2;
// Use the stack buffer if we can.
if (blockSize <= KPH_STACK_COPY_BYTES)
{
buffer = stackBuffer;
break;
}
}
}
}
}
// Reset state.
mappedAddress = NULL;
pagesLocked = FALSE;
copyingToTarget = FALSE;
KeStackAttachProcess(FromProcess, &apcState);
__try
{
// Probe only if this is the first time.
if (sourceAddress == FromAddress && AccessMode != KernelMode)
{
probing = TRUE;
ProbeForRead(sourceAddress, BufferLength, sizeof(UCHAR));
probing = FALSE;
}
if (doMappedCopy)
{
// Initialize the MDL.
MmInitializeMdl(mdl, sourceAddress, blockSize);
MmProbeAndLockPages(mdl, AccessMode, IoReadAccess);
pagesLocked = TRUE;
// Map the pages.
mappedAddress = MmMapLockedPagesSpecifyCache(
mdl,
KernelMode,
MmCached,
NULL,
FALSE,
HighPagePriority
);
if (!mappedAddress)
{
// Insufficient resources; exit.
mapping = TRUE;
ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
memcpy(buffer, sourceAddress, blockSize);
}
KeUnstackDetachProcess(&apcState);
// Attach to the target process and copy the contents out.
KeStackAttachProcess(ToProcess, &apcState);
// Probe only if this is the first time.
if (targetAddress == ToAddress && AccessMode != KernelMode)
{
probing = TRUE;
ProbeForWrite(targetAddress, BufferLength, sizeof(UCHAR));
probing = FALSE;
}
// Copy the data.
copyingToTarget = TRUE;
if (doMappedCopy)
memcpy(targetAddress, mappedAddress, blockSize);
else
memcpy(targetAddress, buffer, blockSize);
}
__except (KphpGetCopyExceptionInfo(
GetExceptionInformation(),
&haveBadAddress,
&badAddress
))
{
KeUnstackDetachProcess(&apcState);
// If we mapped the pages, unmap them.
if (mappedAddress)
MmUnmapLockedPages(mappedAddress, mdl);
// If we locked the pages, unlock them.
if (pagesLocked)
MmUnlockPages(mdl);
// If we allocated pool storage, free it.
if (buffer != stackBuffer)
ExFreePoolWithTag(buffer, 'ChpK');
// If we failed when probing or mapping, return the error status.
if (probing || mapping)
return GetExceptionCode();
// Determine which copy failed.
if (copyingToTarget && haveBadAddress)
{
*ReturnLength = (ULONG)(badAddress - (ULONG_PTR)sourceAddress);
}
else
{
*ReturnLength = BufferLength - stillToCopy;
}
return STATUS_PARTIAL_COPY;
}
KeUnstackDetachProcess(&apcState);
if (doMappedCopy)
{
MmUnmapLockedPages(mappedAddress, mdl);
MmUnlockPages(mdl);
}
stillToCopy -= blockSize;
sourceAddress = (PVOID)((ULONG_PTR)sourceAddress + blockSize);
targetAddress = (PVOID)((ULONG_PTR)targetAddress + blockSize);
}
if (buffer != stackBuffer)
ExFreePoolWithTag(buffer, 'ChpK');
*ReturnLength = BufferLength;
return STATUS_SUCCESS;
}
/**
* Copies process or kernel memory into the current process.
*
* \param ProcessHandle A handle to a process. The handle must have PROCESS_VM_READ access. This
* parameter may be NULL if \a BaseAddress lies above the user-mode range.
* \param BaseAddress The address from which memory is to be copied.
* \param Buffer A buffer which receives the copied memory.
* \param BufferSize The number of bytes to copy.
* \param NumberOfBytesRead A variable which receives the number of bytes copied to the buffer.
* \param Key An access key. If no valid L2 key is provided, the function fails.
* \param Client The client that initiated the request.
* \param AccessMode The mode in which to perform access checks.
*/
NTSTATUS KpiReadVirtualMemoryUnsafe(
__in_opt HANDLE ProcessHandle,
__in PVOID BaseAddress,
__out_bcount(BufferSize) PVOID Buffer,
__in SIZE_T BufferSize,
__out_opt PSIZE_T NumberOfBytesRead,
__in_opt KPH_KEY Key,
__in PKPH_CLIENT Client,
__in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status;
PEPROCESS process;
SIZE_T numberOfBytesRead;
PAGED_CODE();
if (!NT_SUCCESS(status = KphValidateKey(KphKeyLevel2, Key, Client, AccessMode)))
return status;
if (AccessMode != KernelMode)
{
if (
(ULONG_PTR)BaseAddress + BufferSize < (ULONG_PTR)BaseAddress ||
(ULONG_PTR)Buffer + BufferSize < (ULONG_PTR)Buffer ||
(ULONG_PTR)Buffer + BufferSize > (ULONG_PTR)MmHighestUserAddress
)
{
return STATUS_ACCESS_VIOLATION;
}
if (NumberOfBytesRead)
{
__try
{
ProbeForWrite(NumberOfBytesRead, sizeof(SIZE_T), sizeof(SIZE_T));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
}
}
if (BufferSize != 0)
{
// Select the appropriate copy method.
if ((ULONG_PTR)BaseAddress + BufferSize > (ULONG_PTR)MmHighestUserAddress)
{
ULONG_PTR page;
ULONG_PTR pageEnd;
status = KphValidateAddressForSystemModules(BaseAddress, BufferSize);
if (!NT_SUCCESS(status))
return status;
// Kernel memory copy (unsafe)
page = (ULONG_PTR)BaseAddress & ~(PAGE_SIZE - 1);
pageEnd = ((ULONG_PTR)BaseAddress + BufferSize - 1) & ~(PAGE_SIZE - 1);
__try
{
// This will obviously fail if any of the pages aren't resident.
for (; page <= pageEnd; page += PAGE_SIZE)
{
if (!MmIsAddressValid((PVOID)page))
ExRaiseStatus(STATUS_ACCESS_VIOLATION);
}
memcpy(Buffer, BaseAddress, BufferSize);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return GetExceptionCode();
}
numberOfBytesRead = BufferSize;
status = STATUS_SUCCESS;
}
else
{
// User memory copy (safe)
status = ObReferenceObjectByHandle(
ProcessHandle,
PROCESS_VM_READ,
*PsProcessType,
AccessMode,
&process,
NULL
);
if (NT_SUCCESS(status))
{
status = KphCopyVirtualMemory(
process,
BaseAddress,
PsGetCurrentProcess(),
Buffer,
BufferSize,
AccessMode,
&numberOfBytesRead
);
ObDereferenceObject(process);
}
}
}
else
{
numberOfBytesRead = 0;
status = STATUS_SUCCESS;
}
if (NumberOfBytesRead)
{
if (AccessMode != KernelMode)
{
__try
{
*NumberOfBytesRead = numberOfBytesRead;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// Don't mess with the status.
NOTHING;
}
}
else
{
*NumberOfBytesRead = numberOfBytesRead;
}
}
return status;
}

685
LICENSE.txt Normal file
View File

@ -0,0 +1,685 @@
Process Hacker is distributed under the GNU GPL version 3, with the
following exception:
Permission is granted to dynamically (but not statically) link this
program with independent modules, regardless of the license terms of
these independent modules, provided that this program is not modified
in any way. An independent module is a module which is not derived
from or based on this program. If you modify this program, this
additional permission no longer applies unless authorized by the
copyright holders.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

81
ProcessHacker.sln Normal file
View File

@ -0,0 +1,81 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{2758DC86-368B-430C-9D29-F1EF20032A71}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessHacker", "ProcessHacker\ProcessHacker.vcxproj", "{0271DD27-6707-4290-8DFE-285702B7115D}"
ProjectSection(ProjectDependencies) = postProject
{477D0215-F252-41A1-874B-F27E3EA1ED17} = {477D0215-F252-41A1-874B-F27E3EA1ED17}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phlib", "phlib\phlib.vcxproj", "{477D0215-F252-41A1-874B-F27E3EA1ED17}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fixlib", "tools\fixlib\fixlib.vcxproj", "{31F4AA06-7ED5-4A6D-B901-19AD4BD16175}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "peview", "tools\peview\peview.vcxproj", "{72C124A2-3C80-41C6-ABA1-C4948B713204}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FD3C278D-BD40-4551-AE67-4DE196F8D7F6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phlib-test", "tests\phlib-test\phlib-test.vcxproj", "{0C21014E-BC90-4AE5-AA32-398445C13B28}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomSignTool", "tools\CustomSignTool\CustomSignTool.vcxproj", "{E8CD0A41-1537-4EA6-98AC-E80CD59C478E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0271DD27-6707-4290-8DFE-285702B7115D}.Debug|Win32.ActiveCfg = Debug|Win32
{0271DD27-6707-4290-8DFE-285702B7115D}.Debug|Win32.Build.0 = Debug|Win32
{0271DD27-6707-4290-8DFE-285702B7115D}.Debug|x64.ActiveCfg = Debug|x64
{0271DD27-6707-4290-8DFE-285702B7115D}.Debug|x64.Build.0 = Debug|x64
{0271DD27-6707-4290-8DFE-285702B7115D}.Release|Win32.ActiveCfg = Release|Win32
{0271DD27-6707-4290-8DFE-285702B7115D}.Release|Win32.Build.0 = Release|Win32
{0271DD27-6707-4290-8DFE-285702B7115D}.Release|x64.ActiveCfg = Release|x64
{0271DD27-6707-4290-8DFE-285702B7115D}.Release|x64.Build.0 = Release|x64
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Debug|Win32.ActiveCfg = Debug|Win32
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Debug|Win32.Build.0 = Debug|Win32
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Debug|x64.ActiveCfg = Debug|x64
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Debug|x64.Build.0 = Debug|x64
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Release|Win32.ActiveCfg = Release|Win32
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Release|Win32.Build.0 = Release|Win32
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Release|x64.ActiveCfg = Release|x64
{477D0215-F252-41A1-874B-F27E3EA1ED17}.Release|x64.Build.0 = Release|x64
{31F4AA06-7ED5-4A6D-B901-19AD4BD16175}.Debug|Win32.ActiveCfg = Debug|Win32
{31F4AA06-7ED5-4A6D-B901-19AD4BD16175}.Debug|x64.ActiveCfg = Debug|Win32
{31F4AA06-7ED5-4A6D-B901-19AD4BD16175}.Release|Win32.ActiveCfg = Release|Win32
{31F4AA06-7ED5-4A6D-B901-19AD4BD16175}.Release|x64.ActiveCfg = Release|Win32
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Debug|Win32.ActiveCfg = Debug|Win32
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Debug|Win32.Build.0 = Debug|Win32
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Debug|x64.ActiveCfg = Debug|x64
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Debug|x64.Build.0 = Debug|x64
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Release|Win32.ActiveCfg = Release|Win32
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Release|Win32.Build.0 = Release|Win32
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Release|x64.ActiveCfg = Release|x64
{72C124A2-3C80-41C6-ABA1-C4948B713204}.Release|x64.Build.0 = Release|x64
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Debug|Win32.ActiveCfg = Debug|Win32
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Debug|Win32.Build.0 = Debug|Win32
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Debug|x64.ActiveCfg = Debug|Win32
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Release|Win32.ActiveCfg = Release|Win32
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Release|Win32.Build.0 = Release|Win32
{0C21014E-BC90-4AE5-AA32-398445C13B28}.Release|x64.ActiveCfg = Release|Win32
{E8CD0A41-1537-4EA6-98AC-E80CD59C478E}.Debug|Win32.ActiveCfg = Debug|Win32
{E8CD0A41-1537-4EA6-98AC-E80CD59C478E}.Debug|x64.ActiveCfg = Debug|x64
{E8CD0A41-1537-4EA6-98AC-E80CD59C478E}.Release|Win32.ActiveCfg = Release|Win32
{E8CD0A41-1537-4EA6-98AC-E80CD59C478E}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{31F4AA06-7ED5-4A6D-B901-19AD4BD16175} = {2758DC86-368B-430C-9D29-F1EF20032A71}
{72C124A2-3C80-41C6-ABA1-C4948B713204} = {2758DC86-368B-430C-9D29-F1EF20032A71}
{0C21014E-BC90-4AE5-AA32-398445C13B28} = {FD3C278D-BD40-4551-AE67-4DE196F8D7F6}
{E8CD0A41-1537-4EA6-98AC-E80CD59C478E} = {2758DC86-368B-430C-9D29-F1EF20032A71}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,569 @@
EXPORTS
;
; phlib exports
;
; ref
PhAutoDereferenceObject
PhCreateAlloc
PhCreateObject
PhCreateObjectType
PhCreateObjectTypeEx
PhDeleteAutoPool
PhDereferenceObject
PhDereferenceObjectDeferDelete
PhDereferenceObjectEx
PhDrainAutoPool
PhGetObjectType
PhGetObjectTypeInformation
PhInitializeAutoPool
PhReferenceObject
PhReferenceObjectEx
PhReferenceObjectSafe
; queuedlock
PhfAcquireQueuedLockExclusive
PhfAcquireQueuedLockShared
PhfPulseAllCondition
PhfPulseCondition
PhfQueueWakeEvent
PhfReleaseQueuedLockExclusive
PhfReleaseQueuedLockShared
PhfSetWakeEvent
PhfWaitForCondition
PhfWaitForConditionEx
PhfWaitForWakeEvent
PhfWakeForReleaseQueuedLock
; phconfig
PhGlobalDpi DATA
PhHeapHandle DATA
PhIsExecutingInWow64
PhLibImageBase DATA
PhOsVersion DATA
PhSystemBasicInformation DATA
ProcessAllAccess DATA
ProcessQueryAccess DATA
ThreadAllAccess DATA
ThreadQueryAccess DATA
ThreadSetAccess DATA
WindowsVersion DATA
; phbasesup
PhAddElementAvlTree
PhAddEntryHashtable
PhAddEntryHashtableEx
PhAddItemArray
PhAddItemList
PhAddItemPointerList
PhAddItemsArray
PhAddItemSimpleHashtable
PhAddItemsList
PhAllocate
PhAllocateExSafe
PhAllocateFromFreeList
PhAllocatePage
PhAllocateSafe
PhAppendBytesBuilder
PhAppendBytesBuilder2
PhAppendBytesBuilderEx
PhAppendCharStringBuilder
PhAppendCharStringBuilder2
PhAppendFormatStringBuilder
PhAppendFormatStringBuilder_V
PhAppendStringBuilder
PhAppendStringBuilder2
PhAppendStringBuilderEx
PhBufferToHexString
PhBufferToHexStringEx
PhClearArray
PhClearHashtable
PhClearList
PhCompareStringRef
PhCompareStringZNatural
PhConcatStringRef2
PhConcatStringRef3
PhConcatStrings
PhConcatStrings_V
PhConcatStrings2
PhConvertMultiByteToUtf16
PhConvertMultiByteToUtf16Ex
PhConvertUtf16ToAsciiEx
PhConvertUtf16ToMultiByte
PhConvertUtf16ToMultiByteEx
PhConvertUtf16ToUtf8
PhConvertUtf16ToUtf8Buffer
PhConvertUtf16ToUtf8Ex
PhConvertUtf16ToUtf8Size
PhConvertUtf8ToUtf16
PhConvertUtf8ToUtf16Buffer
PhConvertUtf8ToUtf16Ex
PhConvertUtf8ToUtf16Size
PhCopyBytesZ
PhCopyStringZ
PhCopyStringZFromBytes
PhCopyStringZFromMultiByte
PhCountStringZ
PhCreateBytes
PhCreateBytesEx
PhCreateHashtable
PhCreateList
PhCreatePointerList
PhCreateSimpleHashtable
PhCreateString
PhCreateStringEx
PhCreateThread
PhDecodeUnicodeDecoder
PhDeleteArray
PhDeleteBytesBuilder
PhDeleteCallback
PhDeleteFreeList
PhDeleteStringBuilder
PhDivideSinglesBySingle
PhDosErrorToNtStatus
PhDuplicateBytesZ
PhDuplicateBytesZSafe
PhDuplicateStringZ
PhEncodeUnicode
PhEnumAvlTree
PhEnumHashtable
PhEnumPointerListEx
PhEqualStringRef
PhExponentiate
PhExponentiate64
PhfAcquireRundownProtection
PhfBeginInitOnce
PhfEndInitOnce
PhFillMemoryUlong
PhFinalArrayItems
PhFinalBytesBuilderBytes
PhFinalStringBuilderString
PhFindCharInStringRef
PhFindElementAvlTree
PhFindEntryHashtable
PhFindItemList
PhFindItemPointerList
PhFindItemSimpleHashtable
PhFindLastCharInStringRef
PhFindStringInStringRef
PhfInitializeBarrier
PhfInitializeEvent
PhfInitializeInitOnce
PhfInitializeRundownProtection
PhFormat
PhFormatString
PhFormatString_V
PhFormatToBuffer
PhFree
PhFreePage
PhFreeToFreeList
PhfReleaseRundownProtection
PhfResetEvent
PhfSetEvent
PhfWaitForBarrier
PhfWaitForEvent
PhfWaitForRundownProtection
PhGetPrimeNumber
PhHashBytes
PhHashStringRef
PhHexStringToBuffer
PhInitializeArray
PhInitializeAvlTree
PhInitializeBytesBuilder
PhInitializeCallback
PhInitializeFreeList
PhInitializeStringBuilder
PhInsertItemList
PhInsertItemsList
PhInsertStringBuilder
PhInsertStringBuilder2
PhInsertStringBuilderEx
PhIntegerToString64
PhInvokeCallback
PhLocalTimeToSystemTime
PhLowerBoundElementAvlTree
PhLowerDualBoundElementAvlTree
PhMaximumElementAvlTree
PhMinimumElementAvlTree
PhNtStatusFileNotFound
PhNtStatusToDosError
PhPredecessorElementAvlTree
PhPrintTimeSpan
PhQuerySystemTime
PhQueryTimeZoneBias
PhReAllocate
PhReAllocateSafe
PhReferenceEmptyString
PhRegisterCallback
PhRegisterCallbackEx
PhRemoveElementAvlTree
PhRemoveEntryHashtable
PhRemoveItemArray
PhRemoveItemList
PhRemoveItemPointerList
PhRemoveItemsArray
PhRemoveItemSimpleHashtable
PhRemoveItemsList
PhRemoveStringBuilder
PhResizeArray
PhResizeList
PhRoundUpToPowerOfTwo
PhSplitStringRefAtChar
PhSplitStringRefAtLastChar
PhSplitStringRefAtString
PhSplitStringRefEx
PhStringToDouble
PhStringToInteger64
PhSuccessorElementAvlTree
PhSystemTimeToLocalTime
PhTrimStringRef
PhUnregisterCallback
PhUpperBoundElementAvlTree
PhUpperDualBoundElementAvlTree
PhWriteUnicodeDecoder
PhZeroExtendToUtf16Buffer
PhZeroExtendToUtf16Ex
; phnative
PhCreateFileWin32
PhCreateFileWin32Ex
PhCreateKey
PhDeleteFileWin32
PhDisconnectNamedPipe
PhEnumDirectoryFile
PhEnumDirectoryObjects
PhEnumFileStreams
PhEnumGenericModules
PhEnumHandles
PhEnumHandlesEx
PhEnumKernelModules
PhEnumPagefiles
PhEnumProcessEnvironmentVariables
PhEnumProcesses
PhEnumProcessesEx
PhEnumProcessesForSession
PhEnumProcessModules
PhEnumProcessModules32
PhEnumProcessModules32Ex
PhEnumProcessModulesEx
PhFindProcessInformation
PhFindProcessInformationByImageName
PhGetFileName
PhGetFileSize
PhGetJobProcessIdList
PhGetKernelFileName
PhGetObjectSecurity
PhGetOwnTokenAttributes
PhGetProcedureAddressRemote
PhGetProcessCommandLine
PhGetProcessDepStatus
PhGetProcessEnvironment
PhGetProcessImageFileName
PhGetProcessImageFileNameByProcessId
PhGetProcessImageFileNameWin32
PhGetProcessIsDotNet
PhGetProcessIsDotNetEx
PhGetProcessMappedFileName
PhGetProcessPebString
PhGetProcessWindowTitle
PhGetProcessWorkingSetInformation
PhGetProcessWsCounters
PhGetTokenGroups
PhGetTokenIntegrityLevel
PhGetTokenOwner
PhGetTokenPrimaryGroup
PhGetTokenPrivileges
PhGetTokenUser
PhImpersonateClientOfNamedPipe
PhInjectDllProcess
PhListenNamedPipe
PhOpenKey
PhOpenProcess = PhOpenProcessPublic
PhOpenThread = PhOpenThreadPublic
PhOpenThreadProcess
PhPeekNamedPipe
PhQueryFullAttributesFileWin32
PhQueryKey
PhQueryValueKey
PhResolveDevicePrefix
PhSetFileSize
PhSetObjectSecurity
PhSetTokenIsVirtualizationEnabled
PhSetTokenPrivilege
PhSetTokenPrivilege2
PhSetTokenSessionId
PhTerminateProcess = PhTerminateProcessPublic
PhTransceiveNamedPipe
PhUnloadDllProcess
PhUnloadDriver
PhUpdateDosDevicePrefixes
PhUpdateMupDevicePrefixes
PhWaitForNamedPipe
; phutil
PhAdjustRectangleToBounds
PhAdjustRectangleToWorkingArea
PhCenterRectangle
PhCenterWindow
PhCompareUnicodeStringZIgnoreMenuPrefix
PhCreateOpenFileDialog
PhCreateProcess
PhCreateProcessAsUser
PhCreateProcessWin32
PhCreateProcessWin32Ex
PhCreateSaveFileDialog
PhDeleteImageVersionInfo
PhDereferenceObjects
PhEllipsisString
PhEllipsisStringPath
PhEscapeCommandLinePart
PhEscapeStringForMenuPrefix
PhExpandEnvironmentStrings
PhFinalHash
PhFindIntegerSiKeyValuePairs
PhFindLoaderEntry
PhFindStringSiKeyValuePairs
PhFormatDate
PhFormatDateTime
PhFormatDecimal
PhFormatGuid
PhFormatImageVersionInfo
PhFormatSize
PhFormatTime
PhFormatTimeSpan
PhFormatTimeSpanRelative
PhFormatUInt64
PhFreeFileDialog
PhGenerateGuid
PhGenerateGuidFromName
PhGenerateRandomAlphaString
PhGetApplicationDirectory
PhGetApplicationFileName
PhGetBaseName
PhGetDllFileName
PhGetFileDialogFileName
PhGetFileDialogFilterIndex
PhGetFileDialogOptions
PhGetFileVersionInfo
PhGetFileVersionInfoLangCodePage
PhGetFileVersionInfoString
PhGetFileVersionInfoString2
PhGetFullPath
PhGetKnownLocation
PhGetMessage
PhGetNtMessage
PhGetSystemDirectory
PhGetSystemRoot
PhGetWin32Message
PhInitializeHash
PhInitializeImageVersionInfo
PhIsExecutablePacked
PhMapFlags1
PhMapFlags2
PhMatchWildcards
PhParseCommandLine
PhParseCommandLineFuzzy
PhParseCommandLinePart
PhQueryRegistryString
PhReferenceObjects
PhSetFileDialogFileName
PhSetFileDialogFilter
PhSetFileDialogOptions
PhShellExecute
PhShellExecuteEx
PhShellExploreFile
PhShellOpenKey
PhShellProperties
PhShowConfirmMessage
PhShowContinueStatus
PhShowFileDialog
PhShowMessage
PhShowMessage_V
PhShowStatus
PhUpdateHash
; circbuf
PhClearCircularBuffer_FLOAT
PhClearCircularBuffer_PVOID
PhClearCircularBuffer_ULONG
PhClearCircularBuffer_ULONG64
PhCopyCircularBuffer_FLOAT
PhCopyCircularBuffer_PVOID
PhCopyCircularBuffer_ULONG
PhCopyCircularBuffer_ULONG64
PhDeleteCircularBuffer_FLOAT
PhDeleteCircularBuffer_PVOID
PhDeleteCircularBuffer_ULONG
PhDeleteCircularBuffer_ULONG64
PhInitializeCircularBuffer_FLOAT
PhInitializeCircularBuffer_PVOID
PhInitializeCircularBuffer_ULONG
PhInitializeCircularBuffer_ULONG64
PhResizeCircularBuffer_FLOAT
PhResizeCircularBuffer_PVOID
PhResizeCircularBuffer_ULONG
PhResizeCircularBuffer_ULONG64
; cpysave
PhGetGenericTreeNewLines
PhGetTreeNewText
; emenu
PhCreateEMenu
PhCreateEMenuItem
PhDestroyEMenu
PhDestroyEMenuItem
PhFindEMenuItem
PhIndexOfEMenuItem
PhInsertEMenuItem
PhLoadResourceEMenuItem
PhModifyEMenuItem
PhRemoveAllEMenuItems
PhRemoveEMenuItem
PhSetFlagsAllEMenuItems
PhSetFlagsEMenuItem
PhShowEMenu
; fastlock
PhDeleteFastLock
PhfAcquireFastLockExclusive
PhfAcquireFastLockShared
PhfReleaseFastLockExclusive
PhfReleaseFastLockShared
PhfTryAcquireFastLockExclusive
PhfTryAcquireFastLockShared
PhInitializeFastLock
; filestream
PhCreateFileStream
PhCreateFileStream2
PhFlushFileStream
PhGetPositionFileStream
PhLockFileStream
PhReadFileStream
PhSeekFileStream
PhUnlockFileStream
PhVerifyFileStream
PhWriteFileStream
PhWriteStringAsUtf8FileStream
PhWriteStringAsUtf8FileStream2
PhWriteStringAsUtf8FileStreamEx
PhWriteStringFormatAsUtf8FileStream
PhWriteStringFormatAsUtf8FileStream_V
; graph
PhDeleteGraphState
PhDrawGraphDirect
PhGetDrawInfoGraphBuffers
PhGraphStateGetDrawInfo
PhInitializeGraphState
PhSetGraphText
; guisup
PhAddComboBoxStrings
PhAddLayoutItem
PhAddLayoutItemEx
PhAddListViewColumn
PhAddListViewItem
PhAddTabControlTab
PhDeleteLayoutManager
PhFindListViewItemByFlags
PhFindListViewItemByParam
PhGetComboBoxString
PhGetFileShellIcon
PhGetListBoxString
PhGetListViewItemImageIndex
PhGetListViewItemParam
PhGetSelectedListViewItemParam
PhGetSelectedListViewItemParams
PhGetStockApplicationIcon
PhGetWindowText
PhGetWindowTextEx
PhIconToBitmap
PhInitializeLayoutManager
PhLayoutManagerLayout
PhLoadIcon
PhLoadListViewColumnSettings
PhModalPropertySheet
PhRemoveListViewItem
PhSaveListViewColumnSettings
PhSelectComboBoxString
PhSetClipboardString
PhSetControlTheme
PhSetExtendedListView
PhSetHeaderSortIcon
PhSetImageListBitmap
PhSetListViewItemImageIndex
PhSetListViewSubItem
PhSetStateAllListViewItems
; hndlinfo
PhEnumObjectTypes
PhFormatNativeKeyName
PhGetHandleInformation
PhGetHandleInformationEx
PhStdGetClientIdName
; lsasup
PhGetSidFullName
PhLookupName
PhLookupPrivilegeDisplayName
PhLookupPrivilegeName
PhLookupPrivilegeValue
PhLookupSid
PhOpenLsaPolicy
PhSidToStringSid
; secedit
PhCreateSecurityPage
PhEditSecurity
PhGetAccessEntries
PhGetAccessString
PhGetSeObjectSecurity
PhSetSeObjectSecurity
PhStdGetObjectSecurity
PhStdSetObjectSecurity
; svcsup
PhEnumServices
PhGetServiceConfig
PhGetServiceDelayedAutoStart
PhGetServiceDescription
PhGetServiceErrorControlInteger
PhGetServiceErrorControlString
PhGetServiceNameFromTag
PhGetServiceStartTypeInteger
PhGetServiceStartTypeString
PhGetServiceStateString
PhGetServiceTypeInteger
PhGetServiceTypeString
PhGetThreadServiceTag
PhOpenService
PhQueryServiceVariableSize
PhSetServiceDelayedAutoStart
; symprv
PhCreateSymbolProvider
PhGetLineFromAddress
PhGetModuleFromAddress
PhGetSymbolFromAddress
PhGetSymbolFromName
PhLoadModuleSymbolProvider
PhSetOptionsSymbolProvider
PhSetSearchPathSymbolProvider
PhStackWalk
PhWalkThreadStack
PhWriteMiniDumpProcess
; verify
PhVerifyFile
; workqueue
PhDeleteWorkQueue
PhGetGlobalWorkQueue
PhInitializeWorkQueue
PhInitializeWorkQueueEnvironment
PhQueueItemWorkQueue
PhQueueItemWorkQueueEx
PhWaitForWorkQueue

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="Process Hacker"
processorArchitecture="*"
version="2.0.0.0"
type="win32"
/>
<description>Process Hacker</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2011/WindowsSettings">
<disableWindowFiltering>true</disableWindowFiltering>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,421 @@
<?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>{0271DD27-6707-4290-8DFE-285702B7115D}</ProjectGuid>
<RootNamespace>ProcessHacker</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)bin\$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</GenerateManifest>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</GenerateManifest>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\phnt\include;..\phlib\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_PHLIB_;_PHAPP_;_WINDOWS;WIN32;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>phlib.lib;ntdll.lib;winsta.lib;comctl32.lib;version.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
<AdditionalLibraryDirectories>..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>ProcessHacker.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>update_rev.bat</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating revision number...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\phnt\include;..\phlib\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_PHLIB_;_PHAPP_;_WINDOWS;WIN64;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>phlib.lib;ntdll.lib;winsta.lib;comctl32.lib;version.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
<AdditionalLibraryDirectories>..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>ProcessHacker.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>update_rev.bat</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating revision number...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\phnt\include;..\phlib\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_PHLIB_;_PHAPP_;_WINDOWS;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<AdditionalDependencies>phlib.lib;ntdll.lib;winsta.lib;comctl32.lib;version.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
<SetChecksum>true</SetChecksum>
<MinimumRequiredVersion>5.01</MinimumRequiredVersion>
<AdditionalLibraryDirectories>..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>ProcessHacker.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>update_rev.bat</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating revision number...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\phnt\include;..\phlib\include;include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_PHLIB_;_PHAPP_;_WINDOWS;WIN64;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<TreatWarningAsError>true</TreatWarningAsError>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<AdditionalDependencies>phlib.lib;ntdll.lib;winsta.lib;comctl32.lib;version.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
<SetChecksum>true</SetChecksum>
<MinimumRequiredVersion>5.02</MinimumRequiredVersion>
<AdditionalLibraryDirectories>..\phlib\bin\$(Configuration)$(PlatformArchitecture);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>ProcessHacker.def</ModuleDefinitionFile>
</Link>
<PreBuildEvent>
<Command>update_rev.bat</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Generating revision number...</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="about.c" />
<ClCompile Include="actions.c" />
<ClCompile Include="affinity.c" />
<ClCompile Include="anawait.c" />
<ClCompile Include="appsup.c" />
<ClCompile Include="chcol.c" />
<ClCompile Include="chdlg.c" />
<ClCompile Include="chproc.c" />
<ClCompile Include="cmdmode.c" />
<ClCompile Include="colmgr.c" />
<ClCompile Include="dbgcon.c" />
<ClCompile Include="extmgr.c" />
<ClCompile Include="findobj.c" />
<ClCompile Include="gdihndl.c" />
<ClCompile Include="hidnproc.c" />
<ClCompile Include="hndllist.c" />
<ClCompile Include="hndlmenu.c" />
<ClCompile Include="hndlprp.c" />
<ClCompile Include="hndlprv.c" />
<ClCompile Include="hndlstat.c" />
<ClCompile Include="infodlg.c" />
<ClCompile Include="itemtips.c" />
<ClCompile Include="jobprp.c" />
<ClCompile Include="log.c" />
<ClCompile Include="logwnd.c" />
<ClCompile Include="main.c" />
<ClCompile Include="mainwnd.c" />
<ClCompile Include="mdump.c" />
<ClCompile Include="memedit.c" />
<ClCompile Include="memlist.c" />
<ClCompile Include="memlists.c" />
<ClCompile Include="memprot.c" />
<ClCompile Include="memprv.c" />
<ClCompile Include="memrslt.c" />
<ClCompile Include="memsrch.c" />
<ClCompile Include="miniinfo.c" />
<ClCompile Include="modlist.c" />
<ClCompile Include="modprv.c" />
<ClCompile Include="mtgndlg.c" />
<ClCompile Include="netlist.c" />
<ClCompile Include="netprv.c" />
<ClCompile Include="netstk.c" />
<ClCompile Include="notifico.c" />
<ClCompile Include="ntobjprp.c" />
<ClCompile Include="options.c" />
<ClCompile Include="pagfiles.c" />
<ClCompile Include="pcre\pcre2posix.c" />
<ClCompile Include="pcre\pcre2_auto_possess.c" />
<ClCompile Include="pcre\pcre2_chartables.c" />
<ClCompile Include="pcre\pcre2_compile.c" />
<ClCompile Include="pcre\pcre2_config.c" />
<ClCompile Include="pcre\pcre2_context.c" />
<ClCompile Include="pcre\pcre2_dfa_match.c" />
<ClCompile Include="pcre\pcre2_error.c" />
<ClCompile Include="pcre\pcre2_find_bracket.c" />
<ClCompile Include="pcre\pcre2_jit_compile.c" />
<ClCompile Include="pcre\pcre2_maketables.c" />
<ClCompile Include="pcre\pcre2_match.c" />
<ClCompile Include="pcre\pcre2_match_data.c" />
<ClCompile Include="pcre\pcre2_newline.c" />
<ClCompile Include="pcre\pcre2_ord2utf.c" />
<ClCompile Include="pcre\pcre2_pattern_info.c" />
<ClCompile Include="pcre\pcre2_serialize.c" />
<ClCompile Include="pcre\pcre2_string_utils.c" />
<ClCompile Include="pcre\pcre2_study.c" />
<ClCompile Include="pcre\pcre2_substitute.c" />
<ClCompile Include="pcre\pcre2_substring.c" />
<ClCompile Include="pcre\pcre2_tables.c" />
<ClCompile Include="pcre\pcre2_ucd.c" />
<ClCompile Include="pcre\pcre2_valid_utf.c" />
<ClCompile Include="pcre\pcre2_xclass.c" />
<ClCompile Include="phsvc\clapi.c" />
<ClCompile Include="phsvc\svcapi.c" />
<ClCompile Include="phsvc\svcapiport.c" />
<ClCompile Include="phsvc\svcclient.c" />
<ClCompile Include="phsvc\svcmain.c" />
<ClCompile Include="plugin.c" />
<ClCompile Include="plugman.c" />
<ClCompile Include="procgrp.c" />
<ClCompile Include="procmtgn.c" />
<ClCompile Include="procprp.c" />
<ClCompile Include="procprv.c" />
<ClCompile Include="procrec.c" />
<ClCompile Include="proctree.c" />
<ClCompile Include="prpgenv.c" />
<ClCompile Include="prpggen.c" />
<ClCompile Include="prpghndl.c" />
<ClCompile Include="prpgjob.c" />
<ClCompile Include="prpgmem.c" />
<ClCompile Include="prpgmod.c" />
<ClCompile Include="prpgperf.c" />
<ClCompile Include="prpgsrv.c" />
<ClCompile Include="prpgstat.c" />
<ClCompile Include="prpgthrd.c" />
<ClCompile Include="prpgtok.c" />
<ClCompile Include="runas.c" />
<ClCompile Include="sessprp.c" />
<ClCompile Include="sessshad.c" />
<ClCompile Include="settings.c" />
<ClCompile Include="srvcr.c" />
<ClCompile Include="srvctl.c" />
<ClCompile Include="srvlist.c" />
<ClCompile Include="srvprp.c" />
<ClCompile Include="srvprv.c" />
<ClCompile Include="sessmsg.c" />
<ClCompile Include="sysinfo.c" />
<ClCompile Include="syssccpu.c" />
<ClCompile Include="sysscio.c" />
<ClCompile Include="sysscmem.c" />
<ClCompile Include="thrdlist.c" />
<ClCompile Include="thrdprv.c" />
<ClCompile Include="thrdstk.c" />
<ClCompile Include="tokprp.c" />
<ClCompile Include="mxml\mxml-attr.c" />
<ClCompile Include="mxml\mxml-entity.c" />
<ClCompile Include="mxml\mxml-file.c" />
<ClCompile Include="mxml\mxml-index.c" />
<ClCompile Include="mxml\mxml-node.c" />
<ClCompile Include="mxml\mxml-private.c" />
<ClCompile Include="mxml\mxml-search.c" />
<ClCompile Include="mxml\mxml-set.c" />
<ClCompile Include="mxml\mxml-string.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\actions.h" />
<ClInclude Include="include\colmgr.h" />
<ClInclude Include="include\extmgr.h" />
<ClInclude Include="include\extmgri.h" />
<ClInclude Include="include\heapstruct.h" />
<ClInclude Include="include\hndllist.h" />
<ClInclude Include="include\hndlmenu.h" />
<ClInclude Include="include\hndlprv.h" />
<ClInclude Include="include\mainwndp.h" />
<ClInclude Include="include\memlist.h" />
<ClInclude Include="include\miniinfop.h" />
<ClInclude Include="include\modlist.h" />
<ClInclude Include="include\modprv.h" />
<ClInclude Include="include\netlist.h" />
<ClInclude Include="include\netprv.h" />
<ClInclude Include="include\notifico.h" />
<ClInclude Include="include\notificop.h" />
<ClInclude Include="include\phfwddef.h" />
<ClInclude Include="include\phsvccl.h" />
<ClInclude Include="include\procmtgn.h" />
<ClInclude Include="include\procprv.h" />
<ClInclude Include="include\proctree.h" />
<ClInclude Include="include\srvlist.h" />
<ClInclude Include="include\srvprv.h" />
<ClInclude Include="include\sysinfo.h" />
<ClInclude Include="include\thrdlist.h" />
<ClInclude Include="include\thrdprv.h" />
<ClInclude Include="include\phuisup.h" />
<ClInclude Include="include\miniinfo.h" />
<ClInclude Include="mxml\config.h" />
<ClInclude Include="include\hidnproc.h" />
<ClInclude Include="include\memsrch.h" />
<ClInclude Include="mxml\mxml-private.h" />
<ClInclude Include="mxml\mxml.h" />
<ClInclude Include="include\phapp.h" />
<ClInclude Include="include\phsvc.h" />
<ClInclude Include="include\phsvcapi.h" />
<ClInclude Include="include\phappres.h" />
<ClInclude Include="pcre\config.h" />
<ClInclude Include="pcre\pcre2.h" />
<ClInclude Include="pcre\pcre2posix.h" />
<ClInclude Include="pcre\pcre2_internal.h" />
<ClInclude Include="pcre\pcre2_intmodedep.h" />
<ClInclude Include="pcre\pcre2_ucp.h" />
<ClInclude Include="include\procgrp.h" />
<ClInclude Include="sdk\phdk.h" />
<ClInclude Include="include\phplug.h" />
<ClInclude Include="include\procprpp.h" />
<ClInclude Include="include\memprv.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="include\settings.h" />
<ClInclude Include="include\settingsp.h" />
<ClInclude Include="include\sysinfop.h" />
</ItemGroup>
<ItemGroup>
<None Include="ProcessHacker.def" />
<None Include="resources\application.ico" />
<None Include="resources\application_go.ico" />
<None Include="resources\cog.ico" />
<None Include="resources\cog_go.ico" />
<None Include="resources\cross.bmp" />
<None Include="ProcessHacker.ico" />
<None Include="resources\ProcessHacker.png" />
<None Include="resources\tick.bmp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ProcessHacker.rc" />
<ResourceCompile Include="version.rc" />
</ItemGroup>
<ItemGroup>
<Manifest Include="ProcessHacker.manifest">
<SubType>Designer</SubType>
</Manifest>
</ItemGroup>
<ItemGroup>
<Image Include="resources\folder.ico" />
<Image Include="resources\magnifier.ico" />
<Image Include="resources\pencil.ico" />
<Image Include="resources\pin.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,620 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Headers">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resources">
<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>
<Filter Include="Process Hacker">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="PCRE">
<UniqueIdentifier>{3fa0b151-12c1-4832-94fb-e16c52584b65}</UniqueIdentifier>
</Filter>
<Filter Include="Mini-XML">
<UniqueIdentifier>{eaabb14f-9091-4b18-8764-45c8350f4887}</UniqueIdentifier>
</Filter>
<Filter Include="phsvc">
<UniqueIdentifier>{84a3be0b-42cf-42ae-bcd3-16f165caa0db}</UniqueIdentifier>
</Filter>
<Filter Include="PCRE\Headers">
<UniqueIdentifier>{e72b6c69-b510-4578-9ed5-34a16d8dffc1}</UniqueIdentifier>
</Filter>
<Filter Include="Mini-XML\Headers">
<UniqueIdentifier>{c4b014d0-6bd0-4848-a23f-e639563d998e}</UniqueIdentifier>
</Filter>
<Filter Include="Module">
<UniqueIdentifier>{67c40321-0b28-4c16-8c48-dc0b64c148d7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="about.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="actions.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="affinity.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="anawait.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="appsup.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="chcol.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="chdlg.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="chproc.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="cmdmode.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="dbgcon.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="findobj.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="gdihndl.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hidnproc.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hndlprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hndlprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hndlstat.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="infodlg.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="itemtips.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="jobprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="log.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="logwnd.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="main.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="mainwnd.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="mdump.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memedit.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memprot.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memrslt.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memsrch.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="modprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="netprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="netstk.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="notifico.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="ntobjprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="options.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="pagfiles.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="plugin.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="plugman.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="procprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="procprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="procrec.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="proctree.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="runas.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="sessprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="settings.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="srvcr.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="srvprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="srvprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="sysinfo.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="thrdprv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="thrdstk.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="tokprp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-attr.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-entity.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-file.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-index.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-node.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-private.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-search.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-set.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="mxml\mxml-string.c">
<Filter>Mini-XML</Filter>
</ClCompile>
<ClCompile Include="srvctl.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="srvlist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="modlist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="phsvc\svcmain.c">
<Filter>phsvc</Filter>
</ClCompile>
<ClCompile Include="phsvc\svcclient.c">
<Filter>phsvc</Filter>
</ClCompile>
<ClCompile Include="phsvc\svcapiport.c">
<Filter>phsvc</Filter>
</ClCompile>
<ClCompile Include="phsvc\svcapi.c">
<Filter>phsvc</Filter>
</ClCompile>
<ClCompile Include="phsvc\clapi.c">
<Filter>phsvc</Filter>
</ClCompile>
<ClCompile Include="sessmsg.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="sessshad.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="colmgr.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="netlist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="extmgr.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="thrdlist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hndllist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memlists.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="memlist.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="miniinfo.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="procgrp.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_compile.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_config.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_context.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_dfa_match.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_error.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_maketables.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_match.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_match_data.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_newline.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_ord2utf.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_pattern_info.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_serialize.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_string_utils.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_study.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_substitute.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_substring.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_tables.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_ucd.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_valid_utf.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_xclass.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_auto_possess.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_chartables.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_jit_compile.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2posix.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="pcre\pcre2_find_bracket.c">
<Filter>PCRE</Filter>
</ClCompile>
<ClCompile Include="procmtgn.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="mtgndlg.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="hndlmenu.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="syssccpu.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="sysscmem.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="sysscio.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpggen.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgstat.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgperf.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgthrd.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgtok.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgmod.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgmem.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgenv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpghndl.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgjob.c">
<Filter>Process Hacker</Filter>
</ClCompile>
<ClCompile Include="prpgsrv.c">
<Filter>Process Hacker</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\hidnproc.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\memsrch.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phapp.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="sdk\phdk.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phplug.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\procprpp.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\settings.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\settingsp.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phsvcapi.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phsvc.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phsvccl.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phappres.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\colmgr.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\mainwndp.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\extmgr.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\extmgri.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\sysinfop.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\notifico.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\heapstruct.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\miniinfop.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\miniinfo.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\procgrp.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\sysinfo.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\config.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\pcre2.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\pcre2_internal.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\pcre2_intmodedep.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\pcre2_ucp.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="pcre\pcre2posix.h">
<Filter>PCRE\Headers</Filter>
</ClInclude>
<ClInclude Include="mxml\config.h">
<Filter>Mini-XML\Headers</Filter>
</ClInclude>
<ClInclude Include="mxml\mxml-private.h">
<Filter>Mini-XML\Headers</Filter>
</ClInclude>
<ClInclude Include="mxml\mxml.h">
<Filter>Mini-XML\Headers</Filter>
</ClInclude>
<ClInclude Include="include\notificop.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\procmtgn.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phfwddef.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\procprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\srvprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\netprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\modprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\thrdprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\hndlprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\memprv.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\phuisup.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\proctree.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\srvlist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\netlist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\thrdlist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\modlist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\hndllist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\memlist.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\hndlmenu.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="include\actions.h">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="resources\cross.bmp">
<Filter>Resources</Filter>
</None>
<None Include="ProcessHacker.ico">
<Filter>Resources</Filter>
</None>
<None Include="resources\ProcessHacker.png">
<Filter>Resources</Filter>
</None>
<None Include="resources\tick.bmp">
<Filter>Resources</Filter>
</None>
<None Include="resources\application.ico">
<Filter>Resources</Filter>
</None>
<None Include="resources\cog.ico">
<Filter>Resources</Filter>
</None>
<None Include="resources\application_go.ico">
<Filter>Resources</Filter>
</None>
<None Include="resources\cog_go.ico">
<Filter>Resources</Filter>
</None>
<None Include="ProcessHacker.def">
<Filter>Module</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ProcessHacker.rc">
<Filter>Resources</Filter>
</ResourceCompile>
<ResourceCompile Include="version.rc">
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Manifest Include="ProcessHacker.manifest">
<Filter>Resources</Filter>
</Manifest>
</ItemGroup>
<ItemGroup>
<Image Include="resources\pin.ico">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\pencil.ico">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\folder.ico">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\magnifier.ico">
<Filter>Resources</Filter>
</Image>
</ItemGroup>
</Project>

184
ProcessHacker/about.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Process Hacker -
* about dialog
*
* Copyright (C) 2010-2016 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 <phapp.h>
#include <phappres.h>
#include <procprv.h>
#include <srvprv.h>
#include <netprv.h>
#include <modprv.h>
#include <thrdprv.h>
#include <hndlprv.h>
#include <memprv.h>
#include <symprv.h>
static INT_PTR CALLBACK PhpAboutDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PPH_STRING appName;
#if (PHAPP_VERSION_REVISION != 0)
appName = PhFormatString(
L"Process Hacker %u.%u.%u",
PHAPP_VERSION_MAJOR,
PHAPP_VERSION_MINOR,
PHAPP_VERSION_REVISION
);
#else
appName = PhFormatString(
L"Process Hacker %u.%u",
PHAPP_VERSION_MAJOR,
PHAPP_VERSION_MINOR
);
#endif
SetDlgItemText(hwndDlg, IDC_ABOUT_NAME, appName->Buffer);
PhDereferenceObject(appName);
SetDlgItemText(hwndDlg, IDC_CREDITS,
L" Installer by XhmikosR\n"
L"Thanks to:\n"
L" dmex\n"
L" Donors - thank you for your support!\n"
L" <a href=\"http://forum.sysinternals.com\">Sysinternals Forums</a>\n"
L" <a href=\"http://www.reactos.org\">ReactOS</a>\n"
L"Process Hacker uses the following components:\n"
L" <a href=\"http://www.minixml.org\">Mini-XML</a> by Michael Sweet\n"
L" <a href=\"http://www.pcre.org\">PCRE</a>\n"
L" MD5 code by Jouni Malinen\n"
L" SHA1 code by Filip Navara, based on code by Steve Reid\n"
L" <a href=\"http://www.famfamfam.com/lab/icons/silk\">Silk icons</a>\n"
L" <a href=\"http://www.fatcow.com/free-icons\">Farm-fresh web icons</a>\n"
);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
case IDC_DIAGNOSTICS:
{
PhShowInformationDialog(hwndDlg, PH_AUTO_T(PH_STRING, PhGetDiagnosticsString())->Buffer, 0);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case NM_CLICK:
{
switch (header->idFrom)
{
case IDC_CREDITS:
case IDC_LINK_SF:
PhShellExecute(hwndDlg, ((PNMLINK)header)->item.szUrl, NULL);
break;
}
}
break;
}
}
break;
}
return FALSE;
}
VOID PhShowAboutDialog(
_In_ HWND ParentWindowHandle
)
{
DialogBox(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_ABOUT),
ParentWindowHandle,
PhpAboutDlgProc
);
}
FORCEINLINE ULONG PhpGetObjectTypeObjectCount(
_In_ PPH_OBJECT_TYPE ObjectType
)
{
PH_OBJECT_TYPE_INFORMATION info;
PhGetObjectTypeInformation(ObjectType, &info);
return info.NumberOfObjects;
}
PPH_STRING PhGetDiagnosticsString(
VOID
)
{
PH_STRING_BUILDER stringBuilder;
PhInitializeStringBuilder(&stringBuilder, 50);
PhAppendFormatStringBuilder(&stringBuilder, L"OBJECT INFORMATION\r\n");
#define OBJECT_TYPE_COUNT(Type) PhAppendFormatStringBuilder(&stringBuilder, \
L#Type L": %u objects\r\n", PhpGetObjectTypeObjectCount(Type))
// ref
OBJECT_TYPE_COUNT(PhObjectTypeObject);
// basesup
OBJECT_TYPE_COUNT(PhStringType);
OBJECT_TYPE_COUNT(PhBytesType);
OBJECT_TYPE_COUNT(PhListType);
OBJECT_TYPE_COUNT(PhPointerListType);
OBJECT_TYPE_COUNT(PhHashtableType);
OBJECT_TYPE_COUNT(PhFileStreamType);
// ph
OBJECT_TYPE_COUNT(PhSymbolProviderType);
OBJECT_TYPE_COUNT(PhProcessItemType);
OBJECT_TYPE_COUNT(PhServiceItemType);
OBJECT_TYPE_COUNT(PhNetworkItemType);
OBJECT_TYPE_COUNT(PhModuleProviderType);
OBJECT_TYPE_COUNT(PhModuleItemType);
OBJECT_TYPE_COUNT(PhThreadProviderType);
OBJECT_TYPE_COUNT(PhThreadItemType);
OBJECT_TYPE_COUNT(PhHandleProviderType);
OBJECT_TYPE_COUNT(PhHandleItemType);
OBJECT_TYPE_COUNT(PhMemoryItemType);
return PhFinalStringBuilderString(&stringBuilder);
}

3126
ProcessHacker/actions.c Normal file

File diff suppressed because it is too large Load Diff

315
ProcessHacker/affinity.c Normal file
View File

@ -0,0 +1,315 @@
/*
* Process Hacker -
* process affinity editor
*
* Copyright (C) 2010-2015 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/>.
*/
/*
* The affinity dialog was originally created to support the modification
* of process affinity masks, but now supports modifying thread affinity
* and generic masks.
*/
#include <phapp.h>
#include <procprv.h>
#include <thrdprv.h>
#include <windowsx.h>
typedef struct _AFFINITY_DIALOG_CONTEXT
{
PPH_PROCESS_ITEM ProcessItem;
PPH_THREAD_ITEM ThreadItem;
ULONG_PTR AffinityMask;
ULONG_PTR NewAffinityMask;
} AFFINITY_DIALOG_CONTEXT, *PAFFINITY_DIALOG_CONTEXT;
INT_PTR CALLBACK PhpProcessAffinityDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhShowProcessAffinityDialog(
_In_ HWND ParentWindowHandle,
_In_opt_ PPH_PROCESS_ITEM ProcessItem,
_In_opt_ PPH_THREAD_ITEM ThreadItem
)
{
AFFINITY_DIALOG_CONTEXT context;
assert(!!ProcessItem != !!ThreadItem); // make sure we have one and not the other
context.ProcessItem = ProcessItem;
context.ThreadItem = ThreadItem;
DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_AFFINITY),
ParentWindowHandle,
PhpProcessAffinityDlgProc,
(LPARAM)&context
);
}
BOOLEAN PhShowProcessAffinityDialog2(
_In_ HWND ParentWindowHandle,
_In_ ULONG_PTR AffinityMask,
_Out_ PULONG_PTR NewAffinityMask
)
{
AFFINITY_DIALOG_CONTEXT context;
context.ProcessItem = NULL;
context.ThreadItem = NULL;
context.AffinityMask = AffinityMask;
if (DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_AFFINITY),
ParentWindowHandle,
PhpProcessAffinityDlgProc,
(LPARAM)&context
) == IDOK)
{
*NewAffinityMask = context.NewAffinityMask;
return TRUE;
}
else
{
return FALSE;
}
}
static INT_PTR CALLBACK PhpProcessAffinityDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
NTSTATUS status;
PAFFINITY_DIALOG_CONTEXT context = (PAFFINITY_DIALOG_CONTEXT)lParam;
SYSTEM_BASIC_INFORMATION systemBasicInfo;
ULONG_PTR systemAffinityMask;
ULONG_PTR affinityMask;
ULONG i;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
systemAffinityMask = 0;
if (context->ProcessItem)
{
HANDLE processHandle;
PROCESS_BASIC_INFORMATION basicInfo;
if (NT_SUCCESS(status = PhOpenProcess(
&processHandle,
ProcessQueryAccess,
context->ProcessItem->ProcessId
)))
{
status = PhGetProcessBasicInformation(processHandle, &basicInfo);
if (NT_SUCCESS(status))
affinityMask = basicInfo.AffinityMask;
NtClose(processHandle);
}
}
else if (context->ThreadItem)
{
HANDLE threadHandle;
THREAD_BASIC_INFORMATION basicInfo;
HANDLE processHandle;
PROCESS_BASIC_INFORMATION processBasicInfo;
if (NT_SUCCESS(status = PhOpenThread(
&threadHandle,
ThreadQueryAccess,
context->ThreadItem->ThreadId
)))
{
status = PhGetThreadBasicInformation(threadHandle, &basicInfo);
if (NT_SUCCESS(status))
{
affinityMask = basicInfo.AffinityMask;
// A thread's affinity mask is restricted by the process affinity mask,
// so use that as the system affinity mask.
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
basicInfo.ClientId.UniqueProcess
)))
{
if (NT_SUCCESS(PhGetProcessBasicInformation(processHandle, &processBasicInfo)))
systemAffinityMask = processBasicInfo.AffinityMask;
NtClose(processHandle);
}
}
NtClose(threadHandle);
}
}
else
{
affinityMask = context->AffinityMask;
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status) && systemAffinityMask == 0)
{
status = NtQuerySystemInformation(
SystemBasicInformation,
&systemBasicInfo,
sizeof(SYSTEM_BASIC_INFORMATION),
NULL
);
if (NT_SUCCESS(status))
systemAffinityMask = systemBasicInfo.ActiveProcessorsAffinityMask;
}
if (!NT_SUCCESS(status))
{
PhShowStatus(hwndDlg, L"Unable to retrieve the affinity", status, 0);
EndDialog(hwndDlg, IDCANCEL);
break;
}
// Disable the CPU checkboxes which aren't part of the system affinity mask,
// and check the CPU checkboxes which are part of the affinity mask.
for (i = 0; i < 8 * 8; i++)
{
if ((i < sizeof(ULONG_PTR) * 8) && ((systemAffinityMask >> i) & 0x1))
{
if ((affinityMask >> i) & 0x1)
{
Button_SetCheck(GetDlgItem(hwndDlg, IDC_CPU0 + i), BST_CHECKED);
}
}
else
{
EnableWindow(GetDlgItem(hwndDlg, IDC_CPU0 + i), FALSE);
}
}
}
break;
case WM_DESTROY:
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);
break;
case IDOK:
{
NTSTATUS status;
PAFFINITY_DIALOG_CONTEXT context = (PAFFINITY_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
ULONG i;
ULONG_PTR affinityMask;
// Work out the affinity mask.
affinityMask = 0;
for (i = 0; i < sizeof(ULONG_PTR) * 8; i++)
{
if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_CPU0 + i)) == BST_CHECKED)
affinityMask |= (ULONG_PTR)1 << i;
}
if (context->ProcessItem)
{
HANDLE processHandle;
if (NT_SUCCESS(status = PhOpenProcess(
&processHandle,
PROCESS_SET_INFORMATION,
context->ProcessItem->ProcessId
)))
{
status = PhSetProcessAffinityMask(processHandle, affinityMask);
NtClose(processHandle);
}
}
else if (context->ThreadItem)
{
HANDLE threadHandle;
if (NT_SUCCESS(status = PhOpenThread(
&threadHandle,
ThreadSetAccess,
context->ThreadItem->ThreadId
)))
{
status = PhSetThreadAffinityMask(threadHandle, affinityMask);
NtClose(threadHandle);
}
}
else
{
context->NewAffinityMask = affinityMask;
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status))
EndDialog(hwndDlg, IDOK);
else
PhShowStatus(hwndDlg, L"Unable to set the affinity", status, 0);
}
break;
case IDC_SELECTALL:
case IDC_DESELECTALL:
{
ULONG i;
for (i = 0; i < sizeof(ULONG_PTR) * 8; i++)
{
HWND checkBox = GetDlgItem(hwndDlg, IDC_CPU0 + i);
if (IsWindowEnabled(checkBox))
Button_SetCheck(checkBox, LOWORD(wParam) == IDC_SELECTALL ? BST_CHECKED : BST_UNCHECKED);
}
}
break;
}
}
break;
}
return FALSE;
}

1074
ProcessHacker/anawait.c Normal file

File diff suppressed because it is too large Load Diff

2208
ProcessHacker/appsup.c Normal file

File diff suppressed because it is too large Load Diff

422
ProcessHacker/chcol.c Normal file
View File

@ -0,0 +1,422 @@
/*
* Process Hacker -
* column chooser
*
* Copyright (C) 2010 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 <phapp.h>
#include <settings.h>
#include <windowsx.h>
typedef struct _COLUMNS_DIALOG_CONTEXT
{
HWND ControlHandle;
ULONG Type;
PPH_LIST Columns;
HWND InactiveList;
HWND ActiveList;
} COLUMNS_DIALOG_CONTEXT, *PCOLUMNS_DIALOG_CONTEXT;
INT_PTR CALLBACK PhpColumnsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhShowChooseColumnsDialog(
_In_ HWND ParentWindowHandle,
_In_ HWND ControlHandle,
_In_ ULONG Type
)
{
COLUMNS_DIALOG_CONTEXT context;
context.ControlHandle = ControlHandle;
context.Type = Type;
if (Type == PH_CONTROL_TYPE_TREE_NEW)
context.Columns = PhCreateList(TreeNew_GetColumnCount(ControlHandle));
else
return;
DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_CHOOSECOLUMNS),
ParentWindowHandle,
PhpColumnsDlgProc,
(LPARAM)&context
);
PhDereferenceObject(context.Columns);
}
static int __cdecl PhpColumnsCompareDisplayIndexTn(
_In_ const void *elem1,
_In_ const void *elem2
)
{
PPH_TREENEW_COLUMN column1 = *(PPH_TREENEW_COLUMN *)elem1;
PPH_TREENEW_COLUMN column2 = *(PPH_TREENEW_COLUMN *)elem2;
return uintcmp(column1->DisplayIndex, column2->DisplayIndex);
}
_Success_(return != -1)
static ULONG IndexOfStringInList(
_In_ PPH_LIST List,
_In_ PWSTR String
)
{
ULONG i;
for (i = 0; i < List->Count; i++)
{
if (PhEqualString2(List->Items[i], String, FALSE))
return i;
}
return -1;
}
INT_PTR CALLBACK PhpColumnsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PCOLUMNS_DIALOG_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PCOLUMNS_DIALOG_CONTEXT)lParam;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
}
else
{
context = (PCOLUMNS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
ULONG count;
ULONG total;
ULONG i;
PPH_LIST displayOrderList = NULL;
context->InactiveList = GetDlgItem(hwndDlg, IDC_INACTIVE);
context->ActiveList = GetDlgItem(hwndDlg, IDC_ACTIVE);
if (context->Type == PH_CONTROL_TYPE_TREE_NEW)
{
PH_TREENEW_COLUMN column;
count = 0;
total = TreeNew_GetColumnCount(context->ControlHandle);
i = 0;
displayOrderList = PhCreateList(total);
while (count < total)
{
if (TreeNew_GetColumn(context->ControlHandle, i, &column))
{
PPH_TREENEW_COLUMN copy;
if (column.Fixed)
{
i++;
total--;
continue;
}
copy = PhAllocateCopy(&column, sizeof(PH_TREENEW_COLUMN));
PhAddItemList(context->Columns, copy);
count++;
if (column.Visible)
{
PhAddItemList(displayOrderList, copy);
}
else
{
ListBox_AddString(context->InactiveList, column.Text);
}
}
i++;
}
qsort(displayOrderList->Items, displayOrderList->Count, sizeof(PVOID), PhpColumnsCompareDisplayIndexTn);
}
if (displayOrderList)
{
for (i = 0; i < displayOrderList->Count; i++)
{
if (context->Type == PH_CONTROL_TYPE_TREE_NEW)
{
PPH_TREENEW_COLUMN copy = displayOrderList->Items[i];
ListBox_AddString(context->ActiveList, copy->Text);
}
}
PhDereferenceObject(displayOrderList);
}
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList);
}
break;
case WM_DESTROY:
{
ULONG i;
for (i = 0; i < context->Columns->Count; i++)
PhFree(context->Columns->Items[i]);
RemoveProp(hwndDlg, PhMakeContextAtom());
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);
break;
case IDOK:
{
#define ORDER_LIMIT 100
PPH_LIST activeList;
ULONG activeCount;
ULONG i;
INT orderArray[ORDER_LIMIT];
INT maxOrder;
memset(orderArray, 0, sizeof(orderArray));
maxOrder = 0;
activeCount = ListBox_GetCount(context->ActiveList);
activeList = PhCreateList(activeCount);
for (i = 0; i < activeCount; i++)
PhAddItemList(activeList, PhGetListBoxString(context->ActiveList, i));
if (context->Type == PH_CONTROL_TYPE_TREE_NEW)
{
// Apply visiblity settings and build the order array.
TreeNew_SetRedraw(context->ControlHandle, FALSE);
for (i = 0; i < context->Columns->Count; i++)
{
PPH_TREENEW_COLUMN column = context->Columns->Items[i];
ULONG index;
index = IndexOfStringInList(activeList, column->Text);
column->Visible = index != -1;
TreeNew_SetColumn(context->ControlHandle, TN_COLUMN_FLAG_VISIBLE, column);
if (column->Visible && index < ORDER_LIMIT)
{
orderArray[index] = column->Id;
if ((ULONG)maxOrder < index + 1)
maxOrder = index + 1;
}
}
// Apply display order.
TreeNew_SetColumnOrderArray(context->ControlHandle, maxOrder, orderArray);
TreeNew_SetRedraw(context->ControlHandle, TRUE);
PhDereferenceObject(activeList);
InvalidateRect(context->ControlHandle, NULL, FALSE);
}
EndDialog(hwndDlg, IDOK);
}
break;
case IDC_INACTIVE:
{
switch (HIWORD(wParam))
{
case LBN_DBLCLK:
{
SendMessage(hwndDlg, WM_COMMAND, IDC_SHOW, 0);
}
break;
case LBN_SELCHANGE:
{
INT sel = ListBox_GetCurSel(context->InactiveList);
EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW), sel != -1);
}
break;
}
}
break;
case IDC_ACTIVE:
{
switch (HIWORD(wParam))
{
case LBN_DBLCLK:
{
SendMessage(hwndDlg, WM_COMMAND, IDC_HIDE, 0);
}
break;
case LBN_SELCHANGE:
{
INT sel = ListBox_GetCurSel(context->ActiveList);
INT count = ListBox_GetCount(context->ActiveList);
EnableWindow(GetDlgItem(hwndDlg, IDC_HIDE), sel != -1 && count != 1);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0 && sel != -1);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1 && sel != -1);
}
break;
}
}
break;
case IDC_SHOW:
{
INT sel;
INT count;
PPH_STRING string;
sel = ListBox_GetCurSel(context->InactiveList);
count = ListBox_GetCount(context->InactiveList);
if (string = PhGetListBoxString(context->InactiveList, sel))
{
ListBox_DeleteString(context->InactiveList, sel);
ListBox_AddString(context->ActiveList, string->Buffer);
PhDereferenceObject(string);
count--;
if (sel >= count - 1)
sel = count - 1;
ListBox_SetCurSel(context->InactiveList, sel);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList);
}
}
break;
case IDC_HIDE:
{
INT sel;
INT count;
PPH_STRING string;
sel = ListBox_GetCurSel(context->ActiveList);
count = ListBox_GetCount(context->ActiveList);
if (count != 1)
{
if (string = PhGetListBoxString(context->ActiveList, sel))
{
ListBox_DeleteString(context->ActiveList, sel);
ListBox_AddString(context->InactiveList, string->Buffer);
PhDereferenceObject(string);
count--;
if (sel >= count - 1)
sel = count - 1;
ListBox_SetCurSel(context->ActiveList, sel);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList);
SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList);
}
}
}
break;
case IDC_MOVEUP:
{
INT sel;
INT count;
PPH_STRING string;
sel = ListBox_GetCurSel(context->ActiveList);
count = ListBox_GetCount(context->ActiveList);
if (sel != 0)
{
if (string = PhGetListBoxString(context->ActiveList, sel))
{
ListBox_DeleteString(context->ActiveList, sel);
ListBox_InsertString(context->ActiveList, sel - 1, string->Buffer);
PhDereferenceObject(string);
sel -= 1;
ListBox_SetCurSel(context->ActiveList, sel);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1);
}
}
}
break;
case IDC_MOVEDOWN:
{
INT sel;
INT count;
PPH_STRING string;
sel = ListBox_GetCurSel(context->ActiveList);
count = ListBox_GetCount(context->ActiveList);
if (sel != count - 1)
{
if (string = PhGetListBoxString(context->ActiveList, sel))
{
ListBox_DeleteString(context->ActiveList, sel);
ListBox_InsertString(context->ActiveList, sel + 1, string->Buffer);
PhDereferenceObject(string);
sel += 1;
ListBox_SetCurSel(context->ActiveList, sel);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0);
EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1);
}
}
}
break;
}
}
break;
}
return FALSE;
}

358
ProcessHacker/chdlg.c Normal file
View File

@ -0,0 +1,358 @@
/*
* Process Hacker -
* choice dialog
*
* Copyright (C) 2010-2013 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 <phapp.h>
#include <settings.h>
#include <windowsx.h>
typedef struct _CHOICE_DIALOG_CONTEXT
{
PWSTR Title;
PWSTR Message;
PWSTR *Choices;
ULONG NumberOfChoices;
PWSTR Option;
ULONG Flags;
PPH_STRING *SelectedChoice;
PBOOLEAN SelectedOption;
PWSTR SavedChoicesSettingName;
HWND ComboBoxHandle;
} CHOICE_DIALOG_CONTEXT, *PCHOICE_DIALOG_CONTEXT;
INT_PTR CALLBACK PhpChoiceDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
/**
* Prompts the user for input.
*
* \remarks If \c PH_CHOICE_DIALOG_PASSWORD is specified, the string
* returned in \a SelectedChoice is NOT auto-dereferenced.
*/
BOOLEAN PhaChoiceDialog(
_In_ HWND ParentWindowHandle,
_In_ PWSTR Title,
_In_ PWSTR Message,
_In_opt_ PWSTR *Choices,
_In_opt_ ULONG NumberOfChoices,
_In_opt_ PWSTR Option,
_In_ ULONG Flags,
_Inout_ PPH_STRING *SelectedChoice,
_Inout_opt_ PBOOLEAN SelectedOption,
_In_opt_ PWSTR SavedChoicesSettingName
)
{
CHOICE_DIALOG_CONTEXT context;
context.Title = Title;
context.Message = Message;
context.Choices = Choices;
context.NumberOfChoices = NumberOfChoices;
context.Option = Option;
context.Flags = Flags;
context.SelectedChoice = SelectedChoice;
context.SelectedOption = SelectedOption;
context.SavedChoicesSettingName = SavedChoicesSettingName;
return DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_CHOOSE),
ParentWindowHandle,
PhpChoiceDlgProc,
(LPARAM)&context
) == IDOK;
}
INT_PTR CALLBACK PhpChoiceDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)lParam;
ULONG type;
SIZE_T i;
HWND comboBoxHandle;
HWND checkBoxHandle;
RECT checkBoxRect;
RECT rect;
ULONG diff;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
SetWindowText(hwndDlg, context->Title);
SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE), context->Message);
type = context->Flags & PH_CHOICE_DIALOG_TYPE_MASK;
// Select the control to show, depending on the type. This is
// because it is impossible to change the style of the combo box
// after it is created.
switch (type)
{
case PH_CHOICE_DIALOG_USER_CHOICE:
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICEUSER);
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICEUSER), SW_SHOW);
break;
case PH_CHOICE_DIALOG_PASSWORD:
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICESIMPLE);
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICESIMPLE), SW_SHOW);
// Disable combo box features since it isn't a combo box.
context->SavedChoicesSettingName = NULL;
break;
case PH_CHOICE_DIALOG_CHOICE:
default:
comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICE);
ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICE), SW_SHOW);
break;
}
context->ComboBoxHandle = comboBoxHandle;
checkBoxHandle = GetDlgItem(hwndDlg, IDC_OPTION);
if (type == PH_CHOICE_DIALOG_PASSWORD)
{
// Nothing
}
else if (type == PH_CHOICE_DIALOG_USER_CHOICE && context->SavedChoicesSettingName)
{
PPH_STRING savedChoices = PhGetStringSetting(context->SavedChoicesSettingName);
ULONG_PTR indexOfDelim;
PPH_STRING savedChoice;
i = 0;
// Split the saved choices using the delimiter.
while (i < savedChoices->Length / 2)
{
// BUG BUG BUG - what if the user saves "\s"?
indexOfDelim = PhFindStringInString(savedChoices, i, L"\\s");
if (indexOfDelim == -1)
indexOfDelim = savedChoices->Length / 2;
savedChoice = PhSubstring(savedChoices, i, indexOfDelim - i);
if (savedChoice->Length != 0)
{
PPH_STRING unescaped;
unescaped = PhUnescapeStringForDelimiter(savedChoice, '\\');
ComboBox_InsertString(comboBoxHandle, -1, unescaped->Buffer);
PhDereferenceObject(unescaped);
}
PhDereferenceObject(savedChoice);
i = indexOfDelim + 2;
}
PhDereferenceObject(savedChoices);
}
else
{
for (i = 0; i < context->NumberOfChoices; i++)
{
ComboBox_AddString(comboBoxHandle, context->Choices[i]);
}
context->SavedChoicesSettingName = NULL; // make sure we don't try to save the choices
}
if (type == PH_CHOICE_DIALOG_PASSWORD)
{
if (*context->SelectedChoice)
SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer);
Edit_SetSel(comboBoxHandle, 0, -1);
}
else if (type == PH_CHOICE_DIALOG_USER_CHOICE || type == PH_CHOICE_DIALOG_CHOICE)
{
// If we failed to choose a default choice based on what was specified,
// select the first one if possible, or set the text directly.
if (!(*context->SelectedChoice) || PhSelectComboBoxString(
comboBoxHandle, (*context->SelectedChoice)->Buffer, FALSE) == CB_ERR)
{
if (type == PH_CHOICE_DIALOG_USER_CHOICE && *context->SelectedChoice)
{
SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer);
}
else if (type == PH_CHOICE_DIALOG_CHOICE && context->NumberOfChoices != 0)
{
ComboBox_SetCurSel(comboBoxHandle, 0);
}
}
if (type == PH_CHOICE_DIALOG_USER_CHOICE)
ComboBox_SetEditSel(comboBoxHandle, 0, -1);
}
if (context->Option)
{
SetWindowText(checkBoxHandle, context->Option);
if (context->SelectedOption)
Button_SetCheck(checkBoxHandle, *context->SelectedOption ? BST_CHECKED : BST_UNCHECKED);
}
else
{
// Hide the check box and move the buttons up.
ShowWindow(checkBoxHandle, SW_HIDE);
GetWindowRect(checkBoxHandle, &checkBoxRect);
MapWindowPoints(NULL, hwndDlg, (POINT *)&checkBoxRect, 2);
GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect);
MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
diff = rect.top - checkBoxRect.top;
// OK
rect.top -= diff;
rect.bottom -= diff;
SetWindowPos(GetDlgItem(hwndDlg, IDOK), NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
// Cancel
GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rect);
MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2);
rect.top -= diff;
rect.bottom -= diff;
SetWindowPos(GetDlgItem(hwndDlg, IDCANCEL), NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
// Window
GetWindowRect(hwndDlg, &rect);
rect.bottom -= diff;
SetWindowPos(hwndDlg, NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)comboBoxHandle, TRUE);
}
break;
case WM_DESTROY:
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hwndDlg, IDCANCEL);
break;
case IDOK:
{
PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
PPH_STRING selectedChoice;
if ((context->Flags & PH_CHOICE_DIALOG_TYPE_MASK) != PH_CHOICE_DIALOG_PASSWORD)
{
selectedChoice = PH_AUTO(PhGetWindowText(context->ComboBoxHandle));
*context->SelectedChoice = selectedChoice;
}
else
{
// Password values are never auto-dereferenced.
selectedChoice = PhGetWindowText(context->ComboBoxHandle);
*context->SelectedChoice = selectedChoice;
}
if (context->Option && context->SelectedOption)
*context->SelectedOption = Button_GetCheck(GetDlgItem(hwndDlg, IDC_OPTION)) == BST_CHECKED;
if (context->SavedChoicesSettingName)
{
PH_STRING_BUILDER savedChoices;
ULONG i;
ULONG choicesToSave = PH_CHOICE_DIALOG_SAVED_CHOICES;
PPH_STRING choice;
PPH_STRING escaped;
PhInitializeStringBuilder(&savedChoices, 100);
// Push the selected choice to the top, then save the others.
if (selectedChoice->Length != 0)
{
escaped = PhEscapeStringForDelimiter(selectedChoice, '\\');
PhAppendStringBuilder(&savedChoices, &escaped->sr);
PhDereferenceObject(escaped);
PhAppendStringBuilder2(&savedChoices, L"\\s");
}
for (i = 1; i < choicesToSave; i++)
{
choice = PhGetComboBoxString(context->ComboBoxHandle, i - 1);
if (!choice)
break;
// Don't save the choice if it's the same as the one
// entered by the user (since we already saved it above).
if (PhEqualString(choice, selectedChoice, FALSE))
{
PhDereferenceObject(choice);
choicesToSave++; // useless for now, but may be needed in the future
continue;
}
escaped = PhEscapeStringForDelimiter(choice, '\\');
PhAppendStringBuilder(&savedChoices, &escaped->sr);
PhDereferenceObject(escaped);
PhDereferenceObject(choice);
PhAppendStringBuilder2(&savedChoices, L"\\s");
}
if (PhEndsWithString2(savedChoices.String, L"\\s", FALSE))
PhRemoveEndStringBuilder(&savedChoices, 2);
PhSetStringSetting2(context->SavedChoicesSettingName, &savedChoices.String->sr);
PhDeleteStringBuilder(&savedChoices);
}
EndDialog(hwndDlg, IDOK);
}
break;
}
}
break;
}
return FALSE;
}

315
ProcessHacker/chproc.c Normal file
View File

@ -0,0 +1,315 @@
/*
* Process Hacker -
* choose process dialog
*
* Copyright (C) 2010 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 <phapp.h>
#include <lsasup.h>
typedef struct _CHOOSE_PROCESS_DIALOG_CONTEXT
{
PWSTR Message;
HANDLE ProcessId;
PH_LAYOUT_MANAGER LayoutManager;
RECT MinimumSize;
HIMAGELIST ImageList;
HWND ListViewHandle;
} CHOOSE_PROCESS_DIALOG_CONTEXT, *PCHOOSE_PROCESS_DIALOG_CONTEXT;
INT_PTR CALLBACK PhpChooseProcessDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
BOOLEAN PhShowChooseProcessDialog(
_In_ HWND ParentWindowHandle,
_In_ PWSTR Message,
_Out_ PHANDLE ProcessId
)
{
CHOOSE_PROCESS_DIALOG_CONTEXT context;
context.Message = Message;
context.ProcessId = NULL;
if (DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_CHOOSEPROCESS),
ParentWindowHandle,
PhpChooseProcessDlgProc,
(LPARAM)&context
) == IDOK)
{
*ProcessId = context.ProcessId;
return TRUE;
}
else
{
return FALSE;
}
}
static VOID PhpRefreshProcessList(
_In_ HWND hwndDlg,
_In_ PCHOOSE_PROCESS_DIALOG_CONTEXT Context
)
{
NTSTATUS status;
HWND lvHandle;
PVOID processes;
PSYSTEM_PROCESS_INFORMATION process;
lvHandle = Context->ListViewHandle;
ListView_DeleteAllItems(lvHandle);
ImageList_RemoveAll(Context->ImageList);
if (!NT_SUCCESS(status = PhEnumProcesses(&processes)))
{
PhShowStatus(hwndDlg, L"Unable to enumerate processes", status, 0);
return;
}
ExtendedListView_SetRedraw(lvHandle, FALSE);
process = PH_FIRST_PROCESS(processes);
do
{
INT lvItemIndex;
PPH_STRING name;
HANDLE processHandle;
PPH_STRING fileName = NULL;
HICON icon = NULL;
WCHAR processIdString[PH_INT32_STR_LEN_1];
PPH_STRING userName = NULL;
INT imageIndex;
if (process->UniqueProcessId != SYSTEM_IDLE_PROCESS_ID)
name = PhCreateStringFromUnicodeString(&process->ImageName);
else
name = PhCreateString(SYSTEM_IDLE_PROCESS_NAME);
lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, name->Buffer, process->UniqueProcessId);
PhDereferenceObject(name);
if (NT_SUCCESS(PhOpenProcess(&processHandle, ProcessQueryAccess, process->UniqueProcessId)))
{
HANDLE tokenHandle;
PTOKEN_USER user;
if (!WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID)
PhGetProcessImageFileName(processHandle, &fileName);
if (NT_SUCCESS(PhOpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)))
{
if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user)))
{
userName = PhGetSidFullName(user->User.Sid, TRUE, NULL);
PhFree(user);
}
NtClose(tokenHandle);
}
NtClose(processHandle);
}
if (process->UniqueProcessId == SYSTEM_IDLE_PROCESS_ID && !userName && PhLocalSystemName)
PhSetReference(&userName, PhLocalSystemName);
if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID)
PhGetProcessImageFileNameByProcessId(process->UniqueProcessId, &fileName);
if (process->UniqueProcessId == SYSTEM_PROCESS_ID)
fileName = PhGetKernelFileName();
if (fileName)
PhMoveReference(&fileName, PhGetFileName(fileName));
icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", FALSE);
// Icon
if (icon)
{
imageIndex = ImageList_AddIcon(Context->ImageList, icon);
PhSetListViewItemImageIndex(Context->ListViewHandle, lvItemIndex, imageIndex);
DestroyIcon(icon);
}
// PID
PhPrintUInt32(processIdString, HandleToUlong(process->UniqueProcessId));
PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 1, processIdString);
// User Name
PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 2, PhGetString(userName));
if (userName) PhDereferenceObject(userName);
if (fileName) PhDereferenceObject(fileName);
} while (process = PH_NEXT_PROCESS(process));
PhFree(processes);
ExtendedListView_SortItems(lvHandle);
ExtendedListView_SetRedraw(lvHandle, TRUE);
}
INT_PTR CALLBACK PhpChooseProcessDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
PCHOOSE_PROCESS_DIALOG_CONTEXT context = NULL;
if (uMsg == WM_INITDIALOG)
{
context = (PCHOOSE_PROCESS_DIALOG_CONTEXT)lParam;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
}
else
{
context = (PCHOOSE_PROCESS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom());
if (uMsg == WM_DESTROY)
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
}
if (!context)
return FALSE;
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND lvHandle;
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
SetDlgItemText(hwndDlg, IDC_MESSAGE, context->Message);
PhInitializeLayoutManager(&context->LayoutManager, hwndDlg);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_MESSAGE), NULL,
PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_LIST), NULL,
PH_ANCHOR_ALL);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL,
PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDCANCEL), NULL,
PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REFRESH), NULL,
PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT);
PhLayoutManagerLayout(&context->LayoutManager);
context->MinimumSize.left = 0;
context->MinimumSize.top = 0;
context->MinimumSize.right = 280;
context->MinimumSize.bottom = 170;
MapDialogRect(hwndDlg, &context->MinimumSize);
context->ListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
context->ImageList = ImageList_Create(PhSmallIconSize.X, PhSmallIconSize.Y, ILC_COLOR32 | ILC_MASK, 0, 40);
PhSetListViewStyle(lvHandle, FALSE, TRUE);
PhSetControlTheme(lvHandle, L"explorer");
PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 180, L"Name");
PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 60, L"PID");
PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 160, L"User name");
PhSetExtendedListView(lvHandle);
ListView_SetImageList(lvHandle, context->ImageList, LVSIL_SMALL);
PhpRefreshProcessList(hwndDlg, context);
EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
}
break;
case WM_DESTROY:
{
ImageList_Destroy(context->ImageList);
PhDeleteLayoutManager(&context->LayoutManager);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
{
EndDialog(hwndDlg, IDCANCEL);
}
break;
case IDOK:
{
if (ListView_GetSelectedCount(context->ListViewHandle) == 1)
{
context->ProcessId = (HANDLE)PhGetSelectedListViewItemParam(context->ListViewHandle);
EndDialog(hwndDlg, IDOK);
}
}
break;
case IDC_REFRESH:
{
PhpRefreshProcessList(hwndDlg, context);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case LVN_ITEMCHANGED:
{
EnableWindow(GetDlgItem(hwndDlg, IDOK), ListView_GetSelectedCount(context->ListViewHandle) == 1);
}
break;
case NM_DBLCLK:
{
SendMessage(hwndDlg, WM_COMMAND, IDOK, 0);
}
break;
}
}
break;
case WM_SIZE:
{
PhLayoutManagerLayout(&context->LayoutManager);
}
break;
case WM_SIZING:
{
PhResizingMinimumSize((PRECT)lParam, wParam, context->MinimumSize.right, context->MinimumSize.bottom);
}
break;
}
return FALSE;
}

451
ProcessHacker/cmdmode.c Normal file
View File

@ -0,0 +1,451 @@
/*
* Process Hacker -
* command line action mode
*
* Copyright (C) 2010-2012 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 <phapp.h>
#include <svcsup.h>
NTSTATUS PhpGetDllBaseRemote(
_In_ HANDLE ProcessHandle,
_In_ PPH_STRINGREF BaseDllName,
_Out_ PVOID *DllBase
);
static HWND CommandModeWindowHandle;
#define PH_COMMAND_OPTION_HWND 1
BOOLEAN NTAPI PhpCommandModeOptionCallback(
_In_opt_ PPH_COMMAND_LINE_OPTION Option,
_In_opt_ PPH_STRING Value,
_In_opt_ PVOID Context
)
{
ULONG64 integer;
if (Option)
{
switch (Option->Id)
{
case PH_COMMAND_OPTION_HWND:
if (PhStringToInteger64(&Value->sr, 10, &integer))
CommandModeWindowHandle = (HWND)integer;
break;
}
}
return TRUE;
}
NTSTATUS PhCommandModeStart(
VOID
)
{
static PH_COMMAND_LINE_OPTION options[] =
{
{ PH_COMMAND_OPTION_HWND, L"hwnd", MandatoryArgumentType }
};
NTSTATUS status = STATUS_SUCCESS;
PH_STRINGREF commandLine;
PhUnicodeStringToStringRef(&NtCurrentPeb()->ProcessParameters->CommandLine, &commandLine);
PhParseCommandLine(
&commandLine,
options,
sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION),
PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS,
PhpCommandModeOptionCallback,
NULL
);
if (PhEqualString2(PhStartupParameters.CommandType, L"process", TRUE))
{
SIZE_T i;
SIZE_T processIdLength;
HANDLE processId;
HANDLE processHandle;
if (!PhStartupParameters.CommandObject)
return STATUS_INVALID_PARAMETER;
processIdLength = PhStartupParameters.CommandObject->Length / 2;
for (i = 0; i < processIdLength; i++)
{
if (!PhIsDigitCharacter(PhStartupParameters.CommandObject->Buffer[i]))
break;
}
if (i == processIdLength)
{
ULONG64 processId64;
if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &processId64))
return STATUS_INVALID_PARAMETER;
processId = (HANDLE)processId64;
}
else
{
PVOID processes;
PSYSTEM_PROCESS_INFORMATION process;
if (!NT_SUCCESS(status = PhEnumProcesses(&processes)))
return status;
if (!(process = PhFindProcessInformationByImageName(processes, &PhStartupParameters.CommandObject->sr)))
{
PhFree(processes);
return STATUS_NOT_FOUND;
}
processId = process->UniqueProcessId;
PhFree(processes);
}
if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE))
{
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_TERMINATE, processId)))
{
status = NtTerminateProcess(processHandle, STATUS_SUCCESS);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE))
{
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
{
status = NtSuspendProcess(processHandle);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE))
{
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId)))
{
status = NtResumeProcess(processHandle);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"priority", TRUE))
{
UCHAR priority;
if (!PhStartupParameters.CommandValue)
return STATUS_INVALID_PARAMETER;
if (PhEqualString2(PhStartupParameters.CommandValue, L"idle", TRUE))
priority = PROCESS_PRIORITY_CLASS_IDLE;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE))
priority = PROCESS_PRIORITY_CLASS_NORMAL;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE))
priority = PROCESS_PRIORITY_CLASS_HIGH;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"realtime", TRUE))
priority = PROCESS_PRIORITY_CLASS_REALTIME;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"abovenormal", TRUE))
priority = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"belownormal", TRUE))
priority = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
else
return STATUS_INVALID_PARAMETER;
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
{
PROCESS_PRIORITY_CLASS priorityClass;
priorityClass.Foreground = FALSE;
priorityClass.PriorityClass = priority;
status = NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS));
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"iopriority", TRUE))
{
ULONG ioPriority;
if (!PhStartupParameters.CommandValue)
return STATUS_INVALID_PARAMETER;
if (PhEqualString2(PhStartupParameters.CommandValue, L"verylow", TRUE))
ioPriority = 0;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"low", TRUE))
ioPriority = 1;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE))
ioPriority = 2;
else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE))
ioPriority = 3;
else
return STATUS_INVALID_PARAMETER;
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
{
status = PhSetProcessIoPriority(processHandle, ioPriority);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"pagepriority", TRUE))
{
ULONG64 pagePriority64;
ULONG pagePriority;
if (!PhStartupParameters.CommandValue)
return STATUS_INVALID_PARAMETER;
PhStringToInteger64(&PhStartupParameters.CommandValue->sr, 10, &pagePriority64);
pagePriority = (ULONG)pagePriority64;
if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId)))
{
status = NtSetInformationProcess(
processHandle,
ProcessPagePriority,
&pagePriority,
sizeof(ULONG)
);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"injectdll", TRUE))
{
if (!PhStartupParameters.CommandValue)
return STATUS_INVALID_PARAMETER;
if (NT_SUCCESS(status = PhOpenProcessPublic(
&processHandle,
ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
processId
)))
{
LARGE_INTEGER timeout;
timeout.QuadPart = -5 * PH_TIMEOUT_SEC;
status = PhInjectDllProcess(
processHandle,
PhStartupParameters.CommandValue->Buffer,
&timeout
);
NtClose(processHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"unloaddll", TRUE))
{
if (!PhStartupParameters.CommandValue)
return STATUS_INVALID_PARAMETER;
if (NT_SUCCESS(status = PhOpenProcessPublic(
&processHandle,
ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
processId
)))
{
PVOID baseAddress;
if (NT_SUCCESS(status = PhpGetDllBaseRemote(
processHandle,
&PhStartupParameters.CommandValue->sr,
&baseAddress
)))
{
LARGE_INTEGER timeout;
timeout.QuadPart = -5 * PH_TIMEOUT_SEC;
status = PhUnloadDllProcess(
processHandle,
baseAddress,
&timeout
);
}
NtClose(processHandle);
}
}
}
else if (PhEqualString2(PhStartupParameters.CommandType, L"service", TRUE))
{
SC_HANDLE serviceHandle;
SERVICE_STATUS serviceStatus;
if (!PhStartupParameters.CommandObject)
return STATUS_INVALID_PARAMETER;
if (PhEqualString2(PhStartupParameters.CommandAction, L"start", TRUE))
{
if (!(serviceHandle = PhOpenService(
PhStartupParameters.CommandObject->Buffer,
SERVICE_START
)))
return PhGetLastWin32ErrorAsNtStatus();
if (!StartService(serviceHandle, 0, NULL))
status = PhGetLastWin32ErrorAsNtStatus();
CloseServiceHandle(serviceHandle);
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"continue", TRUE))
{
if (!(serviceHandle = PhOpenService(
PhStartupParameters.CommandObject->Buffer,
SERVICE_PAUSE_CONTINUE
)))
return PhGetLastWin32ErrorAsNtStatus();
if (!ControlService(serviceHandle, SERVICE_CONTROL_CONTINUE, &serviceStatus))
status = PhGetLastWin32ErrorAsNtStatus();
CloseServiceHandle(serviceHandle);
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"pause", TRUE))
{
if (!(serviceHandle = PhOpenService(
PhStartupParameters.CommandObject->Buffer,
SERVICE_PAUSE_CONTINUE
)))
return PhGetLastWin32ErrorAsNtStatus();
if (!ControlService(serviceHandle, SERVICE_CONTROL_PAUSE, &serviceStatus))
status = PhGetLastWin32ErrorAsNtStatus();
CloseServiceHandle(serviceHandle);
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"stop", TRUE))
{
if (!(serviceHandle = PhOpenService(
PhStartupParameters.CommandObject->Buffer,
SERVICE_STOP
)))
return PhGetLastWin32ErrorAsNtStatus();
if (!ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus))
status = PhGetLastWin32ErrorAsNtStatus();
CloseServiceHandle(serviceHandle);
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"delete", TRUE))
{
if (!(serviceHandle = PhOpenService(
PhStartupParameters.CommandObject->Buffer,
DELETE
)))
return PhGetLastWin32ErrorAsNtStatus();
if (!DeleteService(serviceHandle))
status = PhGetLastWin32ErrorAsNtStatus();
CloseServiceHandle(serviceHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandType, L"thread", TRUE))
{
ULONG64 threadId64;
HANDLE threadId;
HANDLE threadHandle;
if (!PhStartupParameters.CommandObject)
return STATUS_INVALID_PARAMETER;
if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &threadId64))
return STATUS_INVALID_PARAMETER;
threadId = (HANDLE)threadId64;
if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE))
{
if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_TERMINATE, threadId)))
{
status = NtTerminateThread(threadHandle, STATUS_SUCCESS);
NtClose(threadHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE))
{
if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
{
status = NtSuspendThread(threadHandle, NULL);
NtClose(threadHandle);
}
}
else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE))
{
if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId)))
{
status = NtResumeThread(threadHandle, NULL);
NtClose(threadHandle);
}
}
}
return status;
}
typedef struct _GET_DLL_BASE_REMOTE_CONTEXT
{
PH_STRINGREF BaseDllName;
PVOID DllBase;
} GET_DLL_BASE_REMOTE_CONTEXT, *PGET_DLL_BASE_REMOTE_CONTEXT;
static BOOLEAN PhpGetDllBaseRemoteCallback(
_In_ PLDR_DATA_TABLE_ENTRY Module,
_In_opt_ PVOID Context
)
{
PGET_DLL_BASE_REMOTE_CONTEXT context = Context;
PH_STRINGREF baseDllName;
PhUnicodeStringToStringRef(&Module->BaseDllName, &baseDllName);
if (PhEqualStringRef(&baseDllName, &context->BaseDllName, TRUE))
{
context->DllBase = Module->DllBase;
return FALSE;
}
return TRUE;
}
NTSTATUS PhpGetDllBaseRemote(
_In_ HANDLE ProcessHandle,
_In_ PPH_STRINGREF BaseDllName,
_Out_ PVOID *DllBase
)
{
NTSTATUS status;
GET_DLL_BASE_REMOTE_CONTEXT context;
#ifdef _WIN64
BOOLEAN isWow64 = FALSE;
#endif
context.BaseDllName = *BaseDllName;
context.DllBase = NULL;
#ifdef _WIN64
PhGetProcessIsWow64(ProcessHandle, &isWow64);
if (isWow64)
status = PhEnumProcessModules32(ProcessHandle, PhpGetDllBaseRemoteCallback, &context);
if (!context.DllBase)
#endif
status = PhEnumProcessModules(ProcessHandle, PhpGetDllBaseRemoteCallback, &context);
if (NT_SUCCESS(status))
*DllBase = context.DllBase;
return status;
}

709
ProcessHacker/colmgr.c Normal file
View File

@ -0,0 +1,709 @@
/*
* Process Hacker -
* tree new column manager
*
* Copyright (C) 2011-2016 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 <phapp.h>
#include <extmgri.h>
#include <phplug.h>
#include <colmgr.h>
typedef struct _PH_CM_SORT_CONTEXT
{
PPH_PLUGIN_TREENEW_SORT_FUNCTION SortFunction;
ULONG SubId;
PVOID Context;
PPH_CM_POST_SORT_FUNCTION PostSortFunction;
PH_SORT_ORDER SortOrder;
} PH_CM_SORT_CONTEXT, *PPH_CM_SORT_CONTEXT;
VOID PhCmInitializeManager(
_Out_ PPH_CM_MANAGER Manager,
_In_ HWND Handle,
_In_ ULONG MinId,
_In_ PPH_CM_POST_SORT_FUNCTION PostSortFunction
)
{
Manager->Handle = Handle;
Manager->MinId = MinId;
Manager->NextId = MinId;
Manager->PostSortFunction = PostSortFunction;
InitializeListHead(&Manager->ColumnListHead);
Manager->NotifyList = NULL;
}
VOID PhCmDeleteManager(
_In_ PPH_CM_MANAGER Manager
)
{
PLIST_ENTRY listEntry;
PPH_CM_COLUMN column;
listEntry = Manager->ColumnListHead.Flink;
while (listEntry != &Manager->ColumnListHead)
{
column = CONTAINING_RECORD(listEntry, PH_CM_COLUMN, ListEntry);
listEntry = listEntry->Flink;
PhFree(column);
}
if (Manager->NotifyList)
PhDereferenceObject(Manager->NotifyList);
}
PPH_CM_COLUMN PhCmCreateColumn(
_Inout_ PPH_CM_MANAGER Manager,
_In_ PPH_TREENEW_COLUMN Column,
_In_ struct _PH_PLUGIN *Plugin,
_In_ ULONG SubId,
_In_opt_ PVOID Context,
_In_ PVOID SortFunction
)
{
PPH_CM_COLUMN column;
PH_TREENEW_COLUMN tnColumn;
column = PhAllocate(sizeof(PH_CM_COLUMN));
memset(column, 0, sizeof(PH_CM_COLUMN));
column->Id = Manager->NextId++;
column->Plugin = Plugin;
column->SubId = SubId;
column->Context = Context;
column->SortFunction = SortFunction;
InsertTailList(&Manager->ColumnListHead, &column->ListEntry);
memset(&tnColumn, 0, sizeof(PH_TREENEW_COLUMN));
tnColumn.Id = column->Id;
tnColumn.Context = column;
tnColumn.Visible = Column->Visible;
tnColumn.CustomDraw = Column->CustomDraw;
tnColumn.SortDescending = Column->SortDescending;
tnColumn.Text = Column->Text;
tnColumn.Width = Column->Width;
tnColumn.Alignment = Column->Alignment;
tnColumn.DisplayIndex = Column->Visible ? Column->DisplayIndex : -1;
tnColumn.TextFlags = Column->TextFlags;
TreeNew_AddColumn(Manager->Handle, &tnColumn);
return column;
}
PPH_CM_COLUMN PhCmFindColumn(
_In_ PPH_CM_MANAGER Manager,
_In_ PPH_STRINGREF PluginName,
_In_ ULONG SubId
)
{
PLIST_ENTRY listEntry;
PPH_CM_COLUMN column;
listEntry = Manager->ColumnListHead.Flink;
while (listEntry != &Manager->ColumnListHead)
{
column = CONTAINING_RECORD(listEntry, PH_CM_COLUMN, ListEntry);
if (column->SubId == SubId && PhEqualStringRef(PluginName, &column->Plugin->AppContext.AppName, FALSE))
return column;
listEntry = listEntry->Flink;
}
return NULL;
}
VOID PhCmSetNotifyPlugin(
_In_ PPH_CM_MANAGER Manager,
_In_ struct _PH_PLUGIN *Plugin
)
{
if (!Manager->NotifyList)
{
Manager->NotifyList = PhCreateList(8);
}
else
{
if (PhFindItemList(Manager->NotifyList, Plugin) != -1)
return;
}
PhAddItemList(Manager->NotifyList, Plugin);
}
BOOLEAN PhCmForwardMessage(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2,
_In_ PPH_CM_MANAGER Manager
)
{
PH_PLUGIN_TREENEW_MESSAGE pluginMessage;
PPH_PLUGIN plugin;
if (Message == TreeNewDestroying)
return FALSE;
switch (Message)
{
case TreeNewGetCellText:
{
PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
PH_TREENEW_COLUMN tnColumn;
PPH_CM_COLUMN column;
if (getCellText->Id < Manager->MinId)
return FALSE;
if (!TreeNew_GetColumn(hwnd, getCellText->Id, &tnColumn))
return FALSE;
column = tnColumn.Context;
pluginMessage.SubId = column->SubId;
pluginMessage.Context = column->Context;
plugin = column->Plugin;
}
break;
case TreeNewCustomDraw:
{
PPH_TREENEW_CUSTOM_DRAW customDraw = Parameter1;
PPH_CM_COLUMN column;
if (customDraw->Column->Id < Manager->MinId)
return FALSE;
column = customDraw->Column->Context;
pluginMessage.SubId = column->SubId;
pluginMessage.Context = column->Context;
plugin = column->Plugin;
}
break;
case TreeNewColumnResized:
{
PPH_TREENEW_COLUMN tlColumn = Parameter1;
PPH_CM_COLUMN column;
if (tlColumn->Id < Manager->MinId)
return FALSE;
column = tlColumn->Context;
pluginMessage.SubId = column->SubId;
pluginMessage.Context = column->Context;
plugin = column->Plugin;
}
break;
default:
{
// Some plugins want to be notified about all messages.
if (Manager->NotifyList)
{
ULONG i;
for (i = 0; i < Manager->NotifyList->Count; i++)
{
plugin = Manager->NotifyList->Items[i];
pluginMessage.TreeNewHandle = hwnd;
pluginMessage.Message = Message;
pluginMessage.Parameter1 = Parameter1;
pluginMessage.Parameter2 = Parameter2;
pluginMessage.SubId = 0;
pluginMessage.Context = NULL;
PhInvokeCallback(PhGetPluginCallback(plugin, PluginCallbackTreeNewMessage), &pluginMessage);
}
}
}
return FALSE;
}
pluginMessage.TreeNewHandle = hwnd;
pluginMessage.Message = Message;
pluginMessage.Parameter1 = Parameter1;
pluginMessage.Parameter2 = Parameter2;
PhInvokeCallback(PhGetPluginCallback(plugin, PluginCallbackTreeNewMessage), &pluginMessage);
return TRUE;
}
static int __cdecl PhCmpSortFunction(
_In_ void *context,
_In_ const void *elem1,
_In_ const void *elem2
)
{
PPH_CM_SORT_CONTEXT sortContext = context;
PVOID node1 = *(PVOID *)elem1;
PVOID node2 = *(PVOID *)elem2;
LONG result;
result = sortContext->SortFunction(node1, node2, sortContext->SubId, sortContext->Context);
return sortContext->PostSortFunction(result, node1, node2, sortContext->SortOrder);
}
BOOLEAN PhCmForwardSort(
_In_ PPH_TREENEW_NODE *Nodes,
_In_ ULONG NumberOfNodes,
_In_ ULONG SortColumn,
_In_ PH_SORT_ORDER SortOrder,
_In_ PPH_CM_MANAGER Manager
)
{
PH_TREENEW_COLUMN tnColumn;
PPH_CM_COLUMN column;
PH_CM_SORT_CONTEXT sortContext;
if (SortColumn < Manager->MinId)
return FALSE;
if (!TreeNew_GetColumn(Manager->Handle, SortColumn, &tnColumn))
return TRUE;
column = tnColumn.Context;
if (!column->SortFunction)
return TRUE;
sortContext.SortFunction = column->SortFunction;
sortContext.SubId = column->SubId;
sortContext.Context = column->Context;
sortContext.PostSortFunction = Manager->PostSortFunction;
sortContext.SortOrder = SortOrder;
qsort_s(Nodes, NumberOfNodes, sizeof(PVOID), PhCmpSortFunction, &sortContext);
return TRUE;
}
BOOLEAN PhCmLoadSettings(
_In_ HWND TreeNewHandle,
_In_ PPH_STRINGREF Settings
)
{
return PhCmLoadSettingsEx(TreeNewHandle, NULL, 0, Settings, NULL);
}
BOOLEAN PhCmLoadSettingsEx(
_In_ HWND TreeNewHandle,
_In_opt_ PPH_CM_MANAGER Manager,
_In_ ULONG Flags,
_In_ PPH_STRINGREF Settings,
_In_opt_ PPH_STRINGREF SortSettings
)
{
BOOLEAN result = FALSE;
PH_STRINGREF scalePart;
PH_STRINGREF columnPart;
PH_STRINGREF remainingColumnPart;
PH_STRINGREF valuePart;
PH_STRINGREF subPart;
ULONG64 integer;
ULONG scale;
ULONG total;
BOOLEAN hasFixedColumn;
ULONG count;
ULONG i;
PPH_HASHTABLE columnHashtable;
PH_HASHTABLE_ENUM_CONTEXT enumContext;
PPH_KEY_VALUE_PAIR pair;
LONG orderArray[PH_CM_ORDER_LIMIT];
LONG maxOrder;
if (Settings->Length != 0)
{
columnHashtable = PhCreateSimpleHashtable(20);
remainingColumnPart = *Settings;
if (remainingColumnPart.Length != 0 && remainingColumnPart.Buffer[0] == '@')
{
PhSkipStringRef(&remainingColumnPart, sizeof(WCHAR));
PhSplitStringRefAtChar(&remainingColumnPart, '|', &scalePart, &remainingColumnPart);
if (scalePart.Length == 0 || !PhStringToInteger64(&scalePart, 10, &integer))
goto CleanupExit;
scale = (ULONG)integer;
}
else
{
scale = PhGlobalDpi;
}
while (remainingColumnPart.Length != 0)
{
PPH_TREENEW_COLUMN column;
ULONG id;
ULONG displayIndex;
ULONG width;
PhSplitStringRefAtChar(&remainingColumnPart, '|', &columnPart, &remainingColumnPart);
if (columnPart.Length != 0)
{
// Id
PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart);
if (valuePart.Length == 0)
goto CleanupExit;
if (valuePart.Buffer[0] == '+')
{
PH_STRINGREF pluginName;
ULONG subId;
PPH_CM_COLUMN cmColumn;
// This is a plugin-owned column.
if (!Manager)
continue;
if (!PhEmParseCompoundId(&valuePart, &pluginName, &subId))
continue;
cmColumn = PhCmFindColumn(Manager, &pluginName, subId);
if (!cmColumn)
continue; // can't find the column, skip this part
id = cmColumn->Id;
}
else
{
if (!PhStringToInteger64(&valuePart, 10, &integer))
goto CleanupExit;
id = (ULONG)integer;
}
// Display Index
PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart);
if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY))
{
if (valuePart.Length == 0 || !PhStringToInteger64(&valuePart, 10, &integer))
goto CleanupExit;
displayIndex = (ULONG)integer;
}
else
{
if (valuePart.Length != 0)
goto CleanupExit;
displayIndex = -1;
}
// Width
if (columnPart.Length == 0 || !PhStringToInteger64(&columnPart, 10, &integer))
goto CleanupExit;
width = (ULONG)integer;
if (scale != PhGlobalDpi && scale != 0)
width = PhMultiplyDivide(width, PhGlobalDpi, scale);
column = PhAllocate(sizeof(PH_TREENEW_COLUMN));
column->Id = id;
column->DisplayIndex = displayIndex;
column->Width = width;
PhAddItemSimpleHashtable(columnHashtable, UlongToPtr(column->Id), column);
}
}
TreeNew_SetRedraw(TreeNewHandle, FALSE);
// Set visibility and width.
i = 0;
count = 0;
total = TreeNew_GetColumnCount(TreeNewHandle);
hasFixedColumn = !!TreeNew_GetFixedColumn(TreeNewHandle);
memset(orderArray, 0, sizeof(orderArray));
maxOrder = 0;
while (count < total)
{
PH_TREENEW_COLUMN setColumn;
PPH_TREENEW_COLUMN *columnPtr;
if (TreeNew_GetColumn(TreeNewHandle, i, &setColumn))
{
columnPtr = (PPH_TREENEW_COLUMN *)PhFindItemSimpleHashtable(columnHashtable, UlongToPtr(i));
if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY))
{
if (columnPtr)
{
setColumn.Visible = TRUE;
setColumn.Width = (*columnPtr)->Width;
TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE | TN_COLUMN_WIDTH, &setColumn);
if (!setColumn.Fixed)
{
// For compatibility reasons, normal columns have their display indicies stored
// one higher than usual (so they start from 1, not 0). Fix that here.
if (hasFixedColumn && (*columnPtr)->DisplayIndex != 0)
(*columnPtr)->DisplayIndex--;
if ((*columnPtr)->DisplayIndex < PH_CM_ORDER_LIMIT)
{
orderArray[(*columnPtr)->DisplayIndex] = i;
if ((ULONG)maxOrder < (*columnPtr)->DisplayIndex + 1)
maxOrder = (*columnPtr)->DisplayIndex + 1;
}
}
}
else if (!setColumn.Fixed) // never hide the fixed column
{
setColumn.Visible = FALSE;
TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE, &setColumn);
}
}
else
{
if (columnPtr)
{
setColumn.Width = (*columnPtr)->Width;
TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_WIDTH, &setColumn);
}
}
count++;
}
i++;
}
if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY))
{
// Set the order array.
TreeNew_SetColumnOrderArray(TreeNewHandle, maxOrder, orderArray);
}
TreeNew_SetRedraw(TreeNewHandle, TRUE);
result = TRUE;
CleanupExit:
PhBeginEnumHashtable(columnHashtable, &enumContext);
while (pair = PhNextEnumHashtable(&enumContext))
PhFree(pair->Value);
PhDereferenceObject(columnHashtable);
}
// Load sort settings.
if (SortSettings && SortSettings->Length != 0)
{
PhSplitStringRefAtChar(SortSettings, ',', &valuePart, &subPart);
if (valuePart.Length != 0 && subPart.Length != 0)
{
ULONG sortColumn;
PH_SORT_ORDER sortOrder;
sortColumn = -1;
if (valuePart.Buffer[0] == '+')
{
PH_STRINGREF pluginName;
ULONG subId;
PPH_CM_COLUMN cmColumn;
if (
Manager &&
PhEmParseCompoundId(&valuePart, &pluginName, &subId) &&
(cmColumn = PhCmFindColumn(Manager, &pluginName, subId))
)
{
sortColumn = cmColumn->Id;
}
}
else
{
PhStringToInteger64(&valuePart, 10, &integer);
sortColumn = (ULONG)integer;
}
PhStringToInteger64(&subPart, 10, &integer);
sortOrder = (PH_SORT_ORDER)integer;
if (sortColumn != -1 && sortOrder <= DescendingSortOrder)
{
TreeNew_SetSort(TreeNewHandle, sortColumn, sortOrder);
}
}
}
return result;
}
PPH_STRING PhCmSaveSettings(
_In_ HWND TreeNewHandle
)
{
return PhCmSaveSettingsEx(TreeNewHandle, NULL, 0, NULL);
}
PPH_STRING PhCmSaveSettingsEx(
_In_ HWND TreeNewHandle,
_In_opt_ PPH_CM_MANAGER Manager,
_In_ ULONG Flags,
_Out_opt_ PPH_STRING *SortSettings
)
{
PH_STRING_BUILDER stringBuilder;
ULONG i = 0;
ULONG count = 0;
ULONG total;
ULONG increment;
PH_TREENEW_COLUMN column;
total = TreeNew_GetColumnCount(TreeNewHandle);
if (TreeNew_GetFixedColumn(TreeNewHandle))
increment = 1; // the first normal column should have a display index that starts with 1, for compatibility
else
increment = 0;
PhInitializeStringBuilder(&stringBuilder, 100);
PhAppendFormatStringBuilder(&stringBuilder, L"@%u|", PhGlobalDpi);
while (count < total)
{
if (TreeNew_GetColumn(TreeNewHandle, i, &column))
{
if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY))
{
if (column.Visible)
{
if (!Manager || i < Manager->MinId)
{
PhAppendFormatStringBuilder(
&stringBuilder,
L"%u,%u,%u|",
i,
column.Fixed ? 0 : column.DisplayIndex + increment,
column.Width
);
}
else
{
PPH_CM_COLUMN cmColumn;
cmColumn = column.Context;
PhAppendFormatStringBuilder(
&stringBuilder,
L"+%s+%u,%u,%u|",
cmColumn->Plugin->Name.Buffer,
cmColumn->SubId,
column.DisplayIndex + increment,
column.Width
);
}
}
}
else
{
if (!Manager || i < Manager->MinId)
{
PhAppendFormatStringBuilder(
&stringBuilder,
L"%u,,%u|",
i,
column.Width
);
}
else
{
PPH_CM_COLUMN cmColumn;
cmColumn = column.Context;
PhAppendFormatStringBuilder(
&stringBuilder,
L"+%s+%u,,%u|",
cmColumn->Plugin->Name.Buffer,
cmColumn->SubId,
column.Width
);
}
}
count++;
}
i++;
}
if (stringBuilder.String->Length != 0)
PhRemoveEndStringBuilder(&stringBuilder, 1);
if (SortSettings)
{
ULONG sortColumn;
PH_SORT_ORDER sortOrder;
if (TreeNew_GetSort(TreeNewHandle, &sortColumn, &sortOrder))
{
if (sortOrder != NoSortOrder)
{
if (!Manager || sortColumn < Manager->MinId)
{
*SortSettings = PhFormatString(L"%u,%u", sortColumn, sortOrder);
}
else
{
PH_TREENEW_COLUMN column;
PPH_CM_COLUMN cmColumn;
if (TreeNew_GetColumn(TreeNewHandle, sortColumn, &column))
{
cmColumn = column.Context;
*SortSettings = PhFormatString(L"+%s+%u,%u", cmColumn->Plugin->Name.Buffer, cmColumn->SubId, sortOrder);
}
else
{
*SortSettings = PhReferenceEmptyString();
}
}
}
else
{
*SortSettings = PhCreateString(L"0,0");
}
}
else
{
*SortSettings = PhReferenceEmptyString();
}
}
return PhFinalStringBuilderString(&stringBuilder);
}

1693
ProcessHacker/dbgcon.c Normal file

File diff suppressed because it is too large Load Diff

226
ProcessHacker/extmgr.c Normal file
View File

@ -0,0 +1,226 @@
/*
* Process Hacker -
* extension manager
*
* 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/>.
*/
/*
* The extension manager provides support for generic extensions. It sits directly
* underneath the plugin manager, and has no knowledge of plugin details (how they are
* loaded, plugin information, etc.).
*/
#include <phapp.h>
#include <extmgri.h>
LIST_ENTRY PhEmAppContextListHead = { &PhEmAppContextListHead, &PhEmAppContextListHead };
ULONG PhEmAppContextCount = 0;
PH_EM_OBJECT_TYPE_STATE PhEmObjectTypeState[EmMaximumObjectType] = { 0 };
/**
* Initializes the extension manager module.
*/
VOID PhEmInitialization(
VOID
)
{
ULONG i;
for (i = 0; i < EmMaximumObjectType; i++)
{
InitializeListHead(&PhEmObjectTypeState[i].ExtensionListHead);
}
}
/**
* Initializes an extension application context.
*
* \param AppContext The application context.
* \param AppName The application name.
*/
VOID PhEmInitializeAppContext(
_Out_ PPH_EM_APP_CONTEXT AppContext,
_In_ PPH_STRINGREF AppName
)
{
AppContext->AppName = *AppName;
memset(AppContext->Extensions, 0, sizeof(AppContext->Extensions));
InsertTailList(&PhEmAppContextListHead, &AppContext->ListEntry);
PhEmAppContextCount++;
}
/**
* Sets the object extension size and callbacks for an object type.
*
* \param AppContext The application context.
* \param ObjectType The type of object for which the extension is being registered.
* \param ExtensionSize The size of the extension, in bytes.
* \param CreateCallback The object creation callback.
* \param DeleteCallback The object deletion callback.
*/
VOID PhEmSetObjectExtension(
_Inout_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T ExtensionSize,
_In_opt_ PPH_EM_OBJECT_CALLBACK CreateCallback,
_In_opt_ PPH_EM_OBJECT_CALLBACK DeleteCallback
)
{
PPH_EM_OBJECT_TYPE_STATE objectTypeState;
PPH_EM_OBJECT_EXTENSION objectExtension;
objectTypeState = &PhEmObjectTypeState[ObjectType];
objectExtension = AppContext->Extensions[ObjectType];
if (!objectExtension)
{
objectExtension = PhAllocate(sizeof(PH_EM_OBJECT_EXTENSION));
memset(objectExtension, 0, sizeof(PH_EM_OBJECT_EXTENSION));
InsertTailList(&objectTypeState->ExtensionListHead, &objectExtension->ListEntry);
AppContext->Extensions[ObjectType] = objectExtension;
objectExtension->ExtensionSize = ExtensionSize;
objectExtension->ExtensionOffset = objectTypeState->ExtensionOffset;
objectTypeState->ExtensionOffset += ExtensionSize;
}
objectExtension->Callbacks[EmObjectCreate] = CreateCallback;
objectExtension->Callbacks[EmObjectDelete] = DeleteCallback;
}
/**
* Gets the object extension for an object.
*
* \param AppContext The application context.
* \param ObjectType The type of object for which an extension has been registered.
* \param Object The object.
*/
PVOID PhEmGetObjectExtension(
_In_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object
)
{
PPH_EM_OBJECT_EXTENSION objectExtension;
objectExtension = AppContext->Extensions[ObjectType];
if (!objectExtension)
return NULL;
return (PCHAR)Object + PhEmObjectTypeState[ObjectType].InitialSize + objectExtension->ExtensionOffset;
}
/**
* Determines the size of an object, including extensions.
*
* \param ObjectType The object type.
* \param InitialSize The initial size of the object.
*/
SIZE_T PhEmGetObjectSize(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T InitialSize
)
{
PhEmObjectTypeState[ObjectType].InitialSize = InitialSize;
return InitialSize + PhEmObjectTypeState[ObjectType].ExtensionOffset;
}
/**
* Invokes callbacks for an object operation.
*
* \param ObjectType The object type.
* \param Object The object.
* \param Operation The operation being performed.
*/
VOID PhEmCallObjectOperation(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object,
_In_ PH_EM_OBJECT_OPERATION Operation
)
{
PPH_EM_OBJECT_TYPE_STATE objectTypeState;
PLIST_ENTRY listEntry;
PPH_EM_OBJECT_EXTENSION objectExtension;
if (PhEmAppContextCount == 0)
return;
objectTypeState = &PhEmObjectTypeState[ObjectType];
listEntry = objectTypeState->ExtensionListHead.Flink;
while (listEntry != &objectTypeState->ExtensionListHead)
{
objectExtension = CONTAINING_RECORD(listEntry, PH_EM_OBJECT_EXTENSION, ListEntry);
if (objectExtension->Callbacks[Operation])
{
objectExtension->Callbacks[Operation](
Object,
ObjectType,
(PCHAR)Object + objectTypeState->InitialSize + objectExtension->ExtensionOffset
);
}
listEntry = listEntry->Flink;
}
}
/**
* Parses an application name and sub-ID pair.
*
* \param CompoundId The compound identifier.
* \param AppName A variable which receives the application name.
* \param SubId A variable which receives the sub-ID.
*/
BOOLEAN PhEmParseCompoundId(
_In_ PPH_STRINGREF CompoundId,
_Out_ PPH_STRINGREF AppName,
_Out_ PULONG SubId
)
{
PH_STRINGREF firstPart;
PH_STRINGREF secondPart;
ULONG64 integer;
firstPart = *CompoundId;
if (firstPart.Length == 0)
return FALSE;
if (firstPart.Buffer[0] != '+')
return FALSE;
PhSkipStringRef(&firstPart, sizeof(WCHAR));
PhSplitStringRefAtChar(&firstPart, '+', &firstPart, &secondPart);
if (firstPart.Length == 0 || secondPart.Length == 0)
return FALSE;
if (!PhStringToInteger64(&secondPart, 10, &integer))
return FALSE;
*AppName = firstPart;
*SubId = (ULONG)integer;
return TRUE;
}

1011
ProcessHacker/findobj.c Normal file

File diff suppressed because it is too large Load Diff

378
ProcessHacker/gdihndl.c Normal file
View File

@ -0,0 +1,378 @@
/*
* Process Hacker -
* GDI handles dialog
*
* Copyright (C) 2010 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 <phapp.h>
#include <procprv.h>
#include <ntgdi.h>
typedef struct _GDI_HANDLES_CONTEXT
{
PPH_PROCESS_ITEM ProcessItem;
PPH_LIST List;
} GDI_HANDLES_CONTEXT, *PGDI_HANDLES_CONTEXT;
typedef struct _PH_GDI_HANDLE_ITEM
{
PGDI_HANDLE_ENTRY Entry;
ULONG Handle;
PVOID Object;
PWSTR TypeName;
PPH_STRING Information;
} PH_GDI_HANDLE_ITEM, *PPH_GDI_HANDLE_ITEM;
INT_PTR CALLBACK PhpGdiHandlesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhShowGdiHandlesDialog(
_In_ HWND ParentWindowHandle,
_In_ PPH_PROCESS_ITEM ProcessItem
)
{
GDI_HANDLES_CONTEXT context;
ULONG i;
context.ProcessItem = ProcessItem;
context.List = PhCreateList(20);
DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_GDIHANDLES),
ParentWindowHandle,
PhpGdiHandlesDlgProc,
(LPARAM)&context
);
for (i = 0; i < context.List->Count; i++)
{
PPH_GDI_HANDLE_ITEM gdiHandleItem = context.List->Items[i];
if (gdiHandleItem->Information)
PhDereferenceObject(gdiHandleItem->Information);
PhFree(context.List->Items[i]);
}
PhDereferenceObject(context.List);
}
PWSTR PhpGetGdiHandleTypeName(
_In_ ULONG Unique
)
{
switch (GDI_CLIENT_TYPE_FROM_UNIQUE(Unique))
{
case GDI_CLIENT_ALTDC_TYPE:
return L"Alt. DC";
case GDI_CLIENT_BITMAP_TYPE:
return L"Bitmap";
case GDI_CLIENT_BRUSH_TYPE:
return L"Brush";
case GDI_CLIENT_CLIENTOBJ_TYPE:
return L"Client Object";
case GDI_CLIENT_DIBSECTION_TYPE:
return L"DIB Section";
case GDI_CLIENT_DC_TYPE:
return L"DC";
case GDI_CLIENT_EXTPEN_TYPE:
return L"ExtPen";
case GDI_CLIENT_FONT_TYPE:
return L"Font";
case GDI_CLIENT_METADC16_TYPE:
return L"Metafile DC";
case GDI_CLIENT_METAFILE_TYPE:
return L"Enhanced Metafile";
case GDI_CLIENT_METAFILE16_TYPE:
return L"Metafile";
case GDI_CLIENT_PALETTE_TYPE:
return L"Palette";
case GDI_CLIENT_PEN_TYPE:
return L"Pen";
case GDI_CLIENT_REGION_TYPE:
return L"Region";
default:
return NULL;
}
}
PPH_STRING PhpGetGdiHandleInformation(
_In_ ULONG Handle
)
{
HGDIOBJ handle;
handle = (HGDIOBJ)UlongToPtr(Handle);
switch (GDI_CLIENT_TYPE_FROM_HANDLE(Handle))
{
case GDI_CLIENT_BITMAP_TYPE:
case GDI_CLIENT_DIBSECTION_TYPE:
{
BITMAP bitmap;
if (GetObject(handle, sizeof(BITMAP), &bitmap))
{
return PhFormatString(
L"Width: %u, Height: %u, Depth: %u",
bitmap.bmWidth,
bitmap.bmHeight,
bitmap.bmBitsPixel
);
}
}
break;
case GDI_CLIENT_BRUSH_TYPE:
{
LOGBRUSH brush;
if (GetObject(handle, sizeof(LOGBRUSH), &brush))
{
return PhFormatString(
L"Style: %u, Color: 0x%08x, Hatch: 0x%Ix",
brush.lbStyle,
_byteswap_ulong(brush.lbColor),
brush.lbHatch
);
}
}
break;
case GDI_CLIENT_EXTPEN_TYPE:
{
EXTLOGPEN pen;
if (GetObject(handle, sizeof(EXTLOGPEN), &pen))
{
return PhFormatString(
L"Style: 0x%x, Width: %u, Color: 0x%08x",
pen.elpPenStyle,
pen.elpWidth,
_byteswap_ulong(pen.elpColor)
);
}
}
break;
case GDI_CLIENT_FONT_TYPE:
{
LOGFONT font;
if (GetObject(handle, sizeof(LOGFONT), &font))
{
return PhFormatString(
L"Face: %s, Height: %d",
font.lfFaceName,
font.lfHeight
);
}
}
break;
case GDI_CLIENT_PALETTE_TYPE:
{
USHORT count;
if (GetObject(handle, sizeof(USHORT), &count))
{
return PhFormatString(
L"Entries: %u",
(ULONG)count
);
}
}
break;
case GDI_CLIENT_PEN_TYPE:
{
LOGPEN pen;
if (GetObject(handle, sizeof(LOGPEN), &pen))
{
return PhFormatString(
L"Style: %u, Width: %u, Color: 0x%08x",
pen.lopnStyle,
pen.lopnWidth.x,
_byteswap_ulong(pen.lopnColor)
);
}
}
break;
}
return NULL;
}
VOID PhpRefreshGdiHandles(
_In_ HWND hwndDlg,
_In_ PGDI_HANDLES_CONTEXT Context
)
{
HWND lvHandle;
ULONG i;
PGDI_SHARED_MEMORY gdiShared;
USHORT processId;
PGDI_HANDLE_ENTRY handle;
PPH_GDI_HANDLE_ITEM gdiHandleItem;
lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
ListView_DeleteAllItems(lvHandle);
ExtendedListView_SetRedraw(lvHandle, FALSE);
for (i = 0; i < Context->List->Count; i++)
{
gdiHandleItem = Context->List->Items[i];
if (gdiHandleItem->Information)
PhDereferenceObject(gdiHandleItem->Information);
PhFree(Context->List->Items[i]);
}
PhClearList(Context->List);
gdiShared = (PGDI_SHARED_MEMORY)NtCurrentPeb()->GdiSharedHandleTable;
processId = (USHORT)Context->ProcessItem->ProcessId;
for (i = 0; i < GDI_MAX_HANDLE_COUNT; i++)
{
PWSTR typeName;
INT lvItemIndex;
WCHAR pointer[PH_PTR_STR_LEN_1];
handle = &gdiShared->Handles[i];
if (handle->Owner.ProcessId != processId)
continue;
typeName = PhpGetGdiHandleTypeName(handle->Unique);
if (!typeName)
continue;
gdiHandleItem = PhAllocate(sizeof(PH_GDI_HANDLE_ITEM));
gdiHandleItem->Entry = handle;
gdiHandleItem->Handle = GDI_MAKE_HANDLE(i, handle->Unique);
gdiHandleItem->Object = handle->Object;
gdiHandleItem->TypeName = typeName;
gdiHandleItem->Information = PhpGetGdiHandleInformation(gdiHandleItem->Handle);
PhAddItemList(Context->List, gdiHandleItem);
lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, gdiHandleItem->TypeName, gdiHandleItem);
PhPrintPointer(pointer, UlongToPtr(gdiHandleItem->Handle));
PhSetListViewSubItem(lvHandle, lvItemIndex, 1, pointer);
PhPrintPointer(pointer, gdiHandleItem->Object);
PhSetListViewSubItem(lvHandle, lvItemIndex, 2, pointer);
PhSetListViewSubItem(lvHandle, lvItemIndex, 3, PhGetString(gdiHandleItem->Information));
}
ExtendedListView_SortItems(lvHandle);
ExtendedListView_SetRedraw(lvHandle, TRUE);
}
INT NTAPI PhpGdiHandleHandleCompareFunction(
_In_ PVOID Item1,
_In_ PVOID Item2,
_In_opt_ PVOID Context
)
{
PPH_GDI_HANDLE_ITEM item1 = Item1;
PPH_GDI_HANDLE_ITEM item2 = Item2;
return uintcmp(item1->Handle, item2->Handle);
}
INT NTAPI PhpGdiHandleObjectCompareFunction(
_In_ PVOID Item1,
_In_ PVOID Item2,
_In_opt_ PVOID Context
)
{
PPH_GDI_HANDLE_ITEM item1 = Item1;
PPH_GDI_HANDLE_ITEM item2 = Item2;
return uintptrcmp((ULONG_PTR)item1->Object, (ULONG_PTR)item2->Object);
}
INT_PTR CALLBACK PhpGdiHandlesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PGDI_HANDLES_CONTEXT context = (PGDI_HANDLES_CONTEXT)lParam;
HWND lvHandle;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
PhSetListViewStyle(lvHandle, FALSE, TRUE);
PhSetControlTheme(lvHandle, L"explorer");
PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 100, L"Type");
PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 80, L"Handle");
PhAddListViewColumn(lvHandle, 2, 2, 2, LVCFMT_LEFT, 80, L"Object");
PhAddListViewColumn(lvHandle, 3, 3, 3, LVCFMT_LEFT, 200, L"Information");
PhSetExtendedListView(lvHandle);
ExtendedListView_SetCompareFunction(lvHandle, 1, PhpGdiHandleHandleCompareFunction);
ExtendedListView_SetCompareFunction(lvHandle, 2, PhpGdiHandleObjectCompareFunction);
ExtendedListView_AddFallbackColumn(lvHandle, 0);
ExtendedListView_AddFallbackColumn(lvHandle, 1);
PhpRefreshGdiHandles(hwndDlg, context);
}
break;
case WM_DESTROY:
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
case IDC_REFRESH:
{
PhpRefreshGdiHandles(hwndDlg, (PGDI_HANDLES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()));
}
break;
}
}
break;
case WM_NOTIFY:
{
PhHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
}

1246
ProcessHacker/hidnproc.c Normal file

File diff suppressed because it is too large Load Diff

751
ProcessHacker/hndllist.c Normal file
View File

@ -0,0 +1,751 @@
/*
* Process Hacker -
* handle list
*
* Copyright (C) 2011-2013 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 <phapp.h>
#include <hndllist.h>
#include <hndlprv.h>
#include <secedit.h>
#include <settings.h>
#include <extmgri.h>
#include <phplug.h>
#include <emenu.h>
BOOLEAN PhpHandleNodeHashtableEqualFunction(
_In_ PVOID Entry1,
_In_ PVOID Entry2
);
ULONG PhpHandleNodeHashtableHashFunction(
_In_ PVOID Entry
);
VOID PhpDestroyHandleNode(
_In_ PPH_HANDLE_NODE HandleNode
);
VOID PhpRemoveHandleNode(
_In_ PPH_HANDLE_NODE HandleNode,
_In_ PPH_HANDLE_LIST_CONTEXT Context
);
LONG PhpHandleTreeNewPostSortFunction(
_In_ LONG Result,
_In_ PVOID Node1,
_In_ PVOID Node2,
_In_ PH_SORT_ORDER SortOrder
);
BOOLEAN NTAPI PhpHandleTreeNewCallback(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2,
_In_opt_ PVOID Context
);
VOID PhInitializeHandleList(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
_Out_ PPH_HANDLE_LIST_CONTEXT Context
)
{
HWND hwnd;
memset(Context, 0, sizeof(PH_HANDLE_LIST_CONTEXT));
Context->EnableStateHighlighting = TRUE;
Context->NodeHashtable = PhCreateHashtable(
sizeof(PPH_HANDLE_NODE),
PhpHandleNodeHashtableEqualFunction,
PhpHandleNodeHashtableHashFunction,
100
);
Context->NodeList = PhCreateList(100);
Context->ParentWindowHandle = ParentWindowHandle;
Context->TreeNewHandle = TreeNewHandle;
hwnd = TreeNewHandle;
PhSetControlTheme(hwnd, L"explorer");
TreeNew_SetCallback(hwnd, PhpHandleTreeNewCallback, Context);
TreeNew_SetRedraw(hwnd, FALSE);
// Default columns
PhAddTreeNewColumn(hwnd, PHHNTLC_TYPE, TRUE, L"Type", 100, PH_ALIGN_LEFT, 0, 0);
PhAddTreeNewColumn(hwnd, PHHNTLC_NAME, TRUE, L"Name", 200, PH_ALIGN_LEFT, 1, 0);
PhAddTreeNewColumn(hwnd, PHHNTLC_HANDLE, TRUE, L"Handle", 80, PH_ALIGN_LEFT, 2, 0);
PhAddTreeNewColumn(hwnd, PHHNTLC_OBJECTADDRESS, FALSE, L"Object address", 80, PH_ALIGN_LEFT, -1, 0);
PhAddTreeNewColumnEx(hwnd, PHHNTLC_ATTRIBUTES, FALSE, L"Attributes", 120, PH_ALIGN_LEFT, -1, 0, TRUE);
PhAddTreeNewColumn(hwnd, PHHNTLC_GRANTEDACCESS, FALSE, L"Granted access", 80, PH_ALIGN_LEFT, -1, 0);
PhAddTreeNewColumn(hwnd, PHHNTLC_GRANTEDACCESSSYMBOLIC, FALSE, L"Granted access (symbolic)", 140, PH_ALIGN_LEFT, -1, 0);
PhAddTreeNewColumn(hwnd, PHHNTLC_ORIGINALNAME, FALSE, L"Original name", 200, PH_ALIGN_LEFT, -1, 0);
PhAddTreeNewColumnEx(hwnd, PHHNTLC_FILESHAREACCESS, FALSE, L"File share access", 50, PH_ALIGN_LEFT, -1, 0, TRUE);
TreeNew_SetRedraw(hwnd, TRUE);
TreeNew_SetSort(hwnd, 0, AscendingSortOrder);
PhCmInitializeManager(&Context->Cm, hwnd, PHHNTLC_MAXIMUM, PhpHandleTreeNewPostSortFunction);
}
VOID PhDeleteHandleList(
_In_ PPH_HANDLE_LIST_CONTEXT Context
)
{
ULONG i;
PhCmDeleteManager(&Context->Cm);
for (i = 0; i < Context->NodeList->Count; i++)
PhpDestroyHandleNode(Context->NodeList->Items[i]);
PhDereferenceObject(Context->NodeHashtable);
PhDereferenceObject(Context->NodeList);
}
BOOLEAN PhpHandleNodeHashtableEqualFunction(
_In_ PVOID Entry1,
_In_ PVOID Entry2
)
{
PPH_HANDLE_NODE handleNode1 = *(PPH_HANDLE_NODE *)Entry1;
PPH_HANDLE_NODE handleNode2 = *(PPH_HANDLE_NODE *)Entry2;
return handleNode1->Handle == handleNode2->Handle;
}
ULONG PhpHandleNodeHashtableHashFunction(
_In_ PVOID Entry
)
{
return HandleToUlong((*(PPH_HANDLE_NODE *)Entry)->Handle) / 4;
}
VOID PhLoadSettingsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context
)
{
PPH_STRING settings;
PPH_STRING sortSettings;
settings = PhGetStringSetting(L"HandleTreeListColumns");
sortSettings = PhGetStringSetting(L"HandleTreeListSort");
PhCmLoadSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &settings->sr, &sortSettings->sr);
PhDereferenceObject(settings);
PhDereferenceObject(sortSettings);
}
VOID PhSaveSettingsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context
)
{
PPH_STRING settings;
PPH_STRING sortSettings;
settings = PhCmSaveSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &sortSettings);
PhSetStringSetting2(L"HandleTreeListColumns", &settings->sr);
PhSetStringSetting2(L"HandleTreeListSort", &sortSettings->sr);
PhDereferenceObject(settings);
PhDereferenceObject(sortSettings);
}
VOID PhSetOptionsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ BOOLEAN HideUnnamedHandles
)
{
ULONG i;
BOOLEAN modified;
if (Context->HideUnnamedHandles != HideUnnamedHandles)
{
Context->HideUnnamedHandles = HideUnnamedHandles;
modified = FALSE;
for (i = 0; i < Context->NodeList->Count; i++)
{
PPH_HANDLE_NODE node = Context->NodeList->Items[i];
BOOLEAN visible;
visible = TRUE;
if (HideUnnamedHandles && PhIsNullOrEmptyString(node->HandleItem->BestObjectName))
visible = FALSE;
if (node->Node.Visible != visible)
{
node->Node.Visible = visible;
modified = TRUE;
if (!visible)
node->Node.Selected = FALSE;
}
}
if (modified)
{
TreeNew_NodesStructured(Context->TreeNewHandle);
}
}
}
PPH_HANDLE_NODE PhAddHandleNode(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_ITEM HandleItem,
_In_ ULONG RunId
)
{
PPH_HANDLE_NODE handleNode;
handleNode = PhAllocate(PhEmGetObjectSize(EmHandleNodeType, sizeof(PH_HANDLE_NODE)));
memset(handleNode, 0, sizeof(PH_HANDLE_NODE));
PhInitializeTreeNewNode(&handleNode->Node);
if (Context->EnableStateHighlighting && RunId != 1)
{
PhChangeShStateTn(
&handleNode->Node,
&handleNode->ShState,
&Context->NodeStateList,
NewItemState,
PhCsColorNew,
NULL
);
}
handleNode->Handle = HandleItem->Handle;
handleNode->HandleItem = HandleItem;
PhReferenceObject(HandleItem);
memset(handleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHHNTLC_MAXIMUM);
handleNode->Node.TextCache = handleNode->TextCache;
handleNode->Node.TextCacheSize = PHHNTLC_MAXIMUM;
PhAddEntryHashtable(Context->NodeHashtable, &handleNode);
PhAddItemList(Context->NodeList, handleNode);
if (Context->HideUnnamedHandles && PhIsNullOrEmptyString(HandleItem->BestObjectName))
handleNode->Node.Visible = FALSE;
PhEmCallObjectOperation(EmHandleNodeType, handleNode, EmObjectCreate);
TreeNew_NodesStructured(Context->TreeNewHandle);
return handleNode;
}
PPH_HANDLE_NODE PhFindHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ HANDLE Handle
)
{
PH_HANDLE_NODE lookupHandleNode;
PPH_HANDLE_NODE lookupHandleNodePtr = &lookupHandleNode;
PPH_HANDLE_NODE *handleNode;
lookupHandleNode.Handle = Handle;
handleNode = (PPH_HANDLE_NODE *)PhFindEntryHashtable(
Context->NodeHashtable,
&lookupHandleNodePtr
);
if (handleNode)
return *handleNode;
else
return NULL;
}
VOID PhRemoveHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_NODE HandleNode
)
{
// Remove from the hashtable here to avoid problems in case the key is re-used.
PhRemoveEntryHashtable(Context->NodeHashtable, &HandleNode);
if (Context->EnableStateHighlighting)
{
PhChangeShStateTn(
&HandleNode->Node,
&HandleNode->ShState,
&Context->NodeStateList,
RemovingItemState,
PhCsColorRemoved,
Context->TreeNewHandle
);
}
else
{
PhpRemoveHandleNode(HandleNode, Context);
}
}
VOID PhpDestroyHandleNode(
_In_ PPH_HANDLE_NODE HandleNode
)
{
PhEmCallObjectOperation(EmHandleNodeType, HandleNode, EmObjectDelete);
if (HandleNode->GrantedAccessSymbolicText) PhDereferenceObject(HandleNode->GrantedAccessSymbolicText);
PhDereferenceObject(HandleNode->HandleItem);
PhFree(HandleNode);
}
VOID PhpRemoveHandleNode(
_In_ PPH_HANDLE_NODE HandleNode,
_In_ PPH_HANDLE_LIST_CONTEXT Context // PH_TICK_SH_STATE requires this parameter to be after HandleNode
)
{
ULONG index;
// Remove from list and cleanup.
if ((index = PhFindItemList(Context->NodeList, HandleNode)) != -1)
PhRemoveItemList(Context->NodeList, index);
PhpDestroyHandleNode(HandleNode);
TreeNew_NodesStructured(Context->TreeNewHandle);
}
VOID PhUpdateHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_NODE HandleNode
)
{
memset(HandleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHHNTLC_MAXIMUM);
PhInvalidateTreeNewNode(&HandleNode->Node, TN_CACHE_COLOR);
TreeNew_NodesStructured(Context->TreeNewHandle);
}
VOID PhTickHandleNodes(
_In_ PPH_HANDLE_LIST_CONTEXT Context
)
{
PH_TICK_SH_STATE_TN(PH_HANDLE_NODE, ShState, Context->NodeStateList, PhpRemoveHandleNode, PhCsHighlightingDuration, Context->TreeNewHandle, TRUE, NULL, Context);
}
#define SORT_FUNCTION(Column) PhpHandleTreeNewCompare##Column
#define BEGIN_SORT_FUNCTION(Column) static int __cdecl PhpHandleTreeNewCompare##Column( \
_In_ void *_context, \
_In_ const void *_elem1, \
_In_ const void *_elem2 \
) \
{ \
PPH_HANDLE_NODE node1 = *(PPH_HANDLE_NODE *)_elem1; \
PPH_HANDLE_NODE node2 = *(PPH_HANDLE_NODE *)_elem2; \
PPH_HANDLE_ITEM handleItem1 = node1->HandleItem; \
PPH_HANDLE_ITEM handleItem2 = node2->HandleItem; \
PPH_HANDLE_LIST_CONTEXT context = (PPH_HANDLE_LIST_CONTEXT)_context; \
int sortResult = 0;
#define END_SORT_FUNCTION \
if (sortResult == 0) \
sortResult = uintptrcmp((ULONG_PTR)node1->Handle, (ULONG_PTR)node2->Handle); \
\
return PhModifySort(sortResult, context->TreeNewSortOrder); \
}
LONG PhpHandleTreeNewPostSortFunction(
_In_ LONG Result,
_In_ PVOID Node1,
_In_ PVOID Node2,
_In_ PH_SORT_ORDER SortOrder
)
{
if (Result == 0)
Result = uintptrcmp((ULONG_PTR)((PPH_HANDLE_NODE)Node1)->Handle, (ULONG_PTR)((PPH_HANDLE_NODE)Node2)->Handle);
return PhModifySort(Result, SortOrder);
}
BEGIN_SORT_FUNCTION(Type)
{
sortResult = PhCompareString(handleItem1->TypeName, handleItem2->TypeName, TRUE);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(Name)
{
sortResult = PhCompareStringWithNull(handleItem1->BestObjectName, handleItem2->BestObjectName, TRUE);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(Handle)
{
sortResult = uintptrcmp((ULONG_PTR)node1->Handle, (ULONG_PTR)node2->Handle);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(ObjectAddress)
{
sortResult = uintptrcmp((ULONG_PTR)handleItem1->Object, (ULONG_PTR)handleItem2->Object);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(Attributes)
{
sortResult = uintcmp(handleItem1->Attributes, handleItem2->Attributes);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(GrantedAccess)
{
sortResult = uintcmp(handleItem1->GrantedAccess, handleItem2->GrantedAccess);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(OriginalName)
{
sortResult = PhCompareStringWithNull(handleItem1->ObjectName, handleItem2->ObjectName, TRUE);
}
END_SORT_FUNCTION
BEGIN_SORT_FUNCTION(FileShareAccess)
{
sortResult = uintcmp(handleItem1->FileFlags & (PH_HANDLE_FILE_SHARED_MASK), handleItem2->FileFlags & (PH_HANDLE_FILE_SHARED_MASK));
// Make sure all file handles get grouped together regardless of share access.
if (sortResult == 0)
sortResult = intcmp(PhEqualString2(handleItem1->TypeName, L"File", TRUE), PhEqualString2(handleItem2->TypeName, L"File", TRUE));
}
END_SORT_FUNCTION
BOOLEAN NTAPI PhpHandleTreeNewCallback(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2,
_In_opt_ PVOID Context
)
{
PPH_HANDLE_LIST_CONTEXT context;
PPH_HANDLE_NODE node;
context = Context;
if (PhCmForwardMessage(hwnd, Message, Parameter1, Parameter2, &context->Cm))
return TRUE;
switch (Message)
{
case TreeNewGetChildren:
{
PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
if (!getChildren->Node)
{
static PVOID sortFunctions[] =
{
SORT_FUNCTION(Type),
SORT_FUNCTION(Name),
SORT_FUNCTION(Handle),
SORT_FUNCTION(ObjectAddress),
SORT_FUNCTION(Attributes),
SORT_FUNCTION(GrantedAccess),
SORT_FUNCTION(GrantedAccess), // Granted Access (Symbolic)
SORT_FUNCTION(OriginalName),
SORT_FUNCTION(FileShareAccess)
};
int (__cdecl *sortFunction)(void *, const void *, const void *);
if (!PhCmForwardSort(
(PPH_TREENEW_NODE *)context->NodeList->Items,
context->NodeList->Count,
context->TreeNewSortColumn,
context->TreeNewSortOrder,
&context->Cm
))
{
if (context->TreeNewSortColumn < PHHNTLC_MAXIMUM)
sortFunction = sortFunctions[context->TreeNewSortColumn];
else
sortFunction = NULL;
}
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;
isLeaf->IsLeaf = TRUE;
}
return TRUE;
case TreeNewGetCellText:
{
PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
PPH_HANDLE_ITEM handleItem;
node = (PPH_HANDLE_NODE)getCellText->Node;
handleItem = node->HandleItem;
switch (getCellText->Id)
{
case PHHNTLC_TYPE:
getCellText->Text = handleItem->TypeName->sr;
break;
case PHHNTLC_NAME:
getCellText->Text = PhGetStringRef(handleItem->BestObjectName);
break;
case PHHNTLC_HANDLE:
PhInitializeStringRefLongHint(&getCellText->Text, handleItem->HandleString);
break;
case PHHNTLC_OBJECTADDRESS:
PhInitializeStringRefLongHint(&getCellText->Text, handleItem->ObjectString);
break;
case PHHNTLC_ATTRIBUTES:
switch (handleItem->Attributes & (OBJ_PROTECT_CLOSE | OBJ_INHERIT))
{
case OBJ_PROTECT_CLOSE:
PhInitializeStringRef(&getCellText->Text, L"Protected");
break;
case OBJ_INHERIT:
PhInitializeStringRef(&getCellText->Text, L"Inherit");
break;
case OBJ_PROTECT_CLOSE | OBJ_INHERIT:
PhInitializeStringRef(&getCellText->Text, L"Protected, Inherit");
break;
}
break;
case PHHNTLC_GRANTEDACCESS:
PhInitializeStringRefLongHint(&getCellText->Text, handleItem->GrantedAccessString);
break;
case PHHNTLC_GRANTEDACCESSSYMBOLIC:
if (handleItem->GrantedAccess != 0)
{
if (!node->GrantedAccessSymbolicText)
{
PPH_ACCESS_ENTRY accessEntries;
ULONG numberOfAccessEntries;
if (PhGetAccessEntries(handleItem->TypeName->Buffer, &accessEntries, &numberOfAccessEntries))
{
node->GrantedAccessSymbolicText = PhGetAccessString(handleItem->GrantedAccess, accessEntries, numberOfAccessEntries);
PhFree(accessEntries);
}
else
{
node->GrantedAccessSymbolicText = PhReferenceEmptyString();
}
}
if (node->GrantedAccessSymbolicText->Length != 0)
getCellText->Text = node->GrantedAccessSymbolicText->sr;
else
PhInitializeStringRefLongHint(&getCellText->Text, handleItem->GrantedAccessString);
}
break;
case PHHNTLC_ORIGINALNAME:
getCellText->Text = PhGetStringRef(handleItem->ObjectName);
break;
case PHHNTLC_FILESHAREACCESS:
if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_MASK)
{
node->FileShareAccessText[0] = '-';
node->FileShareAccessText[1] = '-';
node->FileShareAccessText[2] = '-';
node->FileShareAccessText[3] = 0;
if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_READ)
node->FileShareAccessText[0] = 'R';
if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_WRITE)
node->FileShareAccessText[1] = 'W';
if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_DELETE)
node->FileShareAccessText[2] = 'D';
PhInitializeStringRef(&getCellText->Text, node->FileShareAccessText);
}
break;
default:
return FALSE;
}
getCellText->Flags = TN_CACHE;
}
return TRUE;
case TreeNewGetNodeColor:
{
PPH_TREENEW_GET_NODE_COLOR getNodeColor = Parameter1;
PPH_HANDLE_ITEM handleItem;
node = (PPH_HANDLE_NODE)getNodeColor->Node;
handleItem = node->HandleItem;
if (!handleItem)
; // Dummy
else if (PhCsUseColorProtectedHandles && (handleItem->Attributes & OBJ_PROTECT_CLOSE))
getNodeColor->BackColor = PhCsColorProtectedHandles;
else if (PhCsUseColorInheritHandles && (handleItem->Attributes & OBJ_INHERIT))
getNodeColor->BackColor = PhCsColorInheritHandles;
getNodeColor->Flags = TN_CACHE | TN_AUTO_FORECOLOR;
}
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_HANDLE_COPY, 0);
break;
case 'A':
if (GetKeyState(VK_CONTROL) < 0)
TreeNew_SelectRange(context->TreeNewHandle, 0, -1);
break;
case VK_DELETE:
// Pass a 1 in lParam to indicate that warnings should be enabled.
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_CLOSE, 1);
break;
case VK_RETURN:
if (GetKeyState(VK_CONTROL) >= 0)
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_PROPERTIES, 0);
else
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_OBJECTPROPERTIES1, 0);
break;
}
}
return TRUE;
case TreeNewHeaderRightClick:
{
PH_TN_COLUMN_MENU_DATA data;
data.TreeNewHandle = hwnd;
data.MouseEvent = Parameter1;
data.DefaultSortColumn = 0;
data.DefaultSortOrder = AscendingSortOrder;
PhInitializeTreeNewColumnMenu(&data);
data.Selection = PhShowEMenu(data.Menu, hwnd, PH_EMENU_SHOW_LEFTRIGHT,
PH_ALIGN_LEFT | PH_ALIGN_TOP, data.MouseEvent->ScreenLocation.x, data.MouseEvent->ScreenLocation.y);
PhHandleTreeNewColumnMenu(&data);
PhDeleteTreeNewColumnMenu(&data);
}
return TRUE;
case TreeNewLeftDoubleClick:
{
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_PROPERTIES, 0);
}
return TRUE;
case TreeNewContextMenu:
{
PPH_TREENEW_CONTEXT_MENU contextMenu = Parameter1;
SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_SHOWCONTEXTMENU, (LPARAM)contextMenu);
}
return TRUE;
case TreeNewGetDialogCode:
{
PULONG code = Parameter2;
if (PtrToUlong(Parameter1) == VK_RETURN)
{
*code = DLGC_WANTMESSAGE;
return TRUE;
}
}
return FALSE;
}
return FALSE;
}
PPH_HANDLE_ITEM PhGetSelectedHandleItem(
_In_ PPH_HANDLE_LIST_CONTEXT Context
)
{
PPH_HANDLE_ITEM handleItem = NULL;
ULONG i;
for (i = 0; i < Context->NodeList->Count; i++)
{
PPH_HANDLE_NODE node = Context->NodeList->Items[i];
if (node->Node.Selected)
{
handleItem = node->HandleItem;
break;
}
}
return handleItem;
}
VOID PhGetSelectedHandleItems(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_Out_ PPH_HANDLE_ITEM **Handles,
_Out_ PULONG NumberOfHandles
)
{
PH_ARRAY array;
ULONG i;
PhInitializeArray(&array, sizeof(PVOID), 2);
for (i = 0; i < Context->NodeList->Count; i++)
{
PPH_HANDLE_NODE node = Context->NodeList->Items[i];
if (node->Node.Selected)
PhAddItemArray(&array, &node->HandleItem);
}
*NumberOfHandles = (ULONG)array.Count;
*Handles = PhFinalArrayItems(&array);
}
VOID PhDeselectAllHandleNodes(
_In_ PPH_HANDLE_LIST_CONTEXT Context
)
{
TreeNew_DeselectRange(Context->TreeNewHandle, 0, -1);
}

377
ProcessHacker/hndlmenu.c Normal file
View File

@ -0,0 +1,377 @@
/*
* Process Hacker -
* common handle menu items
*
* Copyright (C) 2016 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 <phapp.h>
#include <hndlmenu.h>
#include <procprv.h>
#include <kphuser.h>
#include <emenu.h>
#include <hndlinfo.h>
VOID PhInsertHandleObjectPropertiesEMenuItems(
_In_ struct _PH_EMENU_ITEM *Menu,
_In_ ULONG InsertBeforeId,
_In_ BOOLEAN EnableShortcut,
_In_ PPH_HANDLE_ITEM_INFO Info
)
{
PPH_EMENU_ITEM parentItem;
ULONG indexInParent;
if (!PhFindEMenuItemEx(Menu, 0, NULL, InsertBeforeId, &parentItem, &indexInParent))
return;
if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) ||
PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE))
{
if (PhEqualString2(Info->TypeName, L"File", TRUE))
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES2, L"File properties", NULL, NULL), indexInParent);
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES1, PhaAppendCtrlEnter(L"Open &file location", EnableShortcut), NULL, NULL), indexInParent);
}
else if (PhEqualString2(Info->TypeName, L"Key", TRUE))
{
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES1, PhaAppendCtrlEnter(L"Open key", EnableShortcut), NULL, NULL), indexInParent);
}
else if (PhEqualString2(Info->TypeName, L"Process", TRUE))
{
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES1, PhaAppendCtrlEnter(L"Process properties", EnableShortcut), NULL, NULL), indexInParent);
}
else if (PhEqualString2(Info->TypeName, L"Section", TRUE))
{
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES1, PhaAppendCtrlEnter(L"Read/Write memory", EnableShortcut), NULL, NULL), indexInParent);
}
else if (PhEqualString2(Info->TypeName, L"Thread", TRUE))
{
PhInsertEMenuItem(parentItem, PhCreateEMenuItem(0, ID_HANDLE_OBJECTPROPERTIES1, PhaAppendCtrlEnter(L"Go to thread", EnableShortcut), NULL, NULL), indexInParent);
}
}
static NTSTATUS PhpDuplicateHandleFromProcessItem(
_Out_ PHANDLE NewHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE ProcessId,
_In_ HANDLE Handle
)
{
NTSTATUS status;
HANDLE processHandle;
if (!NT_SUCCESS(status = PhOpenProcess(
&processHandle,
PROCESS_DUP_HANDLE,
ProcessId
)))
return status;
status = NtDuplicateObject(
processHandle,
Handle,
NtCurrentProcess(),
NewHandle,
DesiredAccess,
0,
0
);
NtClose(processHandle);
return status;
}
static VOID PhpShowProcessPropContext(
_In_ PVOID Parameter
)
{
PhShowProcessProperties(Parameter);
PhDereferenceObject(Parameter);
}
VOID PhShowHandleObjectProperties1(
_In_ HWND hWnd,
_In_ PPH_HANDLE_ITEM_INFO Info
)
{
if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) ||
PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE))
{
if (Info->BestObjectName)
PhShellExploreFile(hWnd, Info->BestObjectName->Buffer);
else
PhShowError(hWnd, L"Unable to open file location because the object is unnamed.");
}
else if (PhEqualString2(Info->TypeName, L"Key", TRUE))
{
if (Info->BestObjectName)
PhShellOpenKey2(hWnd, Info->BestObjectName);
else
PhShowError(hWnd, L"Unable to open key because the object is unnamed.");
}
else if (PhEqualString2(Info->TypeName, L"Process", TRUE))
{
HANDLE processHandle;
HANDLE processId;
PPH_PROCESS_ITEM targetProcessItem;
processId = NULL;
if (KphIsConnected())
{
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
Info->ProcessId
)))
{
PROCESS_BASIC_INFORMATION basicInfo;
if (NT_SUCCESS(KphQueryInformationObject(
processHandle,
Info->Handle,
KphObjectProcessBasicInformation,
&basicInfo,
sizeof(PROCESS_BASIC_INFORMATION),
NULL
)))
{
processId = basicInfo.UniqueProcessId;
}
NtClose(processHandle);
}
}
else
{
HANDLE handle;
PROCESS_BASIC_INFORMATION basicInfo;
if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
&handle,
ProcessQueryAccess,
Info->ProcessId,
Info->Handle
)))
{
if (NT_SUCCESS(PhGetProcessBasicInformation(handle, &basicInfo)))
processId = basicInfo.UniqueProcessId;
NtClose(handle);
}
}
if (processId)
{
targetProcessItem = PhReferenceProcessItem(processId);
if (targetProcessItem)
{
ProcessHacker_ShowProcessProperties(PhMainWndHandle, targetProcessItem);
PhDereferenceObject(targetProcessItem);
}
else
{
PhShowError(hWnd, L"The process does not exist.");
}
}
}
else if (PhEqualString2(Info->TypeName, L"Section", TRUE))
{
HANDLE handle = NULL;
BOOLEAN readOnly = FALSE;
if (!NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
&handle,
SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
Info->ProcessId,
Info->Handle
)))
{
PhpDuplicateHandleFromProcessItem(
&handle,
SECTION_QUERY | SECTION_MAP_READ,
Info->ProcessId,
Info->Handle
);
readOnly = TRUE;
}
if (handle)
{
NTSTATUS status;
PPH_STRING sectionName = NULL;
SECTION_BASIC_INFORMATION basicInfo;
SIZE_T viewSize = PH_MAX_SECTION_EDIT_SIZE;
PVOID viewBase = NULL;
BOOLEAN tooBig = FALSE;
PhGetHandleInformation(NtCurrentProcess(), handle, -1, NULL, NULL, NULL, &sectionName);
if (NT_SUCCESS(PhGetSectionBasicInformation(handle, &basicInfo)))
{
if (basicInfo.MaximumSize.QuadPart <= PH_MAX_SECTION_EDIT_SIZE)
viewSize = (SIZE_T)basicInfo.MaximumSize.QuadPart;
else
tooBig = TRUE;
status = NtMapViewOfSection(
handle,
NtCurrentProcess(),
&viewBase,
0,
0,
NULL,
&viewSize,
ViewShare,
0,
readOnly ? PAGE_READONLY : PAGE_READWRITE
);
if (status == STATUS_SECTION_PROTECTION && !readOnly)
{
status = NtMapViewOfSection(
handle,
NtCurrentProcess(),
&viewBase,
0,
0,
NULL,
&viewSize,
ViewShare,
0,
PAGE_READONLY
);
}
if (NT_SUCCESS(status))
{
PPH_SHOWMEMORYEDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR));
if (tooBig)
PhShowWarning(hWnd, L"The section size is greater than 32 MB. Only the first 32 MB will be available for editing.");
memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR));
showMemoryEditor->ProcessId = NtCurrentProcessId();
showMemoryEditor->BaseAddress = viewBase;
showMemoryEditor->RegionSize = viewSize;
showMemoryEditor->SelectOffset = -1;
showMemoryEditor->SelectLength = 0;
showMemoryEditor->Title = sectionName ? PhConcatStrings2(L"Section - ", sectionName->Buffer) : PhCreateString(L"Section");
showMemoryEditor->Flags = PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION;
ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor);
}
else
{
PhShowStatus(hWnd, L"Unable to map a view of the section", status, 0);
}
}
PhClearReference(&sectionName);
NtClose(handle);
}
}
else if (PhEqualString2(Info->TypeName, L"Thread", TRUE))
{
HANDLE processHandle;
CLIENT_ID clientId;
PPH_PROCESS_ITEM targetProcessItem;
PPH_PROCESS_PROPCONTEXT propContext;
clientId.UniqueProcess = NULL;
clientId.UniqueThread = NULL;
if (KphIsConnected())
{
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
ProcessQueryAccess,
Info->ProcessId
)))
{
THREAD_BASIC_INFORMATION basicInfo;
if (NT_SUCCESS(KphQueryInformationObject(
processHandle,
Info->Handle,
KphObjectThreadBasicInformation,
&basicInfo,
sizeof(THREAD_BASIC_INFORMATION),
NULL
)))
{
clientId = basicInfo.ClientId;
}
NtClose(processHandle);
}
}
else
{
HANDLE handle;
THREAD_BASIC_INFORMATION basicInfo;
if (NT_SUCCESS(PhpDuplicateHandleFromProcessItem(
&handle,
ThreadQueryAccess,
Info->ProcessId,
Info->Handle
)))
{
if (NT_SUCCESS(PhGetThreadBasicInformation(handle, &basicInfo)))
clientId = basicInfo.ClientId;
NtClose(handle);
}
}
if (clientId.UniqueProcess)
{
targetProcessItem = PhReferenceProcessItem(clientId.UniqueProcess);
if (targetProcessItem)
{
propContext = PhCreateProcessPropContext(PhMainWndHandle, targetProcessItem);
PhDereferenceObject(targetProcessItem);
PhSetSelectThreadIdProcessPropContext(propContext, clientId.UniqueThread);
ProcessHacker_Invoke(PhMainWndHandle, PhpShowProcessPropContext, propContext);
}
else
{
PhShowError(hWnd, L"The process does not exist.");
}
}
}
}
VOID PhShowHandleObjectProperties2(
_In_ HWND hWnd,
_In_ PPH_HANDLE_ITEM_INFO Info
)
{
if (PhEqualString2(Info->TypeName, L"File", TRUE) || PhEqualString2(Info->TypeName, L"DLL", TRUE) ||
PhEqualString2(Info->TypeName, L"Mapped file", TRUE) || PhEqualString2(Info->TypeName, L"Mapped image", TRUE))
{
if (Info->BestObjectName)
PhShellProperties(hWnd, Info->BestObjectName->Buffer);
else
PhShowError(hWnd, L"Unable to open file properties because the object is unnamed.");
}
}

331
ProcessHacker/hndlprp.c Normal file
View File

@ -0,0 +1,331 @@
/*
* Process Hacker -
* handle properties
*
* Copyright (C) 2010-2013 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 <phapp.h>
#include <kphuser.h>
#include <hndlprv.h>
#include <hndlinfo.h>
#include <secedit.h>
#include <phplug.h>
typedef struct _HANDLE_PROPERTIES_CONTEXT
{
HANDLE ProcessId;
PPH_HANDLE_ITEM HandleItem;
} HANDLE_PROPERTIES_CONTEXT, *PHANDLE_PROPERTIES_CONTEXT;
INT_PTR CALLBACK PhpHandleGeneralDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
static NTSTATUS PhpDuplicateHandleFromProcess(
_Out_ PHANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ PVOID Context
)
{
NTSTATUS status;
PHANDLE_PROPERTIES_CONTEXT context = Context;
HANDLE processHandle;
if (!NT_SUCCESS(status = PhOpenProcess(
&processHandle,
PROCESS_DUP_HANDLE,
context->ProcessId
)))
return status;
status = NtDuplicateObject(
processHandle,
context->HandleItem->Handle,
NtCurrentProcess(),
Handle,
DesiredAccess,
0,
0
);
NtClose(processHandle);
return status;
}
VOID PhShowHandleProperties(
_In_ HWND ParentWindowHandle,
_In_ HANDLE ProcessId,
_In_ PPH_HANDLE_ITEM HandleItem
)
{
PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) };
PROPSHEETPAGE propSheetPage;
HPROPSHEETPAGE pages[16];
HANDLE_PROPERTIES_CONTEXT context;
PH_STD_OBJECT_SECURITY stdObjectSecurity;
PPH_ACCESS_ENTRY accessEntries;
ULONG numberOfAccessEntries;
context.ProcessId = ProcessId;
context.HandleItem = HandleItem;
propSheetHeader.dwFlags =
PSH_NOAPPLYNOW |
PSH_NOCONTEXTHELP |
PSH_PROPTITLE;
propSheetHeader.hwndParent = ParentWindowHandle;
propSheetHeader.pszCaption = L"Handle";
propSheetHeader.nPages = 0;
propSheetHeader.nStartPage = 0;
propSheetHeader.phpage = pages;
// General page
memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_HNDLGENERAL);
propSheetPage.pfnDlgProc = PhpHandleGeneralDlgProc;
propSheetPage.lParam = (LPARAM)&context;
pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
// Object-specific page
if (!HandleItem->TypeName)
{
// Dummy
}
else if (PhEqualString2(HandleItem->TypeName, L"Event", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateEventPage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"EventPair", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateEventPairPage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Job", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateJobPage(
PhpDuplicateHandleFromProcess,
&context,
NULL
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Mutant", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateMutantPage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Section", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateSectionPage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Semaphore", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateSemaphorePage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Timer", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateTimerPage(
PhpDuplicateHandleFromProcess,
&context
);
}
else if (PhEqualString2(HandleItem->TypeName, L"Token", TRUE))
{
pages[propSheetHeader.nPages++] = PhCreateTokenPage(
PhpDuplicateHandleFromProcess,
&context,
NULL
);
}
// Security page
stdObjectSecurity.OpenObject = PhpDuplicateHandleFromProcess;
stdObjectSecurity.ObjectType = HandleItem->TypeName->Buffer;
stdObjectSecurity.Context = &context;
if (PhGetAccessEntries(HandleItem->TypeName->Buffer, &accessEntries, &numberOfAccessEntries))
{
pages[propSheetHeader.nPages++] = PhCreateSecurityPage(
PhGetStringOrEmpty(HandleItem->BestObjectName),
PhStdGetObjectSecurity,
PhStdSetObjectSecurity,
&stdObjectSecurity,
accessEntries,
numberOfAccessEntries
);
PhFree(accessEntries);
}
if (PhPluginsEnabled)
{
PH_PLUGIN_OBJECT_PROPERTIES objectProperties;
PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT propertiesContext;
propertiesContext.ProcessId = ProcessId;
propertiesContext.HandleItem = HandleItem;
objectProperties.Parameter = &propertiesContext;
objectProperties.NumberOfPages = propSheetHeader.nPages;
objectProperties.MaximumNumberOfPages = sizeof(pages) / sizeof(HPROPSHEETPAGE);
objectProperties.Pages = pages;
PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackHandlePropertiesInitializing), &objectProperties);
propSheetHeader.nPages = objectProperties.NumberOfPages;
}
PhModalPropertySheet(&propSheetHeader);
}
INT_PTR CALLBACK PhpHandleGeneralDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam;
PHANDLE_PROPERTIES_CONTEXT context = (PHANDLE_PROPERTIES_CONTEXT)propSheetPage->lParam;
PPH_ACCESS_ENTRY accessEntries;
ULONG numberOfAccessEntries;
HANDLE processHandle;
OBJECT_BASIC_INFORMATION basicInfo;
BOOLEAN haveBasicInfo = FALSE;
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context);
SetDlgItemText(hwndDlg, IDC_NAME, PhGetString(context->HandleItem->BestObjectName));
SetDlgItemText(hwndDlg, IDC_TYPE, context->HandleItem->TypeName->Buffer);
SetDlgItemText(hwndDlg, IDC_ADDRESS, context->HandleItem->ObjectString);
if (PhGetAccessEntries(
context->HandleItem->TypeName->Buffer,
&accessEntries,
&numberOfAccessEntries
))
{
PPH_STRING accessString;
PPH_STRING grantedAccessString;
accessString = PH_AUTO(PhGetAccessString(
context->HandleItem->GrantedAccess,
accessEntries,
numberOfAccessEntries
));
if (accessString->Length != 0)
{
grantedAccessString = PhaFormatString(
L"%s (%s)",
context->HandleItem->GrantedAccessString,
accessString->Buffer
);
SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, grantedAccessString->Buffer);
}
else
{
SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, context->HandleItem->GrantedAccessString);
}
PhFree(accessEntries);
}
else
{
SetDlgItemText(hwndDlg, IDC_GRANTED_ACCESS, context->HandleItem->GrantedAccessString);
}
if (NT_SUCCESS(PhOpenProcess(
&processHandle,
PROCESS_DUP_HANDLE,
context->ProcessId
)))
{
if (NT_SUCCESS(PhGetHandleInformation(
processHandle,
context->HandleItem->Handle,
-1,
&basicInfo,
NULL,
NULL,
NULL
)))
{
SetDlgItemInt(hwndDlg, IDC_REFERENCES, basicInfo.PointerCount, FALSE);
SetDlgItemInt(hwndDlg, IDC_HANDLES, basicInfo.HandleCount, FALSE);
SetDlgItemInt(hwndDlg, IDC_PAGED, basicInfo.PagedPoolCharge, FALSE);
SetDlgItemInt(hwndDlg, IDC_NONPAGED, basicInfo.NonPagedPoolCharge, FALSE);
haveBasicInfo = TRUE;
}
NtClose(processHandle);
}
if (!haveBasicInfo)
{
SetDlgItemText(hwndDlg, IDC_REFERENCES, L"Unknown");
SetDlgItemText(hwndDlg, IDC_HANDLES, L"Unknown");
SetDlgItemText(hwndDlg, IDC_PAGED, L"Unknown");
SetDlgItemText(hwndDlg, IDC_NONPAGED, L"Unknown");
}
}
break;
case WM_DESTROY:
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
break;
case WM_NOTIFY:
{
LPNMHDR header = (LPNMHDR)lParam;
switch (header->code)
{
case PSN_QUERYINITIALFOCUS:
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_BASICINFORMATION));
}
return TRUE;
}
}
break;
}
return FALSE;
}

718
ProcessHacker/hndlprv.c Normal file
View File

@ -0,0 +1,718 @@
/*
* Process Hacker -
* handle provider
*
* Copyright (C) 2010-2015 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 <phapp.h>
#include <hndlprv.h>
#include <workqueue.h>
#include <kphuser.h>
#include <hndlinfo.h>
#include <extmgri.h>
typedef struct _PHP_CREATE_HANDLE_ITEM_CONTEXT
{
PPH_HANDLE_PROVIDER Provider;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle;
} PHP_CREATE_HANDLE_ITEM_CONTEXT, *PPHP_CREATE_HANDLE_ITEM_CONTEXT;
VOID NTAPI PhpHandleProviderDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
);
VOID NTAPI PhpHandleItemDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
);
PPH_OBJECT_TYPE PhHandleProviderType;
PPH_OBJECT_TYPE PhHandleItemType;
BOOLEAN PhHandleProviderInitialization(
VOID
)
{
PhHandleProviderType = PhCreateObjectType(L"HandleProvider", 0, PhpHandleProviderDeleteProcedure);
PhHandleItemType = PhCreateObjectType(L"HandleItem", 0, PhpHandleItemDeleteProcedure);
return TRUE;
}
PPH_HANDLE_PROVIDER PhCreateHandleProvider(
_In_ HANDLE ProcessId
)
{
PPH_HANDLE_PROVIDER handleProvider;
handleProvider = PhCreateObject(
PhEmGetObjectSize(EmHandleProviderType, sizeof(PH_HANDLE_PROVIDER)),
PhHandleProviderType
);
handleProvider->HandleHashSetSize = 128;
handleProvider->HandleHashSet = PhCreateHashSet(handleProvider->HandleHashSetSize);
handleProvider->HandleHashSetCount = 0;
PhInitializeQueuedLock(&handleProvider->HandleHashSetLock);
PhInitializeCallback(&handleProvider->HandleAddedEvent);
PhInitializeCallback(&handleProvider->HandleModifiedEvent);
PhInitializeCallback(&handleProvider->HandleRemovedEvent);
PhInitializeCallback(&handleProvider->UpdatedEvent);
handleProvider->ProcessId = ProcessId;
handleProvider->ProcessHandle = NULL;
handleProvider->RunStatus = PhOpenProcess(
&handleProvider->ProcessHandle,
PROCESS_DUP_HANDLE,
ProcessId
);
handleProvider->TempListHashtable = PhCreateSimpleHashtable(20);
PhEmCallObjectOperation(EmHandleProviderType, handleProvider, EmObjectCreate);
return handleProvider;
}
VOID PhpHandleProviderDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
)
{
PPH_HANDLE_PROVIDER handleProvider = (PPH_HANDLE_PROVIDER)Object;
PhEmCallObjectOperation(EmHandleProviderType, handleProvider, EmObjectDelete);
// Dereference all handle items (we referenced them
// when we added them to the hashtable).
PhDereferenceAllHandleItems(handleProvider);
PhFree(handleProvider->HandleHashSet);
PhDeleteCallback(&handleProvider->HandleAddedEvent);
PhDeleteCallback(&handleProvider->HandleModifiedEvent);
PhDeleteCallback(&handleProvider->HandleRemovedEvent);
if (handleProvider->ProcessHandle) NtClose(handleProvider->ProcessHandle);
PhDereferenceObject(handleProvider->TempListHashtable);
}
PPH_HANDLE_ITEM PhCreateHandleItem(
_In_opt_ PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle
)
{
PPH_HANDLE_ITEM handleItem;
handleItem = PhCreateObject(
PhEmGetObjectSize(EmHandleItemType, sizeof(PH_HANDLE_ITEM)),
PhHandleItemType
);
memset(handleItem, 0, sizeof(PH_HANDLE_ITEM));
if (Handle)
{
handleItem->Handle = (HANDLE)Handle->HandleValue;
PhPrintPointer(handleItem->HandleString, (PVOID)handleItem->Handle);
handleItem->Object = Handle->Object;
PhPrintPointer(handleItem->ObjectString, handleItem->Object);
handleItem->Attributes = Handle->HandleAttributes;
handleItem->GrantedAccess = (ACCESS_MASK)Handle->GrantedAccess;
PhPrintPointer(handleItem->GrantedAccessString, UlongToPtr(handleItem->GrantedAccess));
}
PhEmCallObjectOperation(EmHandleItemType, handleItem, EmObjectCreate);
return handleItem;
}
VOID PhpHandleItemDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
)
{
PPH_HANDLE_ITEM handleItem = (PPH_HANDLE_ITEM)Object;
PhEmCallObjectOperation(EmHandleItemType, handleItem, EmObjectDelete);
if (handleItem->TypeName) PhDereferenceObject(handleItem->TypeName);
if (handleItem->ObjectName) PhDereferenceObject(handleItem->ObjectName);
if (handleItem->BestObjectName) PhDereferenceObject(handleItem->BestObjectName);
}
FORCEINLINE BOOLEAN PhCompareHandleItem(
_In_ PPH_HANDLE_ITEM Value1,
_In_ PPH_HANDLE_ITEM Value2
)
{
return Value1->Handle == Value2->Handle;
}
FORCEINLINE ULONG PhHashHandleItem(
_In_ PPH_HANDLE_ITEM Value
)
{
return HandleToUlong(Value->Handle) / 4;
}
PPH_HANDLE_ITEM PhpLookupHandleItem(
_In_ PPH_HANDLE_PROVIDER HandleProvider,
_In_ HANDLE Handle
)
{
PH_HANDLE_ITEM lookupHandleItem;
PPH_HASH_ENTRY entry;
PPH_HANDLE_ITEM handleItem;
lookupHandleItem.Handle = Handle;
entry = PhFindEntryHashSet(
HandleProvider->HandleHashSet,
HandleProvider->HandleHashSetSize,
PhHashHandleItem(&lookupHandleItem)
);
for (; entry; entry = entry->Next)
{
handleItem = CONTAINING_RECORD(entry, PH_HANDLE_ITEM, HashEntry);
if (PhCompareHandleItem(&lookupHandleItem, handleItem))
return handleItem;
}
return NULL;
}
PPH_HANDLE_ITEM PhReferenceHandleItem(
_In_ PPH_HANDLE_PROVIDER HandleProvider,
_In_ HANDLE Handle
)
{
PPH_HANDLE_ITEM handleItem;
PhAcquireQueuedLockShared(&HandleProvider->HandleHashSetLock);
handleItem = PhpLookupHandleItem(HandleProvider, Handle);
if (handleItem)
PhReferenceObject(handleItem);
PhReleaseQueuedLockShared(&HandleProvider->HandleHashSetLock);
return handleItem;
}
VOID PhDereferenceAllHandleItems(
_In_ PPH_HANDLE_PROVIDER HandleProvider
)
{
ULONG i;
PPH_HASH_ENTRY entry;
PPH_HANDLE_ITEM handleItem;
PhAcquireQueuedLockExclusive(&HandleProvider->HandleHashSetLock);
for (i = 0; i < HandleProvider->HandleHashSetSize; i++)
{
entry = HandleProvider->HandleHashSet[i];
while (entry)
{
handleItem = CONTAINING_RECORD(entry, PH_HANDLE_ITEM, HashEntry);
entry = entry->Next;
PhDereferenceObject(handleItem);
}
}
PhReleaseQueuedLockExclusive(&HandleProvider->HandleHashSetLock);
}
VOID PhpAddHandleItem(
_In_ PPH_HANDLE_PROVIDER HandleProvider,
_In_ _Assume_refs_(1) PPH_HANDLE_ITEM HandleItem
)
{
if (HandleProvider->HandleHashSetSize < HandleProvider->HandleHashSetCount + 1)
{
PhResizeHashSet(
&HandleProvider->HandleHashSet,
&HandleProvider->HandleHashSetSize,
HandleProvider->HandleHashSetSize * 2
);
}
PhAddEntryHashSet(
HandleProvider->HandleHashSet,
HandleProvider->HandleHashSetSize,
&HandleItem->HashEntry,
PhHashHandleItem(HandleItem)
);
HandleProvider->HandleHashSetCount++;
}
VOID PhpRemoveHandleItem(
_In_ PPH_HANDLE_PROVIDER HandleProvider,
_In_ PPH_HANDLE_ITEM HandleItem
)
{
PhRemoveEntryHashSet(HandleProvider->HandleHashSet, HandleProvider->HandleHashSetSize, &HandleItem->HashEntry);
HandleProvider->HandleHashSetCount--;
PhDereferenceObject(HandleItem);
}
/**
* Enumerates all handles in a process.
*
* \param ProcessId The ID of the process.
* \param ProcessHandle A handle to the process.
* \param Handles A variable which receives a pointer to a buffer containing
* information about the handles.
* \param FilterNeeded A variable which receives a boolean indicating
* whether the handle information needs to be filtered by process ID.
*/
NTSTATUS PhEnumHandlesGeneric(
_In_ HANDLE ProcessId,
_In_ HANDLE ProcessHandle,
_Out_ PSYSTEM_HANDLE_INFORMATION_EX *Handles,
_Out_ PBOOLEAN FilterNeeded
)
{
NTSTATUS status;
// There are three ways of enumerating handles:
// * When KProcessHacker is available, using KphEnumerateProcessHandles
// is the most efficient method.
// * On Windows XP and later, NtQuerySystemInformation with
// SystemExtendedHandleInformation can be used.
// * Otherwise, NtQuerySystemInformation with SystemHandleInformation
// can be used.
if (KphIsConnected())
{
PKPH_PROCESS_HANDLE_INFORMATION handles;
PSYSTEM_HANDLE_INFORMATION_EX convertedHandles;
ULONG i;
// Enumerate handles using KProcessHacker. Unlike with NtQuerySystemInformation,
// this only enumerates handles for a single process and saves a lot of processing.
if (NT_SUCCESS(status = KphEnumerateProcessHandles2(ProcessHandle, &handles)))
{
convertedHandles = PhAllocate(
FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles) +
sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX) * handles->HandleCount
);
convertedHandles->NumberOfHandles = handles->HandleCount;
for (i = 0; i < handles->HandleCount; i++)
{
convertedHandles->Handles[i].Object = handles->Handles[i].Object;
convertedHandles->Handles[i].UniqueProcessId = (ULONG_PTR)ProcessId;
convertedHandles->Handles[i].HandleValue = (ULONG_PTR)handles->Handles[i].Handle;
convertedHandles->Handles[i].GrantedAccess = (ULONG)handles->Handles[i].GrantedAccess;
convertedHandles->Handles[i].CreatorBackTraceIndex = 0;
convertedHandles->Handles[i].ObjectTypeIndex = handles->Handles[i].ObjectTypeIndex;
convertedHandles->Handles[i].HandleAttributes = handles->Handles[i].HandleAttributes;
}
PhFree(handles);
*Handles = convertedHandles;
*FilterNeeded = FALSE;
return status;
}
}
if (WindowsVersion >= WINDOWS_XP)
{
PSYSTEM_HANDLE_INFORMATION_EX handles;
// Enumerate handles using the new method; no conversion
// necessary.
if (!NT_SUCCESS(status = PhEnumHandlesEx(&handles)))
return status;
*Handles = handles;
*FilterNeeded = TRUE;
}
else
{
PSYSTEM_HANDLE_INFORMATION handles;
PSYSTEM_HANDLE_INFORMATION_EX convertedHandles;
ULONG count;
ULONG allocatedCount;
ULONG i;
// Enumerate handles using the old info class and convert
// the relevant entries to the new format.
if (!NT_SUCCESS(status = PhEnumHandles(&handles)))
return status;
count = 0;
allocatedCount = 100;
convertedHandles = PhAllocate(
FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles) +
sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX) * allocatedCount
);
for (i = 0; i < handles->NumberOfHandles; i++)
{
if ((HANDLE)handles->Handles[i].UniqueProcessId != ProcessId)
continue;
if (count == allocatedCount)
{
allocatedCount *= 2;
convertedHandles = PhReAllocate(
convertedHandles,
FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handles) +
sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX) * allocatedCount
);
}
convertedHandles->Handles[count].Object = handles->Handles[i].Object;
convertedHandles->Handles[count].UniqueProcessId = (ULONG_PTR)handles->Handles[i].UniqueProcessId;
convertedHandles->Handles[count].HandleValue = (ULONG_PTR)handles->Handles[i].HandleValue;
convertedHandles->Handles[count].GrantedAccess = handles->Handles[i].GrantedAccess;
convertedHandles->Handles[count].CreatorBackTraceIndex = handles->Handles[i].CreatorBackTraceIndex;
convertedHandles->Handles[count].ObjectTypeIndex = handles->Handles[i].ObjectTypeIndex;
convertedHandles->Handles[count].HandleAttributes = (ULONG)handles->Handles[i].HandleAttributes;
count++;
}
convertedHandles->NumberOfHandles = count;
PhFree(handles);
*Handles = convertedHandles;
*FilterNeeded = FALSE;
}
return STATUS_SUCCESS;
}
NTSTATUS PhpCreateHandleItemFunction(
_In_ PVOID Parameter
)
{
PPHP_CREATE_HANDLE_ITEM_CONTEXT context = Parameter;
PPH_HANDLE_ITEM handleItem;
handleItem = PhCreateHandleItem(context->Handle);
PhGetHandleInformationEx(
context->Provider->ProcessHandle,
handleItem->Handle,
context->Handle->ObjectTypeIndex,
0,
NULL,
NULL,
&handleItem->TypeName,
&handleItem->ObjectName,
&handleItem->BestObjectName,
NULL
);
if (handleItem->TypeName)
{
// Add the handle item to the hashtable.
PhAcquireQueuedLockExclusive(&context->Provider->HandleHashSetLock);
PhpAddHandleItem(context->Provider, handleItem);
PhReleaseQueuedLockExclusive(&context->Provider->HandleHashSetLock);
// Raise the handle added event.
PhInvokeCallback(&context->Provider->HandleAddedEvent, handleItem);
}
else
{
PhDereferenceObject(handleItem);
}
PhFree(context);
return STATUS_SUCCESS;
}
VOID PhHandleProviderUpdate(
_In_ PVOID Object
)
{
static PH_INITONCE initOnce = PH_INITONCE_INIT;
static ULONG fileObjectTypeIndex = -1;
PPH_HANDLE_PROVIDER handleProvider = (PPH_HANDLE_PROVIDER)Object;
PSYSTEM_HANDLE_INFORMATION_EX handleInfo;
BOOLEAN filterNeeded;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handles;
ULONG numberOfHandles;
ULONG i;
PH_HASHTABLE_ENUM_CONTEXT enumContext;
PPH_KEY_VALUE_PAIR handlePair;
BOOLEAN useWorkQueue = FALSE;
PH_WORK_QUEUE workQueue;
if (!handleProvider->ProcessHandle)
goto UpdateExit;
if (!NT_SUCCESS(handleProvider->RunStatus = PhEnumHandlesGeneric(
handleProvider->ProcessId,
handleProvider->ProcessHandle,
&handleInfo,
&filterNeeded
)))
goto UpdateExit;
if (!KphIsConnected() && WindowsVersion >= WINDOWS_VISTA)
{
useWorkQueue = TRUE;
PhInitializeWorkQueue(&workQueue, 1, 20, 1000);
if (PhBeginInitOnce(&initOnce))
{
UNICODE_STRING fileTypeName;
RtlInitUnicodeString(&fileTypeName, L"File");
fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName);
PhEndInitOnce(&initOnce);
}
}
handles = handleInfo->Handles;
numberOfHandles = (ULONG)handleInfo->NumberOfHandles;
// Make a list of the relevant handles.
if (filterNeeded)
{
for (i = 0; i < (ULONG)numberOfHandles; i++)
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handle = &handles[i];
if (handle->UniqueProcessId == (ULONG_PTR)handleProvider->ProcessId)
{
PhAddItemSimpleHashtable(
handleProvider->TempListHashtable,
(PVOID)handle->HandleValue,
handle
);
}
}
}
else
{
for (i = 0; i < (ULONG)numberOfHandles; i++)
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handle = &handles[i];
PhAddItemSimpleHashtable(
handleProvider->TempListHashtable,
(PVOID)handle->HandleValue,
handle
);
}
}
// Look for closed handles.
{
PPH_LIST handlesToRemove = NULL;
PPH_HASH_ENTRY entry;
PPH_HANDLE_ITEM handleItem;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX *tempHashtableValue;
for (i = 0; i < handleProvider->HandleHashSetSize; i++)
{
for (entry = handleProvider->HandleHashSet[i]; entry; entry = entry->Next)
{
BOOLEAN found = FALSE;
handleItem = CONTAINING_RECORD(entry, PH_HANDLE_ITEM, HashEntry);
// Check if the handle still exists.
tempHashtableValue = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX *)PhFindItemSimpleHashtable(
handleProvider->TempListHashtable,
(PVOID)(handleItem->Handle)
);
if (tempHashtableValue)
{
// Also compare the object pointers to make sure a
// different object wasn't re-opened with the same
// handle value. This isn't 100% accurate as pool
// addresses may be re-used, but it works well.
if (handleItem->Object == (*tempHashtableValue)->Object)
{
found = TRUE;
}
}
if (!found)
{
// Raise the handle removed event.
PhInvokeCallback(&handleProvider->HandleRemovedEvent, handleItem);
if (!handlesToRemove)
handlesToRemove = PhCreateList(2);
PhAddItemList(handlesToRemove, handleItem);
}
}
}
if (handlesToRemove)
{
PhAcquireQueuedLockExclusive(&handleProvider->HandleHashSetLock);
for (i = 0; i < handlesToRemove->Count; i++)
{
PhpRemoveHandleItem(
handleProvider,
(PPH_HANDLE_ITEM)handlesToRemove->Items[i]
);
}
PhReleaseQueuedLockExclusive(&handleProvider->HandleHashSetLock);
PhDereferenceObject(handlesToRemove);
}
}
// Look for new handles and update existing ones.
PhBeginEnumHashtable(handleProvider->TempListHashtable, &enumContext);
while (handlePair = PhNextEnumHashtable(&enumContext))
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handle = handlePair->Value;
PPH_HANDLE_ITEM handleItem;
handleItem = PhpLookupHandleItem(handleProvider, (HANDLE)handle->HandleValue);
if (!handleItem)
{
// When we don't have KPH, query handle information in parallel to take full advantage of the
// PhCallWithTimeout functionality.
if (useWorkQueue && handle->ObjectTypeIndex == fileObjectTypeIndex)
{
PPHP_CREATE_HANDLE_ITEM_CONTEXT context;
context = PhAllocate(sizeof(PHP_CREATE_HANDLE_ITEM_CONTEXT));
context->Provider = handleProvider;
context->Handle = handle;
PhQueueItemWorkQueue(&workQueue, PhpCreateHandleItemFunction, context);
continue;
}
handleItem = PhCreateHandleItem(handle);
PhGetHandleInformationEx(
handleProvider->ProcessHandle,
handleItem->Handle,
handle->ObjectTypeIndex,
0,
NULL,
NULL,
&handleItem->TypeName,
&handleItem->ObjectName,
&handleItem->BestObjectName,
NULL
);
// We need at least a type name to continue.
if (!handleItem->TypeName)
{
PhDereferenceObject(handleItem);
continue;
}
if (PhEqualString2(handleItem->TypeName, L"File", TRUE) && KphIsConnected())
{
KPH_FILE_OBJECT_INFORMATION objectInfo;
if (NT_SUCCESS(KphQueryInformationObject(
handleProvider->ProcessHandle,
handleItem->Handle,
KphObjectFileObjectInformation,
&objectInfo,
sizeof(KPH_FILE_OBJECT_INFORMATION),
NULL
)))
{
if (objectInfo.SharedRead)
handleItem->FileFlags |= PH_HANDLE_FILE_SHARED_READ;
if (objectInfo.SharedWrite)
handleItem->FileFlags |= PH_HANDLE_FILE_SHARED_WRITE;
if (objectInfo.SharedDelete)
handleItem->FileFlags |= PH_HANDLE_FILE_SHARED_DELETE;
}
}
// Add the handle item to the hashtable.
PhAcquireQueuedLockExclusive(&handleProvider->HandleHashSetLock);
PhpAddHandleItem(handleProvider, handleItem);
PhReleaseQueuedLockExclusive(&handleProvider->HandleHashSetLock);
// Raise the handle added event.
PhInvokeCallback(&handleProvider->HandleAddedEvent, handleItem);
}
else
{
BOOLEAN modified = FALSE;
if (handleItem->Attributes != handle->HandleAttributes)
{
handleItem->Attributes = handle->HandleAttributes;
modified = TRUE;
}
if (modified)
{
// Raise the handle modified event.
PhInvokeCallback(&handleProvider->HandleModifiedEvent, handleItem);
}
}
}
if (useWorkQueue)
{
PhWaitForWorkQueue(&workQueue);
PhDeleteWorkQueue(&workQueue);
}
PhFree(handleInfo);
// Re-create the temporary hashtable if it got too big.
if (handleProvider->TempListHashtable->AllocatedEntries > 8192)
{
PhDereferenceObject(handleProvider->TempListHashtable);
handleProvider->TempListHashtable = PhCreateSimpleHashtable(512);
}
else
{
PhClearHashtable(handleProvider->TempListHashtable);
}
UpdateExit:
PhInvokeCallback(&handleProvider->UpdatedEvent, NULL);
}

238
ProcessHacker/hndlstat.c Normal file
View File

@ -0,0 +1,238 @@
/*
* Process Hacker -
* handle statistics window
*
* Copyright (C) 2010 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 <phapp.h>
#include <hndlprv.h>
#include <hndlinfo.h>
typedef struct _HANDLE_STATISTICS_ENTRY
{
PPH_STRING Name;
ULONG Count;
} HANDLE_STATISTICS_ENTRY, *PHANDLE_STATISTICS_ENTRY;
typedef struct _HANDLE_STATISTICS_CONTEXT
{
HANDLE ProcessId;
HANDLE ProcessHandle;
PSYSTEM_HANDLE_INFORMATION_EX Handles;
HANDLE_STATISTICS_ENTRY Entries[MAX_OBJECT_TYPE_NUMBER];
} HANDLE_STATISTICS_CONTEXT, *PHANDLE_STATISTICS_CONTEXT;
INT_PTR CALLBACK PhpHandleStatisticsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhShowHandleStatisticsDialog(
_In_ HWND ParentWindowHandle,
_In_ HANDLE ProcessId
)
{
NTSTATUS status;
HANDLE_STATISTICS_CONTEXT context;
BOOLEAN filterNeeded;
ULONG i;
context.ProcessId = ProcessId;
if (!NT_SUCCESS(status = PhOpenProcess(
&context.ProcessHandle,
PROCESS_DUP_HANDLE,
ProcessId
)))
{
PhShowStatus(ParentWindowHandle, L"Unable to open the process", status, 0);
return;
}
status = PhEnumHandlesGeneric(
context.ProcessId,
context.ProcessHandle,
&context.Handles,
&filterNeeded
);
if (!NT_SUCCESS(status))
{
NtClose(context.ProcessHandle);
PhShowStatus(ParentWindowHandle, L"Unable to enumerate process handles", status, 0);
return;
}
memset(&context.Entries, 0, sizeof(context.Entries));
DialogBoxParam(
PhInstanceHandle,
MAKEINTRESOURCE(IDD_HANDLESTATS),
ParentWindowHandle,
PhpHandleStatisticsDlgProc,
(LPARAM)&context
);
for (i = 0; i < MAX_OBJECT_TYPE_NUMBER; i++)
{
if (context.Entries[i].Name)
PhDereferenceObject(context.Entries[i].Name);
}
PhFree(context.Handles);
NtClose(context.ProcessHandle);
}
static INT NTAPI PhpTypeCountCompareFunction(
_In_ PVOID Item1,
_In_ PVOID Item2,
_In_opt_ PVOID Context
)
{
PHANDLE_STATISTICS_ENTRY entry1 = Item1;
PHANDLE_STATISTICS_ENTRY entry2 = Item2;
return uintcmp(entry1->Count, entry2->Count);
}
INT_PTR CALLBACK PhpHandleStatisticsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
PHANDLE_STATISTICS_CONTEXT context = (PHANDLE_STATISTICS_CONTEXT)lParam;
HANDLE processId;
ULONG_PTR i;
HWND lvHandle;
processId = context->ProcessId;
for (i = 0; i < context->Handles->NumberOfHandles; i++)
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo;
PHANDLE_STATISTICS_ENTRY entry;
PPH_STRING typeName;
handleInfo = &context->Handles->Handles[i];
if (handleInfo->UniqueProcessId != (ULONG_PTR)processId)
continue;
if (handleInfo->ObjectTypeIndex >= MAX_OBJECT_TYPE_NUMBER)
continue;
entry = &context->Entries[handleInfo->ObjectTypeIndex];
if (!entry->Name)
{
typeName = NULL;
PhGetHandleInformation(
context->ProcessHandle,
(HANDLE)handleInfo->HandleValue,
handleInfo->ObjectTypeIndex,
NULL,
&typeName,
NULL,
NULL
);
entry->Name = typeName;
}
entry->Count++;
}
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
lvHandle = GetDlgItem(hwndDlg, IDC_LIST);
PhSetListViewStyle(lvHandle, FALSE, TRUE);
PhSetControlTheme(lvHandle, L"explorer");
PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 140, L"Type");
PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 100, L"Count");
PhSetExtendedListView(lvHandle);
ExtendedListView_SetCompareFunction(lvHandle, 1, PhpTypeCountCompareFunction);
for (i = 0; i < MAX_OBJECT_TYPE_NUMBER; i++)
{
PHANDLE_STATISTICS_ENTRY entry;
PPH_STRING unknownType;
PPH_STRING countString;
INT lvItemIndex;
entry = &context->Entries[i];
if (entry->Count == 0)
continue;
unknownType = NULL;
if (!entry->Name)
unknownType = PhFormatString(L"(unknown: %u)", i);
countString = PhFormatUInt64(entry->Count, TRUE);
lvItemIndex = PhAddListViewItem(
lvHandle,
MAXINT,
entry->Name ? entry->Name->Buffer : unknownType->Buffer,
entry
);
PhSetListViewSubItem(lvHandle, lvItemIndex, 1, countString->Buffer);
PhDereferenceObject(countString);
if (unknownType)
PhDereferenceObject(unknownType);
}
ExtendedListView_SortItems(lvHandle);
}
break;
case WM_DESTROY:
{
// Nothing
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
EndDialog(hwndDlg, IDOK);
break;
}
}
break;
case WM_NOTIFY:
{
PhHandleListViewNotifyForCopy(lParam, GetDlgItem(hwndDlg, IDC_LIST));
}
break;
}
return FALSE;
}

View File

@ -0,0 +1,368 @@
#ifndef PH_ACTIONS_H
#define PH_ACTIONS_H
typedef enum _PH_ACTION_ELEVATION_LEVEL
{
NeverElevateAction = 0,
PromptElevateAction = 1,
AlwaysElevateAction = 2
} PH_ACTION_ELEVATION_LEVEL;
// begin_phapppub
typedef enum _PH_PHSVC_MODE
{
ElevatedPhSvcMode,
Wow64PhSvcMode
} PH_PHSVC_MODE;
PHAPPAPI
BOOLEAN
NTAPI
PhUiConnectToPhSvc(
_In_opt_ HWND hWnd,
_In_ BOOLEAN ConnectOnly
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiConnectToPhSvcEx(
_In_opt_ HWND hWnd,
_In_ PH_PHSVC_MODE Mode,
_In_ BOOLEAN ConnectOnly
);
PHAPPAPI
VOID
NTAPI
PhUiDisconnectFromPhSvc(
VOID
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiLockComputer(
_In_ HWND hWnd
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiLogoffComputer(
_In_ HWND hWnd
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSleepComputer(
_In_ HWND hWnd
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiHibernateComputer(
_In_ HWND hWnd
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiRestartComputer(
_In_ HWND hWnd,
_In_ ULONG Flags
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiShutdownComputer(
_In_ HWND hWnd,
_In_ ULONG Flags
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiConnectSession(
_In_ HWND hWnd,
_In_ ULONG SessionId
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiDisconnectSession(
_In_ HWND hWnd,
_In_ ULONG SessionId
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiLogoffSession(
_In_ HWND hWnd,
_In_ ULONG SessionId
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiTerminateProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiTerminateTreeProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSuspendProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiResumeProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiRestartProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiDebugProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiReduceWorkingSetProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetVirtualizationProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process,
_In_ BOOLEAN Enable
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiDetachFromDebuggerProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiInjectDllProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetIoPriorityProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses,
_In_ IO_PRIORITY_HINT IoPriority
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetPagePriorityProcess(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM Process,
_In_ ULONG PagePriority
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetPriorityProcesses(
_In_ HWND hWnd,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses,
_In_ ULONG PriorityClass
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiStartService(
_In_ HWND hWnd,
_In_ PPH_SERVICE_ITEM Service
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiContinueService(
_In_ HWND hWnd,
_In_ PPH_SERVICE_ITEM Service
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiPauseService(
_In_ HWND hWnd,
_In_ PPH_SERVICE_ITEM Service
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiStopService(
_In_ HWND hWnd,
_In_ PPH_SERVICE_ITEM Service
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiDeleteService(
_In_ HWND hWnd,
_In_ PPH_SERVICE_ITEM Service
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiCloseConnections(
_In_ HWND hWnd,
_In_ PPH_NETWORK_ITEM *Connections,
_In_ ULONG NumberOfConnections
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiTerminateThreads(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM *Threads,
_In_ ULONG NumberOfThreads
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSuspendThreads(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM *Threads,
_In_ ULONG NumberOfThreads
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiResumeThreads(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM *Threads,
_In_ ULONG NumberOfThreads
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetPriorityThread(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM Thread,
_In_ LONG Increment
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetIoPriorityThread(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM Thread,
_In_ IO_PRIORITY_HINT IoPriority
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetPagePriorityThread(
_In_ HWND hWnd,
_In_ PPH_THREAD_ITEM Thread,
_In_ ULONG PagePriority
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiUnloadModule(
_In_ HWND hWnd,
_In_ HANDLE ProcessId,
_In_ PPH_MODULE_ITEM Module
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiFreeMemory(
_In_ HWND hWnd,
_In_ HANDLE ProcessId,
_In_ PPH_MEMORY_ITEM MemoryItem,
_In_ BOOLEAN Free
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiCloseHandles(
_In_ HWND hWnd,
_In_ HANDLE ProcessId,
_In_ PPH_HANDLE_ITEM *Handles,
_In_ ULONG NumberOfHandles,
_In_ BOOLEAN Warn
);
PHAPPAPI
BOOLEAN
NTAPI
PhUiSetAttributesHandle(
_In_ HWND hWnd,
_In_ HANDLE ProcessId,
_In_ PPH_HANDLE_ITEM Handle,
_In_ ULONG Attributes
);
// end_phapppub
#endif

View File

@ -0,0 +1,118 @@
#ifndef PH_COLMGR_H
#define PH_COLMGR_H
#define PH_CM_ORDER_LIMIT 160
// begin_phapppub
typedef LONG (NTAPI *PPH_CM_POST_SORT_FUNCTION)(
_In_ LONG Result,
_In_ PVOID Node1,
_In_ PVOID Node2,
_In_ PH_SORT_ORDER SortOrder
);
// end_phapppub
typedef struct _PH_CM_MANAGER
{
HWND Handle;
ULONG MinId;
ULONG NextId;
PPH_CM_POST_SORT_FUNCTION PostSortFunction;
LIST_ENTRY ColumnListHead;
PPH_LIST NotifyList;
} PH_CM_MANAGER, *PPH_CM_MANAGER;
typedef struct _PH_CM_COLUMN
{
LIST_ENTRY ListEntry;
ULONG Id;
struct _PH_PLUGIN *Plugin;
ULONG SubId;
PVOID Context;
PVOID SortFunction;
} PH_CM_COLUMN, *PPH_CM_COLUMN;
VOID PhCmInitializeManager(
_Out_ PPH_CM_MANAGER Manager,
_In_ HWND Handle,
_In_ ULONG MinId,
_In_ PPH_CM_POST_SORT_FUNCTION PostSortFunction
);
VOID PhCmDeleteManager(
_In_ PPH_CM_MANAGER Manager
);
PPH_CM_COLUMN PhCmCreateColumn(
_Inout_ PPH_CM_MANAGER Manager,
_In_ PPH_TREENEW_COLUMN Column,
_In_ struct _PH_PLUGIN *Plugin,
_In_ ULONG SubId,
_In_opt_ PVOID Context,
_In_ PVOID SortFunction
);
PPH_CM_COLUMN PhCmFindColumn(
_In_ PPH_CM_MANAGER Manager,
_In_ PPH_STRINGREF PluginName,
_In_ ULONG SubId
);
VOID PhCmSetNotifyPlugin(
_In_ PPH_CM_MANAGER Manager,
_In_ struct _PH_PLUGIN *Plugin
);
BOOLEAN PhCmForwardMessage(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2,
_In_ PPH_CM_MANAGER Manager
);
BOOLEAN PhCmForwardSort(
_In_ PPH_TREENEW_NODE *Nodes,
_In_ ULONG NumberOfNodes,
_In_ ULONG SortColumn,
_In_ PH_SORT_ORDER SortOrder,
_In_ PPH_CM_MANAGER Manager
);
// begin_phapppub
PHAPPAPI
BOOLEAN
NTAPI
PhCmLoadSettings(
_In_ HWND TreeNewHandle,
_In_ PPH_STRINGREF Settings
);
// end_phapppub
#define PH_CM_COLUMN_WIDTHS_ONLY 0x1
BOOLEAN PhCmLoadSettingsEx(
_In_ HWND TreeNewHandle,
_In_opt_ PPH_CM_MANAGER Manager,
_In_ ULONG Flags,
_In_ PPH_STRINGREF Settings,
_In_opt_ PPH_STRINGREF SortSettings
);
// begin_phapppub
PHAPPAPI
PPH_STRING
NTAPI
PhCmSaveSettings(
_In_ HWND TreeNewHandle
);
// end_phapppub
PPH_STRING PhCmSaveSettingsEx(
_In_ HWND TreeNewHandle,
_In_opt_ PPH_CM_MANAGER Manager,
_In_ ULONG Flags,
_Out_opt_ PPH_STRING *SortSettings
);
#endif

View File

@ -0,0 +1,51 @@
#ifndef PH_EXTMGR_H
#define PH_EXTMGR_H
// begin_phapppub
typedef enum _PH_EM_OBJECT_TYPE
{
EmProcessItemType,
EmProcessNodeType,
EmServiceItemType,
EmServiceNodeType,
EmNetworkItemType,
EmNetworkNodeType,
EmThreadItemType,
EmThreadNodeType,
EmModuleItemType,
EmModuleNodeType,
EmHandleItemType,
EmHandleNodeType,
EmThreadsContextType,
EmModulesContextType,
EmHandlesContextType,
EmThreadProviderType,
EmModuleProviderType,
EmHandleProviderType,
EmMemoryNodeType,
EmMemoryContextType,
EmMaximumObjectType
} PH_EM_OBJECT_TYPE;
typedef enum _PH_EM_OBJECT_OPERATION
{
EmObjectCreate,
EmObjectDelete,
EmMaximumObjectOperation
} PH_EM_OBJECT_OPERATION;
typedef VOID (NTAPI *PPH_EM_OBJECT_CALLBACK)(
_In_ PVOID Object,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Extension
);
// end_phapppub
typedef struct _PH_EM_APP_CONTEXT
{
LIST_ENTRY ListEntry;
PH_STRINGREF AppName;
struct _PH_EM_OBJECT_EXTENSION *Extensions[EmMaximumObjectType];
} PH_EM_APP_CONTEXT, *PPH_EM_APP_CONTEXT;
#endif

View File

@ -0,0 +1,61 @@
#ifndef PH_EXTMGRI_H
#define PH_EXTMGRI_H
#include <extmgr.h>
typedef struct _PH_EM_OBJECT_TYPE_STATE
{
SIZE_T InitialSize;
SIZE_T ExtensionOffset;
LIST_ENTRY ExtensionListHead;
} PH_EM_OBJECT_TYPE_STATE, *PPH_EM_OBJECT_TYPE_STATE;
typedef struct _PH_EM_OBJECT_EXTENSION
{
LIST_ENTRY ListEntry;
SIZE_T ExtensionSize;
SIZE_T ExtensionOffset;
PPH_EM_OBJECT_CALLBACK Callbacks[EmMaximumObjectOperation];
} PH_EM_OBJECT_EXTENSION, *PPH_EM_OBJECT_EXTENSION;
VOID PhEmInitialization(
VOID
);
VOID PhEmInitializeAppContext(
_Out_ PPH_EM_APP_CONTEXT AppContext,
_In_ PPH_STRINGREF AppName
);
VOID PhEmSetObjectExtension(
_Inout_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T ExtensionSize,
_In_opt_ PPH_EM_OBJECT_CALLBACK CreateCallback,
_In_opt_ PPH_EM_OBJECT_CALLBACK DeleteCallback
);
PVOID PhEmGetObjectExtension(
_In_ PPH_EM_APP_CONTEXT AppContext,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object
);
SIZE_T PhEmGetObjectSize(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ SIZE_T InitialSize
);
VOID PhEmCallObjectOperation(
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ PVOID Object,
_In_ PH_EM_OBJECT_OPERATION Operation
);
BOOLEAN PhEmParseCompoundId(
_In_ PPH_STRINGREF CompoundId,
_Out_ PPH_STRINGREF AppName,
_Out_ PULONG SubId
);
#endif

View File

@ -0,0 +1,69 @@
#ifndef PH_HEAPSTRUCT_H
#define PH_HEAPSTRUCT_H
// Not the actual structure, but has the same size.
typedef struct _HEAP_ENTRY
{
PVOID Data1;
PVOID Data2;
} HEAP_ENTRY, *PHEAP_ENTRY;
#define HEAP_SEGMENT_SIGNATURE 0xffeeffee
// First few fields of HEAP_SEGMENT, VISTA and above
typedef struct _HEAP_SEGMENT
{
HEAP_ENTRY HeapEntry;
ULONG SegmentSignature;
ULONG SegmentFlags;
LIST_ENTRY SegmentListEntry;
struct _HEAP *Heap;
// ...
} HEAP_SEGMENT, *PHEAP_SEGMENT;
// First few fields of HEAP_SEGMENT, WS03 and below
typedef struct _HEAP_SEGMENT_OLD
{
HEAP_ENTRY Entry;
ULONG Signature;
ULONG Flags;
struct _HEAP *Heap;
// ...
} HEAP_SEGMENT_OLD, *PHEAP_SEGMENT_OLD;
// 32-bit versions
typedef struct _HEAP_ENTRY32
{
WOW64_POINTER(PVOID) Data1;
WOW64_POINTER(PVOID) Data2;
} HEAP_ENTRY32, *PHEAP_ENTRY32;
typedef struct _HEAP_SEGMENT32
{
HEAP_ENTRY32 HeapEntry;
ULONG SegmentSignature;
ULONG SegmentFlags;
LIST_ENTRY32 SegmentListEntry;
WOW64_POINTER(struct _HEAP *) Heap;
// ...
} HEAP_SEGMENT32, *PHEAP_SEGMENT32;
typedef struct _HEAP_SEGMENT_OLD32
{
HEAP_ENTRY32 Entry;
ULONG Signature;
ULONG Flags;
WOW64_POINTER(struct _HEAP *) Heap;
// ...
} HEAP_SEGMENT_OLD32, *PHEAP_SEGMENT_OLD32;
#define HEAP_SEGMENT_MAX_SIZE \
(max(sizeof(HEAP_SEGMENT), max(sizeof(HEAP_SEGMENT_OLD), \
max(sizeof(HEAP_SEGMENT32), sizeof(HEAP_SEGMENT_OLD32)))))
#endif

View File

@ -0,0 +1,75 @@
#ifndef PH_HIDNPROC_H
#define PH_HIDNPROC_H
typedef enum _PH_HIDDEN_PROCESS_METHOD
{
BruteForceScanMethod,
CsrHandlesScanMethod
} PH_HIDDEN_PROCESS_METHOD;
typedef enum _PH_HIDDEN_PROCESS_TYPE
{
UnknownProcess,
NormalProcess,
HiddenProcess,
TerminatedProcess
} PH_HIDDEN_PROCESS_TYPE;
typedef struct _PH_HIDDEN_PROCESS_ENTRY
{
HANDLE ProcessId;
PPH_STRING FileName;
PH_HIDDEN_PROCESS_TYPE Type;
} PH_HIDDEN_PROCESS_ENTRY, *PPH_HIDDEN_PROCESS_ENTRY;
typedef struct _PH_CSR_HANDLE_INFO
{
HANDLE CsrProcessHandle;
HANDLE Handle;
BOOLEAN IsThreadHandle;
HANDLE ProcessId;
} PH_CSR_HANDLE_INFO, *PPH_CSR_HANDLE_INFO;
typedef BOOLEAN (NTAPI *PPH_ENUM_HIDDEN_PROCESSES_CALLBACK)(
_In_ PPH_HIDDEN_PROCESS_ENTRY Process,
_In_opt_ PVOID Context
);
NTSTATUS
NTAPI
PhEnumHiddenProcesses(
_In_ PH_HIDDEN_PROCESS_METHOD Method,
_In_ PPH_ENUM_HIDDEN_PROCESSES_CALLBACK Callback,
_In_opt_ PVOID Context
);
typedef BOOLEAN (NTAPI *PPH_ENUM_CSR_PROCESS_HANDLES_CALLBACK)(
_In_ PPH_CSR_HANDLE_INFO Handle,
_In_opt_ PVOID Context
);
NTSTATUS
NTAPI
PhEnumCsrProcessHandles(
_In_ PPH_ENUM_CSR_PROCESS_HANDLES_CALLBACK Callback,
_In_opt_ PVOID Context
);
NTSTATUS
NTAPI
PhOpenProcessByCsrHandle(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ PPH_CSR_HANDLE_INFO Handle
);
NTSTATUS
NTAPI
PhOpenProcessByCsrHandles(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ HANDLE ProcessId
);
#endif

View File

@ -0,0 +1,119 @@
#ifndef PH_HNDLLIST_H
#define PH_HNDLLIST_H
#include <phuisup.h>
#include <colmgr.h>
// Columns
#define PHHNTLC_TYPE 0
#define PHHNTLC_NAME 1
#define PHHNTLC_HANDLE 2
#define PHHNTLC_OBJECTADDRESS 3
#define PHHNTLC_ATTRIBUTES 4
#define PHHNTLC_GRANTEDACCESS 5
#define PHHNTLC_GRANTEDACCESSSYMBOLIC 6
#define PHHNTLC_ORIGINALNAME 7
#define PHHNTLC_FILESHAREACCESS 8
#define PHHNTLC_MAXIMUM 9
// begin_phapppub
typedef struct _PH_HANDLE_NODE
{
PH_TREENEW_NODE Node;
PH_SH_STATE ShState;
HANDLE Handle;
PPH_HANDLE_ITEM HandleItem;
// end_phapppub
PH_STRINGREF TextCache[PHHNTLC_MAXIMUM];
PPH_STRING GrantedAccessSymbolicText;
WCHAR FileShareAccessText[4];
// begin_phapppub
} PH_HANDLE_NODE, *PPH_HANDLE_NODE;
// end_phapppub
typedef struct _PH_HANDLE_LIST_CONTEXT
{
HWND ParentWindowHandle;
HWND TreeNewHandle;
ULONG TreeNewSortColumn;
PH_SORT_ORDER TreeNewSortOrder;
PH_CM_MANAGER Cm;
BOOLEAN HideUnnamedHandles;
PPH_HASHTABLE NodeHashtable;
PPH_LIST NodeList;
BOOLEAN EnableStateHighlighting;
PPH_POINTER_LIST NodeStateList;
} PH_HANDLE_LIST_CONTEXT, *PPH_HANDLE_LIST_CONTEXT;
VOID PhInitializeHandleList(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
_Out_ PPH_HANDLE_LIST_CONTEXT Context
);
VOID PhDeleteHandleList(
_In_ PPH_HANDLE_LIST_CONTEXT Context
);
VOID PhLoadSettingsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context
);
VOID PhSaveSettingsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context
);
VOID PhSetOptionsHandleList(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ BOOLEAN HideUnnamedHandles
);
PPH_HANDLE_NODE PhAddHandleNode(
_Inout_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_ITEM HandleItem,
_In_ ULONG RunId
);
PPH_HANDLE_NODE PhFindHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ HANDLE Handle
);
VOID PhRemoveHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_NODE HandleNode
);
VOID PhUpdateHandleNode(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_In_ PPH_HANDLE_NODE HandleNode
);
VOID PhTickHandleNodes(
_In_ PPH_HANDLE_LIST_CONTEXT Context
);
PPH_HANDLE_ITEM PhGetSelectedHandleItem(
_In_ PPH_HANDLE_LIST_CONTEXT Context
);
VOID PhGetSelectedHandleItems(
_In_ PPH_HANDLE_LIST_CONTEXT Context,
_Out_ PPH_HANDLE_ITEM **Handles,
_Out_ PULONG NumberOfHandles
);
VOID PhDeselectAllHandleNodes(
_In_ PPH_HANDLE_LIST_CONTEXT Context
);
#endif

View File

@ -0,0 +1,33 @@
#ifndef PH_HNDLMENU_H
#define PH_HNDLMENU_H
typedef struct _PH_HANDLE_ITEM_INFO
{
HANDLE ProcessId;
HANDLE Handle;
PPH_STRING TypeName;
PPH_STRING BestObjectName;
} PH_HANDLE_ITEM_INFO, *PPH_HANDLE_ITEM_INFO;
#define PhaAppendCtrlEnter(Text, Enable) ((Enable) ? PhaConcatStrings2((Text), L"\tCtrl+Enter")->Buffer : (Text))
VOID PhInsertHandleObjectPropertiesEMenuItems(
_In_ struct _PH_EMENU_ITEM *Menu,
_In_ ULONG InsertBeforeId,
_In_ BOOLEAN EnableShortcut,
_In_ PPH_HANDLE_ITEM_INFO Info
);
#define PH_MAX_SECTION_EDIT_SIZE (32 * 1024 * 1024) // 32 MB
VOID PhShowHandleObjectProperties1(
_In_ HWND hWnd,
_In_ PPH_HANDLE_ITEM_INFO Info
);
VOID PhShowHandleObjectProperties2(
_In_ HWND hWnd,
_In_ PPH_HANDLE_ITEM_INFO Info
);
#endif

View File

@ -0,0 +1,84 @@
#ifndef PH_HNDLPRV_H
#define PH_HNDLPRV_H
extern PPH_OBJECT_TYPE PhHandleProviderType;
extern PPH_OBJECT_TYPE PhHandleItemType;
// begin_phapppub
#define PH_HANDLE_FILE_SHARED_READ 0x1
#define PH_HANDLE_FILE_SHARED_WRITE 0x2
#define PH_HANDLE_FILE_SHARED_DELETE 0x4
#define PH_HANDLE_FILE_SHARED_MASK 0x7
typedef struct _PH_HANDLE_ITEM
{
PH_HASH_ENTRY HashEntry;
HANDLE Handle;
PVOID Object;
ULONG Attributes;
ACCESS_MASK GrantedAccess;
ULONG FileFlags;
PPH_STRING TypeName;
PPH_STRING ObjectName;
PPH_STRING BestObjectName;
WCHAR HandleString[PH_PTR_STR_LEN_1];
WCHAR ObjectString[PH_PTR_STR_LEN_1];
WCHAR GrantedAccessString[PH_PTR_STR_LEN_1];
} PH_HANDLE_ITEM, *PPH_HANDLE_ITEM;
typedef struct _PH_HANDLE_PROVIDER
{
PPH_HASH_ENTRY *HandleHashSet;
ULONG HandleHashSetSize;
ULONG HandleHashSetCount;
PH_QUEUED_LOCK HandleHashSetLock;
PH_CALLBACK HandleAddedEvent;
PH_CALLBACK HandleModifiedEvent;
PH_CALLBACK HandleRemovedEvent;
PH_CALLBACK UpdatedEvent;
HANDLE ProcessId;
HANDLE ProcessHandle;
PPH_HASHTABLE TempListHashtable;
NTSTATUS RunStatus;
} PH_HANDLE_PROVIDER, *PPH_HANDLE_PROVIDER;
// end_phapppub
BOOLEAN PhHandleProviderInitialization(
VOID
);
PPH_HANDLE_PROVIDER PhCreateHandleProvider(
_In_ HANDLE ProcessId
);
PPH_HANDLE_ITEM PhCreateHandleItem(
_In_opt_ PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle
);
PPH_HANDLE_ITEM PhReferenceHandleItem(
_In_ PPH_HANDLE_PROVIDER HandleProvider,
_In_ HANDLE Handle
);
VOID PhDereferenceAllHandleItems(
_In_ PPH_HANDLE_PROVIDER HandleProvider
);
NTSTATUS PhEnumHandlesGeneric(
_In_ HANDLE ProcessId,
_In_ HANDLE ProcessHandle,
_Out_ PSYSTEM_HANDLE_INFORMATION_EX *Handles,
_Out_ PBOOLEAN FilterNeeded
);
VOID PhHandleProviderUpdate(
_In_ PVOID Object
);
#endif

View File

@ -0,0 +1,450 @@
#ifndef PH_MAINWNDP_H
#define PH_MAINWNDP_H
#define PH_FLUSH_PROCESS_QUERY_DATA_INTERVAL_1 250
#define PH_FLUSH_PROCESS_QUERY_DATA_INTERVAL_2 750
#define PH_FLUSH_PROCESS_QUERY_DATA_INTERVAL_LONG_TERM 1000
#define TIMER_FLUSH_PROCESS_QUERY_DATA 1
#define TIMER_ICON_CLICK_ACTIVATE 2
#define TIMER_ICON_RESTORE_HOVER 3
LRESULT CALLBACK PhMwpWndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// Initialization
BOOLEAN PhMwpInitializeWindowClass(
VOID
);
VOID PhMwpInitializeProviders(
VOID
);
VOID PhMwpApplyUpdateInterval(
_In_ ULONG Interval
);
VOID PhMwpInitializeControls(
VOID
);
NTSTATUS PhMwpDelayedLoadFunction(
_In_ PVOID Parameter
);
PPH_STRING PhMwpFindDbghelpPath(
VOID
);
// Event handlers
VOID PhMwpOnDestroy(
VOID
);
VOID PhMwpOnEndSession(
VOID
);
VOID PhMwpOnSettingChange(
VOID
);
VOID PhMwpOnCommand(
_In_ ULONG Id
);
VOID PhMwpOnShowWindow(
_In_ BOOLEAN Showing,
_In_ ULONG State
);
BOOLEAN PhMwpOnSysCommand(
_In_ ULONG Type,
_In_ LONG CursorScreenX,
_In_ LONG CursorScreenY
);
VOID PhMwpOnMenuCommand(
_In_ ULONG Index,
_In_ HMENU Menu
);
VOID PhMwpOnInitMenuPopup(
_In_ HMENU Menu,
_In_ ULONG Index,
_In_ BOOLEAN IsWindowMenu
);
VOID PhMwpOnSize(
VOID
);
VOID PhMwpOnSizing(
_In_ ULONG Edge,
_In_ PRECT DragRectangle
);
VOID PhMwpOnSetFocus(
VOID
);
VOID PhMwpOnTimer(
_In_ ULONG Id
);
BOOLEAN PhMwpOnNotify(
_In_ NMHDR *Header,
_Out_ LRESULT *Result
);
VOID PhMwpOnWtsSessionChange(
_In_ ULONG Reason,
_In_ ULONG SessionId
);
ULONG_PTR PhMwpOnUserMessage(
_In_ ULONG Message,
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam
);
// Callbacks
VOID NTAPI PhMwpProcessAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpProcessModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpProcessRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpProcessesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpServiceAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpServiceModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpServiceRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpServicesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpNetworkItemAddedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpNetworkItemModifiedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpNetworkItemRemovedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID NTAPI PhMwpNetworkItemsUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
// Settings
VOID PhMwpLoadSettings(
VOID
);
VOID PhMwpSaveSettings(
VOID
);
VOID PhMwpSaveWindowState(
VOID
);
// Misc.
VOID PhMwpSymInitHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID PhMwpUpdateLayoutPadding(
VOID
);
VOID PhMwpApplyLayoutPadding(
_Inout_ PRECT Rect,
_In_ PRECT Padding
);
VOID PhMwpLayout(
_Inout_ HDWP *DeferHandle
);
VOID PhMwpSetCheckOpacityMenu(
_In_ BOOLEAN AssumeAllUnchecked,
_In_ ULONG Opacity
);
VOID PhMwpSetupComputerMenu(
_In_ PPH_EMENU_ITEM Root
);
BOOLEAN PhMwpExecuteComputerCommand(
_In_ ULONG Id
);
VOID PhMwpActivateWindow(
_In_ BOOLEAN Toggle
);
// Main menu
VOID PhMwpInitializeMainMenu(
_In_ HMENU Menu
);
VOID PhMwpDispatchMenuCommand(
_In_ HMENU MenuHandle,
_In_ ULONG ItemIndex,
_In_ ULONG ItemId,
_In_ ULONG_PTR ItemData
);
ULONG_PTR PhMwpLegacyAddPluginMenuItem(
_In_ PPH_ADDMENUITEM AddMenuItem
);
HBITMAP PhMwpGetShieldBitmap(
VOID
);
VOID PhMwpInitializeSubMenu(
_In_ PPH_EMENU Menu,
_In_ ULONG Index
);
PPH_EMENU_ITEM PhMwpFindTrayIconsMenuItem(
_In_ PPH_EMENU Menu
);
VOID PhMwpInitializeSectionMenuItems(
_In_ PPH_EMENU Menu,
_In_ ULONG StartIndex
);
// Tab control
VOID PhMwpLayoutTabControl(
_Inout_ HDWP *DeferHandle
);
VOID PhMwpNotifyTabControl(
_In_ NMHDR *Header
);
VOID PhMwpSelectionChangedTabControl(
_In_ ULONG OldIndex
);
PPH_ADDITIONAL_TAB_PAGE PhMwpAddTabPage(
_In_ PPH_ADDITIONAL_TAB_PAGE TabPage
);
VOID PhMwpSelectTabPage(
_In_ ULONG Index
);
INT PhMwpFindTabPageIndex(
_In_ PWSTR Text
);
// Notifications
VOID PhMwpAddIconProcesses(
_In_ PPH_EMENU_ITEM Menu,
_In_ ULONG NumberOfProcesses
);
VOID PhMwpShowIconContextMenu(
_In_ POINT Location
);
VOID PhMwpClearLastNotificationDetails(
VOID
);
BOOLEAN PhMwpPluginNotifyEvent(
_In_ ULONG Type,
_In_ PVOID Parameter
);
// Processes
VOID PhMwpShowProcessProperties(
_In_ PPH_PROCESS_ITEM ProcessItem
);
BOOLEAN PhMwpCurrentUserProcessTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
);
BOOLEAN PhMwpSignedProcessTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
);
BOOLEAN PhMwpExecuteProcessPriorityCommand(
_In_ ULONG Id,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
BOOLEAN PhMwpExecuteProcessIoPriorityCommand(
_In_ ULONG Id,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
VOID PhMwpSetProcessMenuPriorityChecks(
_In_ PPH_EMENU Menu,
_In_ HANDLE ProcessId,
_In_ BOOLEAN SetPriority,
_In_ BOOLEAN SetIoPriority,
_In_ BOOLEAN SetPagePriority
);
VOID PhMwpInitializeProcessMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_PROCESS_ITEM *Processes,
_In_ ULONG NumberOfProcesses
);
VOID PhMwpOnProcessAdded(
_In_ _Assume_refs_(1) PPH_PROCESS_ITEM ProcessItem,
_In_ ULONG RunId
);
VOID PhMwpOnProcessModified(
_In_ PPH_PROCESS_ITEM ProcessItem
);
VOID PhMwpOnProcessRemoved(
_In_ PPH_PROCESS_ITEM ProcessItem
);
VOID PhMwpOnProcessesUpdated(
VOID
);
// Services
VOID PhMwpNeedServiceTreeList(
VOID
);
BOOLEAN PhMwpDriverServiceTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
);
VOID PhMwpInitializeServiceMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_SERVICE_ITEM *Services,
_In_ ULONG NumberOfServices
);
VOID PhMwpOnServiceAdded(
_In_ _Assume_refs_(1) PPH_SERVICE_ITEM ServiceItem,
_In_ ULONG RunId
);
VOID PhMwpOnServiceModified(
_In_ struct _PH_SERVICE_MODIFIED_DATA *ServiceModifiedData
);
VOID PhMwpOnServiceRemoved(
_In_ PPH_SERVICE_ITEM ServiceItem
);
VOID PhMwpOnServicesUpdated(
VOID
);
// Network
VOID PhMwpNeedNetworkTreeList(
VOID
);
BOOLEAN PhMwpCurrentUserNetworkTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
);
BOOLEAN PhMwpSignedNetworkTreeFilter(
_In_ PPH_TREENEW_NODE Node,
_In_opt_ PVOID Context
);
VOID PhMwpInitializeNetworkMenu(
_In_ PPH_EMENU Menu,
_In_ PPH_NETWORK_ITEM *NetworkItems,
_In_ ULONG NumberOfNetworkItems
);
VOID PhMwpOnNetworkItemAdded(
_In_ ULONG RunId,
_In_ _Assume_refs_(1) PPH_NETWORK_ITEM NetworkItem
);
VOID PhMwpOnNetworkItemModified(
_In_ PPH_NETWORK_ITEM NetworkItem
);
VOID PhMwpOnNetworkItemRemoved(
_In_ PPH_NETWORK_ITEM NetworkItem
);
VOID PhMwpOnNetworkItemsUpdated(
VOID
);
// Users
VOID PhMwpUpdateUsersMenu(
VOID
);
#endif

View File

@ -0,0 +1,116 @@
#ifndef PH_MEMLIST_H
#define PH_MEMLIST_H
#include <phuisup.h>
#include <colmgr.h>
// Columns
#define PHMMTLC_BASEADDRESS 0
#define PHMMTLC_TYPE 1
#define PHMMTLC_SIZE 2
#define PHMMTLC_PROTECTION 3
#define PHMMTLC_USE 4
#define PHMMTLC_TOTALWS 5
#define PHMMTLC_PRIVATEWS 6
#define PHMMTLC_SHAREABLEWS 7
#define PHMMTLC_SHAREDWS 8
#define PHMMTLC_LOCKEDWS 9
#define PHMMTLC_COMMITTED 10
#define PHMMTLC_PRIVATE 11
#define PHMMTLC_MAXIMUM 12
// begin_phapppub
typedef struct _PH_MEMORY_NODE
{
PH_TREENEW_NODE Node;
BOOLEAN IsAllocationBase;
BOOLEAN Reserved1;
USHORT Reserved2;
PPH_MEMORY_ITEM MemoryItem;
struct _PH_MEMORY_NODE *Parent;
PPH_LIST Children;
// end_phapppub
PH_STRINGREF TextCache[PHMMTLC_MAXIMUM];
WCHAR BaseAddressText[PH_PTR_STR_LEN_1];
WCHAR TypeText[30];
PPH_STRING SizeText;
WCHAR ProtectionText[17];
PPH_STRING UseText;
PPH_STRING TotalWsText;
PPH_STRING PrivateWsText;
PPH_STRING ShareableWsText;
PPH_STRING SharedWsText;
PPH_STRING LockedWsText;
PPH_STRING CommittedText;
PPH_STRING PrivateText;
// begin_phapppub
} PH_MEMORY_NODE, *PPH_MEMORY_NODE;
// end_phapppub
typedef struct _PH_MEMORY_LIST_CONTEXT
{
HWND ParentWindowHandle;
HWND TreeNewHandle;
ULONG TreeNewSortColumn;
PH_SORT_ORDER TreeNewSortOrder;
PH_CM_MANAGER Cm;
BOOLEAN HideFreeRegions;
PPH_LIST AllocationBaseNodeList; // Allocation base nodes (list should always be sorted by base address)
PPH_LIST RegionNodeList; // Memory region nodes
} PH_MEMORY_LIST_CONTEXT, *PPH_MEMORY_LIST_CONTEXT;
VOID PhInitializeMemoryList(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
_Out_ PPH_MEMORY_LIST_CONTEXT Context
);
VOID PhDeleteMemoryList(
_In_ PPH_MEMORY_LIST_CONTEXT Context
);
VOID PhLoadSettingsMemoryList(
_Inout_ PPH_MEMORY_LIST_CONTEXT Context
);
VOID PhSaveSettingsMemoryList(
_Inout_ PPH_MEMORY_LIST_CONTEXT Context
);
VOID PhSetOptionsMemoryList(
_Inout_ PPH_MEMORY_LIST_CONTEXT Context,
_In_ BOOLEAN HideFreeRegions
);
VOID PhReplaceMemoryList(
_Inout_ PPH_MEMORY_LIST_CONTEXT Context,
_In_ PPH_MEMORY_ITEM_LIST List
);
VOID PhUpdateMemoryNode(
_In_ PPH_MEMORY_LIST_CONTEXT Context,
_In_ PPH_MEMORY_NODE MemoryNode
);
PPH_MEMORY_NODE PhGetSelectedMemoryNode(
_In_ PPH_MEMORY_LIST_CONTEXT Context
);
VOID PhGetSelectedMemoryNodes(
_In_ PPH_MEMORY_LIST_CONTEXT Context,
_Out_ PPH_MEMORY_NODE **MemoryNodes,
_Out_ PULONG NumberOfMemoryNodes
);
VOID PhDeselectAllMemoryNodes(
_In_ PPH_MEMORY_LIST_CONTEXT Context
);
#endif

View File

@ -0,0 +1,148 @@
#ifndef PH_MEMPRV_H
#define PH_MEMPRV_H
extern PPH_OBJECT_TYPE PhMemoryItemType;
// begin_phapppub
typedef enum _PH_MEMORY_REGION_TYPE
{
UnknownRegion,
CustomRegion,
UnusableRegion,
MappedFileRegion,
UserSharedDataRegion,
PebRegion,
Peb32Region,
TebRegion,
Teb32Region, // Not used
StackRegion,
Stack32Region,
HeapRegion,
Heap32Region,
HeapSegmentRegion,
HeapSegment32Region
} PH_MEMORY_REGION_TYPE;
typedef struct _PH_MEMORY_ITEM
{
LIST_ENTRY ListEntry;
PH_AVL_LINKS Links;
union
{
struct
{
PVOID BaseAddress;
PVOID AllocationBase;
ULONG AllocationProtect;
SIZE_T RegionSize;
ULONG State;
ULONG Protect;
ULONG Type;
};
MEMORY_BASIC_INFORMATION BasicInfo;
};
struct _PH_MEMORY_ITEM *AllocationBaseItem;
SIZE_T CommittedSize;
SIZE_T PrivateSize;
SIZE_T TotalWorkingSetPages;
SIZE_T PrivateWorkingSetPages;
SIZE_T SharedWorkingSetPages;
SIZE_T ShareableWorkingSetPages;
SIZE_T LockedWorkingSetPages;
PH_MEMORY_REGION_TYPE RegionType;
union
{
struct
{
PPH_STRING Text;
BOOLEAN PropertyOfAllocationBase;
} Custom;
struct
{
PPH_STRING FileName;
} MappedFile;
struct
{
HANDLE ThreadId;
} Teb;
struct
{
HANDLE ThreadId;
} Stack;
struct
{
ULONG Index;
} Heap;
struct
{
struct _PH_MEMORY_ITEM *HeapItem;
} HeapSegment;
} u;
} PH_MEMORY_ITEM, *PPH_MEMORY_ITEM;
typedef struct _PH_MEMORY_ITEM_LIST
{
HANDLE ProcessId;
PH_AVL_TREE Set;
LIST_ENTRY ListHead;
} PH_MEMORY_ITEM_LIST, *PPH_MEMORY_ITEM_LIST;
// end_phapppub
BOOLEAN PhMemoryProviderInitialization(
VOID
);
VOID PhGetMemoryProtectionString(
_In_ ULONG Protection,
_Out_writes_(17) PWSTR String
);
PWSTR PhGetMemoryStateString(
_In_ ULONG State
);
PWSTR PhGetMemoryTypeString(
_In_ ULONG Type
);
PPH_MEMORY_ITEM PhCreateMemoryItem(
VOID
);
// begin_phapppub
PHAPPAPI
VOID
NTAPI
PhDeleteMemoryItemList(
_In_ PPH_MEMORY_ITEM_LIST List
);
PHAPPAPI
PPH_MEMORY_ITEM
NTAPI
PhLookupMemoryItemList(
_In_ PPH_MEMORY_ITEM_LIST List,
_In_ PVOID Address
);
#define PH_QUERY_MEMORY_IGNORE_FREE 0x1
#define PH_QUERY_MEMORY_REGION_TYPE 0x2
#define PH_QUERY_MEMORY_WS_COUNTERS 0x4
PHAPPAPI
NTSTATUS
NTAPI
PhQueryMemoryItemList(
_In_ HANDLE ProcessId,
_In_ ULONG Flags,
_Out_ PPH_MEMORY_ITEM_LIST List
);
// end_phapppub
#endif

View File

@ -0,0 +1,61 @@
#ifndef PH_MEMSRCH_H
#define PH_MEMSRCH_H
typedef struct _PH_MEMORY_RESULT
{
LONG RefCount;
PVOID Address;
SIZE_T Length;
PH_STRINGREF Display;
} PH_MEMORY_RESULT, *PPH_MEMORY_RESULT;
typedef VOID (NTAPI *PPH_MEMORY_RESULT_CALLBACK)(
_In_ _Assume_refs_(1) PPH_MEMORY_RESULT Result,
_In_opt_ PVOID Context
);
#define PH_DISPLAY_BUFFER_COUNT (PAGE_SIZE * 2 - 1)
typedef struct _PH_MEMORY_SEARCH_OPTIONS
{
BOOLEAN Cancel;
PPH_MEMORY_RESULT_CALLBACK Callback;
PVOID Context;
} PH_MEMORY_SEARCH_OPTIONS, *PPH_MEMORY_SEARCH_OPTIONS;
typedef struct _PH_MEMORY_STRING_OPTIONS
{
PH_MEMORY_SEARCH_OPTIONS Header;
ULONG MinimumLength;
BOOLEAN DetectUnicode;
ULONG MemoryTypeMask;
} PH_MEMORY_STRING_OPTIONS, *PPH_MEMORY_STRING_OPTIONS;
PVOID PhAllocateForMemorySearch(
_In_ SIZE_T Size
);
VOID PhFreeForMemorySearch(
_In_ _Post_invalid_ PVOID Memory
);
PVOID PhCreateMemoryResult(
_In_ PVOID Address,
_In_ SIZE_T Length
);
VOID PhReferenceMemoryResult(
_In_ PPH_MEMORY_RESULT Result
);
VOID PhDereferenceMemoryResult(
_In_ PPH_MEMORY_RESULT Result
);
VOID PhDereferenceMemoryResults(
_In_reads_(NumberOfResults) PPH_MEMORY_RESULT *Results,
_In_ ULONG NumberOfResults
);
#endif

View File

@ -0,0 +1,222 @@
#ifndef PH_MINIINFO_H
#define PH_MINIINFO_H
#include <procgrp.h>
// begin_phapppub
// Section
typedef VOID (NTAPI *PPH_MINIINFO_SET_SECTION_TEXT)(
_In_ struct _PH_MINIINFO_SECTION *Section,
_In_opt_ PPH_STRING Text
);
typedef struct _PH_MINIINFO_PARAMETERS
{
HWND ContainerWindowHandle;
HWND MiniInfoWindowHandle;
HFONT Font;
HFONT MediumFont;
ULONG FontHeight;
ULONG FontAverageWidth;
ULONG MediumFontHeight;
ULONG MediumFontAverageWidth;
PPH_MINIINFO_SET_SECTION_TEXT SetSectionText;
} PH_MINIINFO_PARAMETERS, *PPH_MINIINFO_PARAMETERS;
typedef enum _PH_MINIINFO_SECTION_MESSAGE
{
MiniInfoCreate,
MiniInfoDestroy,
MiniInfoTick,
MiniInfoSectionChanging, // PPH_MINIINFO_SECTION Parameter1
MiniInfoShowing, // BOOLEAN Parameter1 (Showing)
MiniInfoCreateDialog, // PPH_MINIINFO_CREATE_DIALOG Parameter1
MaxMiniInfoMessage
} PH_MINIINFO_SECTION_MESSAGE;
typedef BOOLEAN (NTAPI *PPH_MINIINFO_SECTION_CALLBACK)(
_In_ struct _PH_MINIINFO_SECTION *Section,
_In_ PH_MINIINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
typedef struct _PH_MINIINFO_CREATE_DIALOG
{
BOOLEAN CustomCreate;
// Parameters for default create
PVOID Instance;
PWSTR Template;
DLGPROC DialogProc;
PVOID Parameter;
} PH_MINIINFO_CREATE_DIALOG, *PPH_MINIINFO_CREATE_DIALOG;
#define PH_MINIINFO_SECTION_NO_UPPER_MARGINS 0x1
// end_phapppub
// begin_phapppub
typedef struct _PH_MINIINFO_SECTION
{
// Public
// Initialization
PH_STRINGREF Name;
ULONG Flags;
PPH_MINIINFO_SECTION_CALLBACK Callback;
PVOID Context;
PVOID Reserved1[3];
PPH_MINIINFO_PARAMETERS Parameters;
PVOID Reserved2[3];
// end_phapppub
// Private
struct
{
ULONG SpareFlags : 32;
};
HWND DialogHandle;
PPH_STRING Text;
// begin_phapppub
} PH_MINIINFO_SECTION, *PPH_MINIINFO_SECTION;
// end_phapppub
typedef enum _PH_MINIINFO_PIN_TYPE
{
MiniInfoManualPinType, // User pin
MiniInfoIconPinType, // Notification icon
MiniInfoActivePinType, // Window is active
MiniInfoHoverPinType, // Cursor is over mini info window
MiniInfoChildControlPinType, // Interacting with child control
MaxMiniInfoPinType
} PH_MINIINFO_PIN_TYPE;
#define PH_MINIINFO_ACTIVATE_WINDOW 0x1
#define PH_MINIINFO_LOAD_POSITION 0x2
#define PH_MINIINFO_DONT_CHANGE_SECTION_IF_PINNED 0x4
VOID PhPinMiniInformation(
_In_ PH_MINIINFO_PIN_TYPE PinType,
_In_ LONG PinCount,
_In_opt_ ULONG PinDelayMs,
_In_ ULONG Flags,
_In_opt_ PWSTR SectionName,
_In_opt_ PPOINT SourcePoint
);
// begin_phapppub
// List section
typedef enum _PH_MINIINFO_LIST_SECTION_MESSAGE
{
MiListSectionCreate,
MiListSectionDestroy,
MiListSectionTick,
MiListSectionShowing, // BOOLEAN Parameter1 (Showing)
MiListSectionDialogCreated, // HWND Parameter1
MiListSectionSortProcessList, // PPH_MINIINFO_LIST_SECTION_SORT_LIST Parameter1
MiListSectionAssignSortData, // PPH_MINIINFO_LIST_SECTION_ASSIGN_SORT_DATA Parameter1
MiListSectionSortGroupList, // PPH_MINIINFO_LIST_SECTION_SORT_LIST Parameter1
MiListSectionGetTitleText, // PPH_MINIINFO_LIST_SECTION_GET_TITLE_TEXT Parameter1
MiListSectionGetUsageText, // PPH_MINIINFO_LIST_SECTION_GET_USAGE_TEXT Parameter1
MiListSectionInitializeContextMenu, // PPH_MINIINFO_LIST_SECTION_MENU_INFORMATION Parameter1
MiListSectionHandleContextMenu, // PPH_MINIINFO_LIST_SECTION_MENU_INFORMATION Parameter1
MaxMiListSectionMessage
} PH_MINIINFO_LIST_SECTION_MESSAGE;
typedef BOOLEAN (NTAPI *PPH_MINIINFO_LIST_SECTION_CALLBACK)(
_In_ struct _PH_MINIINFO_LIST_SECTION *ListSection,
_In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
// The list section performs the following steps when constructing the list of process groups:
// 1. MiListSectionSortProcessList is sent in order to sort the process list.
// 2. A small number of process groups is created from the first few processes in the sorted list (typically high
// resource consumers).
// 3. MiListSectionAssignSortData is sent for each process group so that the user can assign custom sort data to
// each process group.
// 4. MiListSectionSortGroupList is sent in order to ensure that the process groups are correctly sorted by resource
// usage.
// The user also has access to the sort data when handling MiListSectionGetTitleText and MiListSectionGetUsageText.
typedef struct _PH_MINIINFO_LIST_SECTION_SORT_DATA
{
PH_TREENEW_NODE DoNotModify;
ULONGLONG UserData[4];
} PH_MINIINFO_LIST_SECTION_SORT_DATA, *PPH_MINIINFO_LIST_SECTION_SORT_DATA;
typedef struct _PH_MINIINFO_LIST_SECTION_ASSIGN_SORT_DATA
{
PPH_PROCESS_GROUP ProcessGroup;
PPH_MINIINFO_LIST_SECTION_SORT_DATA SortData;
} PH_MINIINFO_LIST_SECTION_ASSIGN_SORT_DATA, *PPH_MINIINFO_LIST_SECTION_ASSIGN_SORT_DATA;
typedef struct _PH_MINIINFO_LIST_SECTION_SORT_LIST
{
// MiListSectionSortProcessList: List of PPH_PROCESS_NODE
// MiListSectionSortGroupList: List of PPH_MINIINFO_LIST_SECTION_SORT_DATA
PPH_LIST List;
} PH_MINIINFO_LIST_SECTION_SORT_LIST, *PPH_MINIINFO_LIST_SECTION_SORT_LIST;
typedef struct _PH_MINIINFO_LIST_SECTION_GET_TITLE_TEXT
{
PPH_PROCESS_GROUP ProcessGroup;
PPH_MINIINFO_LIST_SECTION_SORT_DATA SortData;
PPH_STRING Title; // Top line (may already contain a string)
PPH_STRING Subtitle; // Bottom line (may already contain a string)
COLORREF TitleColor;
COLORREF SubtitleColor;
} PH_MINIINFO_LIST_SECTION_GET_TITLE_TEXT, *PPH_MINIINFO_LIST_SECTION_GET_TITLE_TEXT;
typedef struct _PH_MINIINFO_LIST_SECTION_GET_USAGE_TEXT
{
PPH_PROCESS_GROUP ProcessGroup;
PPH_MINIINFO_LIST_SECTION_SORT_DATA SortData;
PPH_STRING Line1; // Top line
PPH_STRING Line2; // Bottom line
COLORREF Line1Color;
COLORREF Line2Color;
} PH_MINIINFO_LIST_SECTION_GET_USAGE_TEXT, *PPH_MINIINFO_LIST_SECTION_GET_USAGE_TEXT;
typedef struct _PH_MINIINFO_LIST_SECTION_MENU_INFORMATION
{
PPH_PROCESS_GROUP ProcessGroup;
PPH_MINIINFO_LIST_SECTION_SORT_DATA SortData;
PPH_TREENEW_CONTEXT_MENU ContextMenu;
struct _PH_EMENU_ITEM *SelectedItem;
} PH_MINIINFO_LIST_SECTION_MENU_INFORMATION, *PPH_MINIINFO_LIST_SECTION_MENU_INFORMATION;
// end_phapppub
// begin_phapppub
typedef struct _PH_MINIINFO_LIST_SECTION
{
// Public
PPH_MINIINFO_SECTION Section; // State
HWND DialogHandle; // State
HWND TreeNewHandle; // State
PVOID Context; // Initialization
PPH_MINIINFO_LIST_SECTION_CALLBACK Callback; // Initialization
// end_phapppub
// Private
PH_LAYOUT_MANAGER LayoutManager;
ULONG RunCount;
LONG SuspendUpdate;
PPH_LIST ProcessGroupList;
PPH_LIST NodeList;
HANDLE SelectedRepresentativeProcessId;
LARGE_INTEGER SelectedRepresentativeCreateTime;
// begin_phapppub
} PH_MINIINFO_LIST_SECTION, *PPH_MINIINFO_LIST_SECTION;
// end_phapppub
#endif

View File

@ -0,0 +1,403 @@
#ifndef PH_MINIINFOP_H
#define PH_MINIINFOP_H
// Constants
#define MIP_CONTAINER_CLASSNAME L"ProcessHackerMiniInfo"
#define MIP_TIMER_PIN_FIRST 1
#define MIP_TIMER_PIN_LAST (MIP_TIMER_PIN_FIRST + MaxMiniInfoPinType - 1)
#define MIP_MSG_FIRST (WM_APP + 150)
#define MIP_MSG_UPDATE (WM_APP + 150)
#define MIP_MSG_LAST (WM_APP + 151)
#define MIP_UNPIN_CHILD_CONTROL_DELAY 1000
#define MIP_UNPIN_HOVER_DELAY 250
#define MIP_REFRESH_AUTOMATICALLY_PINNED 0x1
#define MIP_REFRESH_AUTOMATICALLY_UNPINNED 0x2
#define MIP_REFRESH_AUTOMATICALLY_FLAG(Pinned) \
((Pinned) ? MIP_REFRESH_AUTOMATICALLY_PINNED : MIP_REFRESH_AUTOMATICALLY_UNPINNED)
// Misc.
#define SET_BUTTON_ICON(hwndDlg, Id, Icon) \
SendMessage(GetDlgItem(hwndDlg, (Id)), BM_SETIMAGE, IMAGE_ICON, (LPARAM)(Icon))
// Dialog procedure
LRESULT CALLBACK PhMipContainerWndProc(
_In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhMipMiniInfoDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// Container event handlers
VOID PhMipContainerOnShowWindow(
_In_ BOOLEAN Showing,
_In_ ULONG State
);
VOID PhMipContainerOnActivate(
_In_ ULONG Type,
_In_ BOOLEAN Minimized
);
VOID PhMipContainerOnSize(
VOID
);
VOID PhMipContainerOnSizing(
_In_ ULONG Edge,
_In_ PRECT DragRectangle
);
VOID PhMipContainerOnExitSizeMove(
VOID
);
BOOLEAN PhMipContainerOnEraseBkgnd(
_In_ HDC hdc
);
VOID PhMipContainerOnTimer(
_In_ ULONG Id
);
// Child dialog event handlers
VOID PhMipOnInitDialog(
VOID
);
VOID PhMipOnShowWindow(
_In_ BOOLEAN Showing,
_In_ ULONG State
);
VOID PhMipOnCommand(
_In_ ULONG Id,
_In_ ULONG Code
);
BOOLEAN PhMipOnNotify(
_In_ NMHDR *Header,
_Out_ LRESULT *Result
);
BOOLEAN PhMipOnCtlColorXxx(
_In_ ULONG Message,
_In_ HWND hwnd,
_In_ HDC hdc,
_Out_ HBRUSH *Brush
);
BOOLEAN PhMipOnDrawItem(
_In_ ULONG_PTR Id,
_In_ DRAWITEMSTRUCT *DrawItemStruct
);
VOID PhMipOnUserMessage(
_In_ ULONG Message,
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam
);
// Framework
typedef enum _PH_MIP_ADJUST_PIN_RESULT
{
NoAdjustPinResult,
ShowAdjustPinResult,
HideAdjustPinResult
} PH_MIP_ADJUST_PIN_RESULT;
BOOLEAN NTAPI PhMipMessageLoopFilter(
_In_ PMSG Message,
_In_ PVOID Context
);
VOID NTAPI PhMipUpdateHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
PH_MIP_ADJUST_PIN_RESULT PhMipAdjustPin(
_In_ PH_MINIINFO_PIN_TYPE PinType,
_In_ LONG PinCount
);
VOID PhMipCalculateWindowRectangle(
_In_ PPOINT SourcePoint,
_Out_ PPH_RECTANGLE WindowRectangle
);
VOID PhMipInitializeParameters(
VOID
);
PPH_MINIINFO_SECTION PhMipCreateSection(
_In_ PPH_MINIINFO_SECTION Template
);
VOID PhMipDestroySection(
_In_ PPH_MINIINFO_SECTION Section
);
PPH_MINIINFO_SECTION PhMipFindSection(
_In_ PPH_STRINGREF Name
);
PPH_MINIINFO_SECTION PhMipCreateInternalSection(
_In_ PWSTR Name,
_In_ ULONG Flags,
_In_ PPH_MINIINFO_SECTION_CALLBACK Callback
);
VOID PhMipCreateSectionDialog(
_In_ PPH_MINIINFO_SECTION Section
);
VOID PhMipChangeSection(
_In_ PPH_MINIINFO_SECTION NewSection
);
VOID PhMipSetSectionText(
_In_ struct _PH_MINIINFO_SECTION *Section,
_In_opt_ PPH_STRING Text
);
VOID PhMipUpdateSectionText(
_In_ PPH_MINIINFO_SECTION Section
);
VOID PhMipLayout(
VOID
);
VOID PhMipBeginChildControlPin(
VOID
);
VOID PhMipEndChildControlPin(
VOID
);
VOID PhMipRefresh(
VOID
);
VOID PhMipToggleRefreshAutomatically(
VOID
);
VOID PhMipSetPinned(
_In_ BOOLEAN Pinned
);
VOID PhMipShowSectionMenu(
VOID
);
VOID PhMipShowOptionsMenu(
VOID
);
LRESULT CALLBACK PhMipSectionControlHookWndProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// List-based section
#define MIP_MAX_PROCESS_GROUPS 15
#define MIP_SINGLE_COLUMN_ID 0
#define MIP_CELL_PADDING 5
#define MIP_ICON_PADDING 3
#define MIP_INNER_PADDING 3
typedef struct _PH_MIP_GROUP_NODE
{
union
{
PH_TREENEW_NODE Node;
PH_MINIINFO_LIST_SECTION_SORT_DATA SortData;
};
PPH_PROCESS_GROUP ProcessGroup;
HANDLE RepresentativeProcessId;
LARGE_INTEGER RepresentativeCreateTime;
BOOLEAN RepresentativeIsHung;
PPH_STRING TooltipText;
} PH_MIP_GROUP_NODE, *PPH_MIP_GROUP_NODE;
PPH_MINIINFO_LIST_SECTION PhMipCreateListSection(
_In_ PWSTR Name,
_In_ ULONG Flags,
_In_ PPH_MINIINFO_LIST_SECTION Template
);
PPH_MINIINFO_LIST_SECTION PhMipCreateInternalListSection(
_In_ PWSTR Name,
_In_ ULONG Flags,
_In_ PPH_MINIINFO_LIST_SECTION_CALLBACK Callback
);
BOOLEAN PhMipListSectionCallback(
_In_ PPH_MINIINFO_SECTION Section,
_In_ PH_MINIINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
INT_PTR CALLBACK PhMipListSectionDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhMipListSectionSortFunction(
_In_ PPH_LIST List,
_In_opt_ PVOID Context
);
VOID PhMipTickListSection(
_In_ PPH_MINIINFO_LIST_SECTION ListSection
);
VOID PhMipClearListSection(
_In_ PPH_MINIINFO_LIST_SECTION ListSection
);
LONG PhMipCalculateRowHeight(
VOID
);
PPH_MIP_GROUP_NODE PhMipAddGroupNode(
_In_ PPH_MINIINFO_LIST_SECTION ListSection,
_In_ PPH_PROCESS_GROUP ProcessGroup
);
VOID PhMipDestroyGroupNode(
_In_ PPH_MIP_GROUP_NODE Node
);
BOOLEAN PhMipListSectionTreeNewCallback(
_In_ HWND hwnd,
_In_ PH_TREENEW_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2,
_In_opt_ PVOID Context
);
PPH_STRING PhMipGetGroupNodeTooltip(
_In_ PPH_MINIINFO_LIST_SECTION ListSection,
_In_ PPH_MIP_GROUP_NODE Node
);
PPH_MIP_GROUP_NODE PhMipGetSelectedGroupNode(
_In_ PPH_MINIINFO_LIST_SECTION ListSection
);
VOID PhMipShowListSectionContextMenu(
_In_ PPH_MINIINFO_LIST_SECTION ListSection,
_In_ PPH_TREENEW_CONTEXT_MENU ContextMenu
);
VOID PhMipHandleListSectionCommand(
_In_ PPH_MINIINFO_LIST_SECTION ListSection,
_In_ PPH_PROCESS_GROUP ProcessGroup,
_In_ ULONG Id
);
// CPU section
BOOLEAN PhMipCpuListSectionCallback(
_In_ struct _PH_MINIINFO_LIST_SECTION *ListSection,
_In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
int __cdecl PhMipCpuListSectionProcessCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
int __cdecl PhMipCpuListSectionNodeCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
// Commit charge section
BOOLEAN PhMipCommitListSectionCallback(
_In_ struct _PH_MINIINFO_LIST_SECTION *ListSection,
_In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
int __cdecl PhMipCommitListSectionProcessCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
int __cdecl PhMipCommitListSectionNodeCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
// Physical memory section
BOOLEAN PhMipPhysicalListSectionCallback(
_In_ struct _PH_MINIINFO_LIST_SECTION *ListSection,
_In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
int __cdecl PhMipPhysicalListSectionProcessCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
int __cdecl PhMipPhysicalListSectionNodeCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
// I/O section
BOOLEAN PhMipIoListSectionCallback(
_In_ struct _PH_MINIINFO_LIST_SECTION *ListSection,
_In_ PH_MINIINFO_LIST_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
int __cdecl PhMipIoListSectionProcessCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
int __cdecl PhMipIoListSectionNodeCompareFunction(
_In_ const void *elem1,
_In_ const void *elem2
);
#endif

View File

@ -0,0 +1,132 @@
#ifndef PH_MODLIST_H
#define PH_MODLIST_H
#include <phuisup.h>
#include <colmgr.h>
// Columns
#define PHMOTLC_NAME 0
#define PHMOTLC_BASEADDRESS 1
#define PHMOTLC_SIZE 2
#define PHMOTLC_DESCRIPTION 3
#define PHMOTLC_COMPANYNAME 4
#define PHMOTLC_VERSION 5
#define PHMOTLC_FILENAME 6
#define PHMOTLC_TYPE 7
#define PHMOTLC_LOADCOUNT 8
#define PHMOTLC_VERIFICATIONSTATUS 9
#define PHMOTLC_VERIFIEDSIGNER 10
#define PHMOTLC_ASLR 11
#define PHMOTLC_TIMESTAMP 12
#define PHMOTLC_CFGUARD 13
#define PHMOTLC_LOADTIME 14
#define PHMOTLC_LOADREASON 15
#define PHMOTLC_FILEMODIFIEDTIME 16
#define PHMOTLC_FILESIZE 17
#define PHMOTLC_MAXIMUM 18
// begin_phapppub
typedef struct _PH_MODULE_NODE
{
PH_TREENEW_NODE Node;
PH_SH_STATE ShState;
PPH_MODULE_ITEM ModuleItem;
// end_phapppub
PH_STRINGREF TextCache[PHMOTLC_MAXIMUM];
ULONG ValidMask;
PPH_STRING TooltipText;
PPH_STRING SizeText;
WCHAR LoadCountText[PH_INT32_STR_LEN_1];
PPH_STRING TimeStampText;
PPH_STRING LoadTimeText;
PPH_STRING FileModifiedTimeText;
PPH_STRING FileSizeText;
// begin_phapppub
} PH_MODULE_NODE, *PPH_MODULE_NODE;
// end_phapppub
typedef struct _PH_MODULE_LIST_CONTEXT
{
HWND ParentWindowHandle;
HWND TreeNewHandle;
ULONG TreeNewSortColumn;
PH_SORT_ORDER TreeNewSortOrder;
PH_CM_MANAGER Cm;
PPH_HASHTABLE NodeHashtable;
PPH_LIST NodeList;
BOOLEAN EnableStateHighlighting;
PPH_POINTER_LIST NodeStateList;
HFONT BoldFont;
} PH_MODULE_LIST_CONTEXT, *PPH_MODULE_LIST_CONTEXT;
VOID PhInitializeModuleList(
_In_ HWND ParentWindowHandle,
_In_ HWND TreeNewHandle,
_Out_ PPH_MODULE_LIST_CONTEXT Context
);
VOID PhDeleteModuleList(
_In_ PPH_MODULE_LIST_CONTEXT Context
);
VOID PhLoadSettingsModuleList(
_Inout_ PPH_MODULE_LIST_CONTEXT Context
);
VOID PhSaveSettingsModuleList(
_Inout_ PPH_MODULE_LIST_CONTEXT Context
);
PPH_MODULE_NODE PhAddModuleNode(
_Inout_ PPH_MODULE_LIST_CONTEXT Context,
_In_ PPH_MODULE_ITEM ModuleItem,
_In_ ULONG RunId
);
PPH_MODULE_NODE PhFindModuleNode(
_In_ PPH_MODULE_LIST_CONTEXT Context,
_In_ PPH_MODULE_ITEM ModuleItem
);
VOID PhRemoveModuleNode(
_In_ PPH_MODULE_LIST_CONTEXT Context,
_In_ PPH_MODULE_NODE ModuleNode
);
VOID PhUpdateModuleNode(
_In_ PPH_MODULE_LIST_CONTEXT Context,
_In_ PPH_MODULE_NODE ModuleNode
);
VOID PhTickModuleNodes(
_In_ PPH_MODULE_LIST_CONTEXT Context
);
PPH_MODULE_ITEM PhGetSelectedModuleItem(
_In_ PPH_MODULE_LIST_CONTEXT Context
);
VOID PhGetSelectedModuleItems(
_In_ PPH_MODULE_LIST_CONTEXT Context,
_Out_ PPH_MODULE_ITEM **Modules,
_Out_ PULONG NumberOfModules
);
VOID PhDeselectAllModuleNodes(
_In_ PPH_MODULE_LIST_CONTEXT Context
);
#endif

View File

@ -0,0 +1,80 @@
#ifndef PH_MODPRV_H
#define PH_MODPRV_H
extern PPH_OBJECT_TYPE PhModuleProviderType;
extern PPH_OBJECT_TYPE PhModuleItemType;
// begin_phapppub
typedef struct _PH_MODULE_ITEM
{
PVOID BaseAddress;
ULONG Size;
ULONG Flags;
ULONG Type;
USHORT LoadReason;
USHORT LoadCount;
PPH_STRING Name;
PPH_STRING FileName;
PH_IMAGE_VERSION_INFO VersionInfo;
WCHAR BaseAddressString[PH_PTR_STR_LEN_1];
BOOLEAN IsFirst;
BOOLEAN JustProcessed;
enum _VERIFY_RESULT VerifyResult;
PPH_STRING VerifySignerName;
ULONG ImageTimeDateStamp;
USHORT ImageCharacteristics;
USHORT ImageDllCharacteristics;
LARGE_INTEGER LoadTime;
LARGE_INTEGER FileLastWriteTime;
LARGE_INTEGER FileEndOfFile;
} PH_MODULE_ITEM, *PPH_MODULE_ITEM;
typedef struct _PH_MODULE_PROVIDER
{
PPH_HASHTABLE ModuleHashtable;
PH_FAST_LOCK ModuleHashtableLock;
PH_CALLBACK ModuleAddedEvent;
PH_CALLBACK ModuleModifiedEvent;
PH_CALLBACK ModuleRemovedEvent;
PH_CALLBACK UpdatedEvent;
HANDLE ProcessId;
HANDLE ProcessHandle;
PPH_STRING PackageFullName;
SLIST_HEADER QueryListHead;
NTSTATUS RunStatus;
} PH_MODULE_PROVIDER, *PPH_MODULE_PROVIDER;
// end_phapppub
BOOLEAN PhModuleProviderInitialization(
VOID
);
PPH_MODULE_PROVIDER PhCreateModuleProvider(
_In_ HANDLE ProcessId
);
PPH_MODULE_ITEM PhCreateModuleItem(
VOID
);
PPH_MODULE_ITEM PhReferenceModuleItem(
_In_ PPH_MODULE_PROVIDER ModuleProvider,
_In_ PVOID BaseAddress
);
VOID PhDereferenceAllModuleItems(
_In_ PPH_MODULE_PROVIDER ModuleProvider
);
VOID PhModuleProviderUpdate(
_In_ PVOID Object
);
#endif

View File

@ -0,0 +1,119 @@
#ifndef PH_NETLIST_H
#define PH_NETLIST_H
#include <phuisup.h>
// Columns
#define PHNETLC_PROCESS 0
#define PHNETLC_LOCALADDRESS 1
#define PHNETLC_LOCALPORT 2
#define PHNETLC_REMOTEADDRESS 3
#define PHNETLC_REMOTEPORT 4
#define PHNETLC_PROTOCOL 5
#define PHNETLC_STATE 6
#define PHNETLC_OWNER 7
#define PHNETLC_TIMESTAMP 8
#define PHNETLC_MAXIMUM 9
// begin_phapppub
typedef struct _PH_NETWORK_NODE
{
PH_TREENEW_NODE Node;
PH_SH_STATE ShState;
PPH_NETWORK_ITEM NetworkItem;
// end_phapppub
PH_STRINGREF TextCache[PHNETLC_MAXIMUM];
LONG UniqueId;
PPH_STRING ProcessNameText;
PH_STRINGREF LocalAddressText;
PH_STRINGREF RemoteAddressText;
PPH_STRING TimeStampText;
PPH_STRING TooltipText;
// begin_phapppub
} PH_NETWORK_NODE, *PPH_NETWORK_NODE;
// end_phapppub
VOID PhNetworkTreeListInitialization(
VOID
);
VOID PhInitializeNetworkTreeList(
_In_ HWND hwnd
);
VOID PhLoadSettingsNetworkTreeList(
VOID
);
VOID PhSaveSettingsNetworkTreeList(
VOID
);
// begin_phapppub
PHAPPAPI
struct _PH_TN_FILTER_SUPPORT *
NTAPI
PhGetFilterSupportNetworkTreeList(
VOID
);
// end_phapppub
PPH_NETWORK_NODE PhAddNetworkNode(
_In_ PPH_NETWORK_ITEM NetworkItem,
_In_ ULONG RunId
);
// begin_phapppub
PHAPPAPI
PPH_NETWORK_NODE
NTAPI
PhFindNetworkNode(
_In_ PPH_NETWORK_ITEM NetworkItem
);
// end_phapppub
VOID PhRemoveNetworkNode(
_In_ PPH_NETWORK_NODE NetworkNode
);
VOID PhUpdateNetworkNode(
_In_ PPH_NETWORK_NODE NetworkNode
);
VOID PhTickNetworkNodes(
VOID
);
PPH_NETWORK_ITEM PhGetSelectedNetworkItem(
VOID
);
VOID PhGetSelectedNetworkItems(
_Out_ PPH_NETWORK_ITEM **NetworkItems,
_Out_ PULONG NumberOfNetworkItems
);
VOID PhDeselectAllNetworkNodes(
VOID
);
VOID PhSelectAndEnsureVisibleNetworkNode(
_In_ PPH_NETWORK_NODE NetworkNode
);
VOID PhCopyNetworkList(
VOID
);
VOID PhWriteNetworkList(
_Inout_ PPH_FILE_STREAM FileStream,
_In_ ULONG Mode
);
#endif

View File

@ -0,0 +1,86 @@
#ifndef PH_NETPRV_H
#define PH_NETPRV_H
extern PPH_OBJECT_TYPE PhNetworkItemType;
PHAPPAPI extern PH_CALLBACK PhNetworkItemAddedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhNetworkItemModifiedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhNetworkItemRemovedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhNetworkItemsUpdatedEvent; // phapppub
extern BOOLEAN PhEnableNetworkProviderResolve;
// begin_phapppub
#define PH_NETWORK_OWNER_INFO_SIZE 16
typedef struct _PH_NETWORK_ITEM
{
ULONG ProtocolType;
PH_IP_ENDPOINT LocalEndpoint;
PH_IP_ENDPOINT RemoteEndpoint;
ULONG State;
HANDLE ProcessId;
PPH_STRING ProcessName;
HICON ProcessIcon;
BOOLEAN ProcessIconValid;
PPH_STRING OwnerName;
BOOLEAN JustResolved;
WCHAR LocalAddressString[65];
WCHAR LocalPortString[PH_INT32_STR_LEN_1];
WCHAR RemoteAddressString[65];
WCHAR RemotePortString[PH_INT32_STR_LEN_1];
PPH_STRING LocalHostString;
PPH_STRING RemoteHostString;
LARGE_INTEGER CreateTime;
ULONGLONG OwnerInfo[PH_NETWORK_OWNER_INFO_SIZE];
} PH_NETWORK_ITEM, *PPH_NETWORK_ITEM;
// end_phapppub
BOOLEAN PhNetworkProviderInitialization(
VOID
);
PPH_NETWORK_ITEM PhCreateNetworkItem(
VOID
);
// begin_phapppub
PHAPPAPI
PPH_NETWORK_ITEM
NTAPI
PhReferenceNetworkItem(
_In_ ULONG ProtocolType,
_In_ PPH_IP_ENDPOINT LocalEndpoint,
_In_ PPH_IP_ENDPOINT RemoteEndpoint,
_In_ HANDLE ProcessId
);
// end_phapppub
PPH_STRING PhGetHostNameFromAddress(
_In_ PPH_IP_ADDRESS Address
);
VOID PhNetworkProviderUpdate(
_In_ PVOID Object
);
// begin_phapppub
PHAPPAPI
PWSTR
NTAPI
PhGetProtocolTypeName(
_In_ ULONG ProtocolType
);
PHAPPAPI
PWSTR
NTAPI
PhGetTcpStateName(
_In_ ULONG State
);
// end_phapppub
#endif

View File

@ -0,0 +1,171 @@
#ifndef PH_NOTIFICO_H
#define PH_NOTIFICO_H
#define PH_ICON_MINIMUM 0x1
#define PH_ICON_CPU_HISTORY 0x1
#define PH_ICON_IO_HISTORY 0x2
#define PH_ICON_COMMIT_HISTORY 0x4
#define PH_ICON_PHYSICAL_HISTORY 0x8
#define PH_ICON_CPU_USAGE 0x10
#define PH_ICON_DEFAULT_MAXIMUM 0x20
#define PH_ICON_DEFAULT_ALL 0x1f
#define PH_ICON_LIMIT 0x80000000
#define PH_ICON_ALL 0xffffffff
// begin_phapppub
typedef VOID (NTAPI *PPH_NF_UPDATE_REGISTERED_ICON)(
_In_ struct _PH_NF_ICON *Icon
);
typedef VOID (NTAPI *PPH_NF_BEGIN_BITMAP)(
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ HBITMAP *Bitmap,
_Out_opt_ PVOID *Bits,
_Out_ HDC *Hdc,
_Out_ HBITMAP *OldBitmap
);
typedef struct _PH_NF_POINTERS
{
PPH_NF_UPDATE_REGISTERED_ICON UpdateRegisteredIcon;
PPH_NF_BEGIN_BITMAP BeginBitmap;
} PH_NF_POINTERS, *PPH_NF_POINTERS;
#define PH_NF_UPDATE_IS_BITMAP 0x1
#define PH_NF_UPDATE_DESTROY_RESOURCE 0x2
typedef VOID (NTAPI *PPH_NF_ICON_UPDATE_CALLBACK)(
_In_ struct _PH_NF_ICON *Icon,
_Out_ PVOID *NewIconOrBitmap,
_Out_ PULONG Flags,
_Out_ PPH_STRING *NewText,
_In_opt_ PVOID Context
);
typedef BOOLEAN (NTAPI *PPH_NF_ICON_MESSAGE_CALLBACK)(
_In_ struct _PH_NF_ICON *Icon,
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam,
_In_opt_ PVOID Context
);
// Special messages
// The message type is stored in LOWORD(LParam), and the message data is in WParam.
#define PH_NF_MSG_SHOWMINIINFOSECTION (WM_APP + 1)
typedef struct _PH_NF_MSG_SHOWMINIINFOSECTION_DATA
{
PWSTR SectionName; // NULL to leave unchanged
} PH_NF_MSG_SHOWMINIINFOSECTION_DATA, *PPH_NF_MSG_SHOWMINIINFOSECTION_DATA;
// Structures and internal functions
#define PH_NF_ICON_UNAVAILABLE 0x1
#define PH_NF_ICON_SHOW_MINIINFO 0x2
// end_phapppub
// begin_phapppub
typedef struct _PH_NF_ICON
{
// Public
struct _PH_PLUGIN *Plugin;
ULONG SubId;
PVOID Context;
PPH_NF_POINTERS Pointers;
// end_phapppub
// Private
PWSTR Text;
ULONG Flags;
ULONG IconId;
PPH_NF_ICON_UPDATE_CALLBACK UpdateCallback;
PPH_NF_ICON_MESSAGE_CALLBACK MessageCallback;
// begin_phapppub
} PH_NF_ICON, *PPH_NF_ICON;
// end_phapppub
VOID PhNfLoadStage1(
VOID
);
VOID PhNfLoadStage2(
VOID
);
VOID PhNfSaveSettings(
VOID
);
VOID PhNfUninitialization(
VOID
);
VOID PhNfForwardMessage(
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam
);
ULONG PhNfGetMaximumIconId(
VOID
);
ULONG PhNfTestIconMask(
_In_ ULONG Id
);
VOID PhNfSetVisibleIcon(
_In_ ULONG Id,
_In_ BOOLEAN Visible
);
BOOLEAN PhNfShowBalloonTip(
_In_opt_ ULONG Id,
_In_ PWSTR Title,
_In_ PWSTR Text,
_In_ ULONG Timeout,
_In_ ULONG Flags
);
HICON PhNfBitmapToIcon(
_In_ HBITMAP Bitmap
);
PPH_NF_ICON PhNfRegisterIcon(
_In_ struct _PH_PLUGIN *Plugin,
_In_ ULONG SubId,
_In_opt_ PVOID Context,
_In_ PWSTR Text,
_In_ ULONG Flags,
_In_opt_ PPH_NF_ICON_UPDATE_CALLBACK UpdateCallback,
_In_opt_ PPH_NF_ICON_MESSAGE_CALLBACK MessageCallback
);
PPH_NF_ICON PhNfGetIconById(
_In_ ULONG Id
);
PPH_NF_ICON PhNfFindIcon(
_In_ PPH_STRINGREF PluginName,
_In_ ULONG SubId
);
VOID PhNfNotifyMiniInfoPinned(
_In_ BOOLEAN Pinned
);
// begin_phapppub
// Public registration data
typedef struct _PH_NF_ICON_REGISTRATION_DATA
{
PPH_NF_ICON_UPDATE_CALLBACK UpdateCallback;
PPH_NF_ICON_MESSAGE_CALLBACK MessageCallback;
} PH_NF_ICON_REGISTRATION_DATA, *PPH_NF_ICON_REGISTRATION_DATA;
// end_phapppub
#endif

View File

@ -0,0 +1,107 @@
#ifndef PH_NOTIFICOP_H
#define PH_NOTIFICOP_H
typedef struct _PH_NF_BITMAP
{
BOOLEAN Initialized;
HDC Hdc;
BITMAPINFOHEADER Header;
HBITMAP Bitmap;
PVOID Bits;
} PH_NF_BITMAP, *PPH_NF_BITMAP;
HICON PhNfpGetBlackIcon(
VOID
);
BOOLEAN PhNfpAddNotifyIcon(
_In_ ULONG Id
);
BOOLEAN PhNfpRemoveNotifyIcon(
_In_ ULONG Id
);
BOOLEAN PhNfpModifyNotifyIcon(
_In_ ULONG Id,
_In_ ULONG Flags,
_In_opt_ PPH_STRING Text,
_In_opt_ HICON Icon
);
VOID PhNfpProcessesUpdatedHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
VOID PhNfpUpdateRegisteredIcon(
_In_ PPH_NF_ICON Icon
);
VOID PhNfpBeginBitmap(
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ HBITMAP *Bitmap,
_Out_opt_ PVOID *Bits,
_Out_ HDC *Hdc,
_Out_ HBITMAP *OldBitmap
);
VOID PhNfpBeginBitmap2(
_Inout_ PPH_NF_BITMAP Context,
_Out_ PULONG Width,
_Out_ PULONG Height,
_Out_ HBITMAP *Bitmap,
_Out_opt_ PVOID *Bits,
_Out_ HDC *Hdc,
_Out_ HBITMAP *OldBitmap
);
VOID PhNfpUpdateIconCpuHistory(
VOID
);
VOID PhNfpUpdateIconIoHistory(
VOID
);
VOID PhNfpUpdateIconCommitHistory(
VOID
);
VOID PhNfpUpdateIconPhysicalHistory(
VOID
);
VOID PhNfpUpdateIconCpuUsage(
VOID
);
BOOLEAN PhNfpGetShowMiniInfoSectionData(
_In_ ULONG IconIndex,
_In_ PPH_NF_ICON RegisteredIcon,
_Out_ PPH_NF_MSG_SHOWMINIINFOSECTION_DATA Data
);
#define NFP_ICON_CLICK_ACTIVATE_DELAY 140
#define NFP_ICON_RESTORE_HOVER_DELAY 1000
VOID PhNfpIconClickActivateTimerProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime
);
VOID PhNfpDisableHover(
VOID
);
VOID PhNfpIconRestoreHoverTimerProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ UINT_PTR idEvent,
_In_ DWORD dwTime
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
// Notes:
// * Do not use /* comments */ since ISPP is buggy and it will throw an error.
#ifndef PH_PHAPPRES_H
#define PH_PHAPPRES_H
#include "phapprev.h"
#define PHAPP_VERSION_MAJOR 2
#define PHAPP_VERSION_MINOR 39
#define PHAPP_VERSION_BUILD 0
#if (PHAPP_VERSION_BUILD == 0)
#define TWO_DIGIT_VER 1
#else
#define THREE_DIGIT_VER 1
#endif
#define DO_MAKE_STR(x) #x
#define MAKE_STR(x) DO_MAKE_STR(x)
#ifndef ISPP_INVOKED
#if defined(TWO_DIGIT_VER)
#define PHAPP_VERSION_STRING MAKE_STR(PHAPP_VERSION_MAJOR) "." MAKE_STR(PHAPP_VERSION_MINOR) ".0" "." MAKE_STR(PHAPP_VERSION_REVISION)
#elif defined(THREE_DIGIT_VER)
#define PHAPP_VERSION_STRING MAKE_STR(PHAPP_VERSION_MAJOR) "." MAKE_STR(PHAPP_VERSION_MINOR) "." MAKE_STR(PHAPP_VERSION_BUILD) "." MAKE_STR(PHAPP_VERSION_REVISION)
#endif
#define PHAPP_VERSION_NUMBER PHAPP_VERSION_MAJOR,PHAPP_VERSION_MINOR,PHAPP_VERSION_BUILD,PHAPP_VERSION_REVISION
#endif // ISPP_INVOKED
#endif // PHAPPRES_H

View File

@ -0,0 +1,6 @@
#ifndef PHAPPREV_H
#define PHAPPREV_H
#define PHAPP_VERSION_REVISION $COMMITS$
#endif // PHAPPREV_H

View File

@ -0,0 +1,31 @@
#ifndef PH_PHFWDDEF_H
#define PH_PHFWDDEF_H
// begin_phapppub
// Providers
typedef struct _PH_PROCESS_ITEM *PPH_PROCESS_ITEM;
typedef struct _PH_PROCESS_RECORD *PPH_PROCESS_RECORD;
typedef struct _PH_SERVICE_ITEM *PPH_SERVICE_ITEM;
typedef struct _PH_NETWORK_ITEM *PPH_NETWORK_ITEM;
typedef struct _PH_MODULE_ITEM *PPH_MODULE_ITEM;
typedef struct _PH_MODULE_PROVIDER *PPH_MODULE_PROVIDER;
typedef struct _PH_THREAD_ITEM *PPH_THREAD_ITEM;
typedef struct _PH_THREAD_PROVIDER *PPH_THREAD_PROVIDER;
typedef struct _PH_HANDLE_ITEM *PPH_HANDLE_ITEM;
typedef struct _PH_HANDLE_PROVIDER *PPH_HANDLE_PROVIDER;
typedef struct _PH_MEMORY_ITEM *PPH_MEMORY_ITEM;
typedef struct _PH_MEMORY_ITEM_LIST *PPH_MEMORY_ITEM_LIST;
// uimodels
typedef struct _PH_PROCESS_NODE *PPH_PROCESS_NODE;
typedef struct _PH_SERVICE_NODE *PPH_SERVICE_NODE;
typedef struct _PH_NETWORK_NODE *PPH_NETWORK_NODE;
typedef struct _PH_MODULE_NODE *PPH_MODULE_NODE;
typedef struct _PH_THREAD_NODE *PPH_THREAD_NODE;
typedef struct _PH_HANDLE_NODE *PPH_HANDLE_NODE;
typedef struct _PH_MEMORY_NODE *PPH_MEMORY_NODE;
// end_phapppub
#endif

View File

@ -0,0 +1,675 @@
#ifndef PH_PHPLUG_H
#define PH_PHPLUG_H
#include <extmgr.h>
#include <sysinfo.h>
#include <miniinfo.h>
// begin_phapppub
// Callbacks
typedef enum _PH_GENERAL_CALLBACK
{
GeneralCallbackMainWindowShowing = 0, // INT ShowCommand [main thread]
GeneralCallbackProcessesUpdated = 1, // [main thread]
GeneralCallbackGetProcessHighlightingColor = 2, // PPH_PLUGIN_GET_HIGHLIGHTING_COLOR Data [main thread]
GeneralCallbackGetProcessTooltipText = 3, // PPH_PLUGIN_GET_TOOLTIP_TEXT Data [main thread]
GeneralCallbackProcessPropertiesInitializing = 4, // PPH_PLUGIN_PROCESS_PROPCONTEXT Data [properties thread]
GeneralCallbackMainMenuInitializing = 5, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackNotifyEvent = 6, // PPH_PLUGIN_NOTIFY_EVENT Data [main thread]
GeneralCallbackServicePropertiesInitializing = 7, // PPH_PLUGIN_OBJECT_PROPERTIES Data [properties thread]
GeneralCallbackHandlePropertiesInitializing = 8, // PPH_PLUGIN_OBJECT_PROPERTIES Data [properties thread]
GeneralCallbackProcessMenuInitializing = 9, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackServiceMenuInitializing = 10, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackNetworkMenuInitializing = 11, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackIconMenuInitializing = 12, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackThreadMenuInitializing = 13, // PPH_PLUGIN_MENU_INFORMATION Data [properties thread]
GeneralCallbackModuleMenuInitializing = 14, // PPH_PLUGIN_MENU_INFORMATION Data [properties thread]
GeneralCallbackMemoryMenuInitializing = 15, // PPH_PLUGIN_MENU_INFORMATION Data [properties thread]
GeneralCallbackHandleMenuInitializing = 16, // PPH_PLUGIN_MENU_INFORMATION Data [properties thread]
GeneralCallbackProcessTreeNewInitializing = 17, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
GeneralCallbackServiceTreeNewInitializing = 18, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
GeneralCallbackNetworkTreeNewInitializing = 19, // PPH_PLUGIN_TREENEW_INFORMATION Data [main thread]
GeneralCallbackModuleTreeNewInitializing = 20, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackModuleTreeNewUninitializing = 21, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackThreadTreeNewInitializing = 22, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackThreadTreeNewUninitializing = 23, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackHandleTreeNewInitializing = 24, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackHandleTreeNewUninitializing = 25, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackThreadStackControl = 26, // PPH_PLUGIN_THREAD_STACK_CONTROL Data [properties thread]
GeneralCallbackSystemInformationInitializing = 27, // PPH_PLUGIN_SYSINFO_POINTERS Data [system information thread]
GeneralCallbackMainWindowTabChanged = 28, // INT NewIndex [main thread]
GeneralCallbackMemoryTreeNewInitializing = 29, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackMemoryTreeNewUninitializing = 30, // PPH_PLUGIN_TREENEW_INFORMATION Data [properties thread]
GeneralCallbackMemoryItemListControl = 31, // PPH_PLUGIN_MEMORY_ITEM_LIST_CONTROL Data [properties thread]
GeneralCallbackMiniInformationInitializing = 32, // PPH_PLUGIN_MINIINFO_POINTERS Data [main thread]
GeneralCallbackMiListSectionMenuInitializing = 33, // PPH_PLUGIN_MENU_INFORMATION Data [main thread]
GeneralCallbackMaximum
} PH_GENERAL_CALLBACK, *PPH_GENERAL_CALLBACK;
typedef enum _PH_PLUGIN_CALLBACK
{
PluginCallbackLoad = 0, // PPH_LIST Parameters [main thread] // list of strings, might be NULL
PluginCallbackUnload = 1, // [main thread]
PluginCallbackShowOptions = 2, // HWND ParentWindowHandle [main thread]
PluginCallbackMenuItem = 3, // PPH_PLUGIN_MENU_ITEM MenuItem [main/properties thread]
PluginCallbackTreeNewMessage = 4, // PPH_PLUGIN_TREENEW_MESSAGE Message [main/properties thread]
PluginCallbackPhSvcRequest = 5, // PPH_PLUGIN_PHSVC_REQUEST Message [phsvc thread]
PluginCallbackMenuHook = 6, // PH_PLUGIN_MENU_HOOK_INFORMATION MenuHookInfo [menu thread]
PluginCallbackMaximum
} PH_PLUGIN_CALLBACK, *PPH_PLUGIN_CALLBACK;
typedef struct _PH_PLUGIN_GET_HIGHLIGHTING_COLOR
{
// Parameter is:
// PPH_PROCESS_ITEM for GeneralCallbackGetProcessHighlightingColor
PVOID Parameter;
COLORREF BackColor;
BOOLEAN Handled;
BOOLEAN Cache;
} PH_PLUGIN_GET_HIGHLIGHTING_COLOR, *PPH_PLUGIN_GET_HIGHLIGHTING_COLOR;
typedef struct _PH_PLUGIN_GET_TOOLTIP_TEXT
{
// Parameter is:
// PPH_PROCESS_ITEM for GeneralCallbackGetProcessTooltipText
PVOID Parameter;
PPH_STRING_BUILDER StringBuilder;
ULONG ValidForMs;
} PH_PLUGIN_GET_TOOLTIP_TEXT, *PPH_PLUGIN_GET_TOOLTIP_TEXT;
typedef struct _PH_PLUGIN_PROCESS_PROPCONTEXT
{
PPH_PROCESS_PROPCONTEXT PropContext;
PPH_PROCESS_ITEM ProcessItem;
} PH_PLUGIN_PROCESS_PROPCONTEXT, *PPH_PLUGIN_PROCESS_PROPCONTEXT;
typedef struct _PH_PLUGIN_NOTIFY_EVENT
{
// Parameter is:
// PPH_PROCESS_ITEM for Type = PH_NOTIFY_PROCESS_*
// PPH_SERVICE_ITEM for Type = PH_NOTIFY_SERVICE_*
ULONG Type;
BOOLEAN Handled;
PVOID Parameter;
} PH_PLUGIN_NOTIFY_EVENT, *PPH_PLUGIN_NOTIFY_EVENT;
typedef struct _PH_PLUGIN_OBJECT_PROPERTIES
{
// Parameter is:
// PPH_SERVICE_ITEM for GeneralCallbackServicePropertiesInitializing
// PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT for GeneralCallbackHandlePropertiesInitializing
PVOID Parameter;
ULONG NumberOfPages;
ULONG MaximumNumberOfPages;
HPROPSHEETPAGE *Pages;
} PH_PLUGIN_OBJECT_PROPERTIES, *PPH_PLUGIN_OBJECT_PROPERTIES;
typedef struct _PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT
{
HANDLE ProcessId;
PPH_HANDLE_ITEM HandleItem;
} PH_PLUGIN_HANDLE_PROPERTIES_CONTEXT, *PPH_PLUGIN_HANDLE_PROPERTIES_CONTEXT;
typedef struct _PH_EMENU_ITEM *PPH_EMENU_ITEM, *PPH_EMENU;
#define PH_PLUGIN_MENU_DISALLOW_HOOKS 0x1
typedef struct _PH_PLUGIN_MENU_INFORMATION
{
PPH_EMENU Menu;
HWND OwnerWindow;
union
{
struct
{
PVOID Reserved[8]; // Reserve space for future expansion of this union
} DoNotUse;
struct
{
ULONG SubMenuIndex;
} MainMenu;
struct
{
PPH_PROCESS_ITEM *Processes;
ULONG NumberOfProcesses;
} Process;
struct
{
PPH_SERVICE_ITEM *Services;
ULONG NumberOfServices;
} Service;
struct
{
PPH_NETWORK_ITEM *NetworkItems;
ULONG NumberOfNetworkItems;
} Network;
struct
{
HANDLE ProcessId;
PPH_THREAD_ITEM *Threads;
ULONG NumberOfThreads;
} Thread;
struct
{
HANDLE ProcessId;
PPH_MODULE_ITEM *Modules;
ULONG NumberOfModules;
} Module;
struct
{
HANDLE ProcessId;
PPH_MEMORY_NODE *MemoryNodes;
ULONG NumberOfMemoryNodes;
} Memory;
struct
{
HANDLE ProcessId;
PPH_HANDLE_ITEM *Handles;
ULONG NumberOfHandles;
} Handle;
struct
{
PPH_STRINGREF SectionName;
PPH_PROCESS_GROUP ProcessGroup;
} MiListSection;
} u;
ULONG Flags;
PPH_LIST PluginHookList;
} PH_PLUGIN_MENU_INFORMATION, *PPH_PLUGIN_MENU_INFORMATION;
C_ASSERT(RTL_FIELD_SIZE(PH_PLUGIN_MENU_INFORMATION, u) == RTL_FIELD_SIZE(PH_PLUGIN_MENU_INFORMATION, u.DoNotUse));
typedef struct _PH_PLUGIN_MENU_HOOK_INFORMATION
{
PPH_PLUGIN_MENU_INFORMATION MenuInfo;
PPH_EMENU SelectedItem;
PVOID Context;
BOOLEAN Handled;
} PH_PLUGIN_MENU_HOOK_INFORMATION, *PPH_PLUGIN_MENU_HOOK_INFORMATION;
typedef struct _PH_PLUGIN_TREENEW_INFORMATION
{
HWND TreeNewHandle;
PVOID CmData;
PVOID SystemContext; // e.g. PPH_THREADS_CONTEXT
} PH_PLUGIN_TREENEW_INFORMATION, *PPH_PLUGIN_TREENEW_INFORMATION;
typedef enum _PH_PLUGIN_THREAD_STACK_CONTROL_TYPE
{
PluginThreadStackInitializing,
PluginThreadStackUninitializing,
PluginThreadStackResolveSymbol,
PluginThreadStackGetTooltip,
PluginThreadStackWalkStack,
PluginThreadStackBeginDefaultWalkStack,
PluginThreadStackEndDefaultWalkStack,
PluginThreadStackMaximum
} PH_PLUGIN_THREAD_STACK_CONTROL_TYPE;
typedef struct _PH_SYMBOL_PROVIDER *PPH_SYMBOL_PROVIDER;
typedef struct _PH_THREAD_STACK_FRAME *PPH_THREAD_STACK_FRAME;
typedef BOOLEAN (NTAPI *PPH_PLUGIN_WALK_THREAD_STACK_CALLBACK)(
_In_ PPH_THREAD_STACK_FRAME StackFrame,
_In_opt_ PVOID Context
);
typedef struct _PH_PLUGIN_THREAD_STACK_CONTROL
{
PH_PLUGIN_THREAD_STACK_CONTROL_TYPE Type;
PVOID UniqueKey;
union
{
struct
{
HANDLE ProcessId;
HANDLE ThreadId;
HANDLE ThreadHandle;
PPH_SYMBOL_PROVIDER SymbolProvider;
BOOLEAN CustomWalk;
} Initializing;
struct
{
PPH_THREAD_STACK_FRAME StackFrame;
PPH_STRING Symbol;
} ResolveSymbol;
struct
{
PPH_THREAD_STACK_FRAME StackFrame;
PPH_STRING_BUILDER StringBuilder;
} GetTooltip;
struct
{
NTSTATUS Status;
HANDLE ThreadHandle;
HANDLE ProcessHandle;
PCLIENT_ID ClientId;
ULONG Flags;
PPH_PLUGIN_WALK_THREAD_STACK_CALLBACK Callback;
PVOID CallbackContext;
} WalkStack;
} u;
} PH_PLUGIN_THREAD_STACK_CONTROL, *PPH_PLUGIN_THREAD_STACK_CONTROL;
typedef enum _PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL_TYPE
{
PluginMemoryItemListInitialized,
PluginMemoryItemListMaximum
} PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL_TYPE;
typedef struct _PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL
{
PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL_TYPE Type;
union
{
struct
{
PPH_MEMORY_ITEM_LIST List;
} Initialized;
} u;
} PH_PLUGIN_MEMORY_ITEM_LIST_CONTROL, *PPH_PLUGIN_MEMORY_ITEM_LIST_CONTROL;
typedef PPH_SYSINFO_SECTION (NTAPI *PPH_SYSINFO_CREATE_SECTION)(
_In_ PPH_SYSINFO_SECTION Template
);
typedef PPH_SYSINFO_SECTION (NTAPI *PPH_SYSINFO_FIND_SECTION)(
_In_ PPH_STRINGREF Name
);
typedef VOID (NTAPI *PPH_SYSINFO_ENTER_SECTION_VIEW)(
_In_ PPH_SYSINFO_SECTION NewSection
);
typedef VOID (NTAPI *PPH_SYSINFO_RESTORE_SUMMARY_VIEW)(
VOID
);
typedef struct _PH_PLUGIN_SYSINFO_POINTERS
{
HWND WindowHandle;
PPH_SYSINFO_CREATE_SECTION CreateSection;
PPH_SYSINFO_FIND_SECTION FindSection;
PPH_SYSINFO_ENTER_SECTION_VIEW EnterSectionView;
PPH_SYSINFO_RESTORE_SUMMARY_VIEW RestoreSummaryView;
} PH_PLUGIN_SYSINFO_POINTERS, *PPH_PLUGIN_SYSINFO_POINTERS;
typedef PPH_MINIINFO_SECTION (NTAPI *PPH_MINIINFO_CREATE_SECTION)(
_In_ PPH_MINIINFO_SECTION Template
);
typedef PPH_MINIINFO_SECTION (NTAPI *PPH_MINIINFO_FIND_SECTION)(
_In_ PPH_STRINGREF Name
);
typedef PPH_MINIINFO_LIST_SECTION (NTAPI *PPH_MINIINFO_CREATE_LIST_SECTION)(
_In_ PWSTR Name,
_In_ ULONG Flags,
_In_ PPH_MINIINFO_LIST_SECTION Template
);
typedef struct _PH_PLUGIN_MINIINFO_POINTERS
{
HWND WindowHandle;
PPH_MINIINFO_CREATE_SECTION CreateSection;
PPH_MINIINFO_FIND_SECTION FindSection;
PPH_MINIINFO_CREATE_LIST_SECTION CreateListSection;
} PH_PLUGIN_MINIINFO_POINTERS, *PPH_PLUGIN_MINIINFO_POINTERS;
typedef struct _PH_PLUGIN_TREENEW_MESSAGE
{
HWND TreeNewHandle;
PH_TREENEW_MESSAGE Message;
PVOID Parameter1;
PVOID Parameter2;
ULONG SubId;
PVOID Context;
} PH_PLUGIN_TREENEW_MESSAGE, *PPH_PLUGIN_TREENEW_MESSAGE;
typedef LONG (NTAPI *PPH_PLUGIN_TREENEW_SORT_FUNCTION)(
_In_ PVOID Node1,
_In_ PVOID Node2,
_In_ ULONG SubId,
_In_ PVOID Context
);
typedef NTSTATUS (NTAPI *PPHSVC_SERVER_PROBE_BUFFER)(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ ULONG Alignment,
_In_ BOOLEAN AllowNull,
_Out_ PVOID *Pointer
);
typedef NTSTATUS (NTAPI *PPHSVC_SERVER_CAPTURE_BUFFER)(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_Out_ PVOID *CapturedBuffer
);
typedef NTSTATUS (NTAPI *PPHSVC_SERVER_CAPTURE_STRING)(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_Out_ PPH_STRING *CapturedString
);
typedef struct _PH_PLUGIN_PHSVC_REQUEST
{
ULONG SubId;
NTSTATUS ReturnStatus;
PVOID InBuffer;
ULONG InLength;
PVOID OutBuffer;
ULONG OutLength;
PPHSVC_SERVER_PROBE_BUFFER ProbeBuffer;
PPHSVC_SERVER_CAPTURE_BUFFER CaptureBuffer;
PPHSVC_SERVER_CAPTURE_STRING CaptureString;
} PH_PLUGIN_PHSVC_REQUEST, *PPH_PLUGIN_PHSVC_REQUEST;
typedef VOID (NTAPI *PPHSVC_CLIENT_FREE_HEAP)(
_In_ PVOID Memory
);
typedef PVOID (NTAPI *PPHSVC_CLIENT_CREATE_STRING)(
_In_opt_ PVOID String,
_In_ SIZE_T Length,
_Out_ PPH_RELATIVE_STRINGREF StringRef
);
typedef struct _PH_PLUGIN_PHSVC_CLIENT
{
HANDLE ServerProcessId;
PPHSVC_CLIENT_FREE_HEAP FreeHeap;
PPHSVC_CLIENT_CREATE_STRING CreateString;
} PH_PLUGIN_PHSVC_CLIENT, *PPH_PLUGIN_PHSVC_CLIENT;
// Plugin structures
typedef struct _PH_PLUGIN_INFORMATION
{
PWSTR DisplayName;
PWSTR Author;
PWSTR Description;
PWSTR Url;
BOOLEAN HasOptions;
BOOLEAN Reserved1[3];
PVOID Interface;
} PH_PLUGIN_INFORMATION, *PPH_PLUGIN_INFORMATION;
#define PH_PLUGIN_FLAG_RESERVED 0x1
// end_phapppub
// begin_phapppub
typedef struct _PH_PLUGIN
{
// Public
PH_AVL_LINKS Links;
PVOID Reserved;
PVOID DllBase;
// end_phapppub
// Private
PPH_STRING FileName;
ULONG Flags;
PH_STRINGREF Name;
PH_PLUGIN_INFORMATION Information;
PH_CALLBACK Callbacks[PluginCallbackMaximum];
PH_EM_APP_CONTEXT AppContext;
// begin_phapppub
} PH_PLUGIN, *PPH_PLUGIN;
// end_phapppub
// begin_phapppub
// Plugin API
PHAPPAPI
PPH_PLUGIN
NTAPI
PhRegisterPlugin(
_In_ PWSTR Name,
_In_ PVOID DllBase,
_Out_opt_ PPH_PLUGIN_INFORMATION *Information
);
PHAPPAPI
PPH_PLUGIN
NTAPI
PhFindPlugin(
_In_ PWSTR Name
);
PHAPPAPI
PPH_PLUGIN_INFORMATION
NTAPI
PhGetPluginInformation(
_In_ PPH_PLUGIN Plugin
);
PHAPPAPI
PPH_CALLBACK
NTAPI
PhGetPluginCallback(
_In_ PPH_PLUGIN Plugin,
_In_ PH_PLUGIN_CALLBACK Callback
);
PHAPPAPI
PPH_CALLBACK
NTAPI
PhGetGeneralCallback(
_In_ PH_GENERAL_CALLBACK Callback
);
PHAPPAPI
ULONG
NTAPI
PhPluginReserveIds(
_In_ ULONG Count
);
typedef VOID (NTAPI *PPH_PLUGIN_MENU_ITEM_DELETE_FUNCTION)(
_In_ struct _PH_PLUGIN_MENU_ITEM *MenuItem
);
typedef struct _PH_PLUGIN_MENU_ITEM
{
PPH_PLUGIN Plugin;
ULONG Id;
ULONG Reserved1;
PVOID Context;
HWND OwnerWindow; // valid only when the menu item is chosen
PVOID Reserved2;
PVOID Reserved3;
PPH_PLUGIN_MENU_ITEM_DELETE_FUNCTION DeleteFunction; // valid only for EMENU-based menu items
} PH_PLUGIN_MENU_ITEM, *PPH_PLUGIN_MENU_ITEM;
// Location
#define PH_MENU_ITEM_LOCATION_VIEW 1
#define PH_MENU_ITEM_LOCATION_TOOLS 2
// Id flags (non-functional)
#define PH_MENU_ITEM_SUB_MENU 0x80000000
#define PH_MENU_ITEM_RETURN_MENU 0x40000000
#define PH_MENU_ITEM_VALID_FLAGS 0xc0000000
PHAPPAPI
ULONG_PTR
NTAPI
PhPluginAddMenuItem(
_In_ PPH_PLUGIN Plugin,
_In_ ULONG_PTR Location,
_In_opt_ PWSTR InsertAfter,
_In_ ULONG Id,
_In_ PWSTR Text,
_In_opt_ PVOID Context
);
typedef struct _PH_PLUGIN_SYSTEM_STATISTICS
{
PSYSTEM_PERFORMANCE_INFORMATION Performance;
ULONG NumberOfProcesses;
ULONG NumberOfThreads;
ULONG NumberOfHandles;
FLOAT CpuKernelUsage;
FLOAT CpuUserUsage;
PH_UINT64_DELTA IoReadDelta;
PH_UINT64_DELTA IoWriteDelta;
PH_UINT64_DELTA IoOtherDelta;
ULONG CommitPages;
ULONG PhysicalPages;
HANDLE MaxCpuProcessId;
HANDLE MaxIoProcessId;
PPH_CIRCULAR_BUFFER_FLOAT CpuKernelHistory;
PPH_CIRCULAR_BUFFER_FLOAT CpuUserHistory;
PPH_CIRCULAR_BUFFER_FLOAT *CpusKernelHistory;
PPH_CIRCULAR_BUFFER_FLOAT *CpusUserHistory;
PPH_CIRCULAR_BUFFER_ULONG64 IoReadHistory;
PPH_CIRCULAR_BUFFER_ULONG64 IoWriteHistory;
PPH_CIRCULAR_BUFFER_ULONG64 IoOtherHistory;
PPH_CIRCULAR_BUFFER_ULONG CommitHistory;
PPH_CIRCULAR_BUFFER_ULONG PhysicalHistory;
PPH_CIRCULAR_BUFFER_ULONG MaxCpuHistory; // ID of max. CPU process
PPH_CIRCULAR_BUFFER_ULONG MaxIoHistory; // ID of max. I/O process
PPH_CIRCULAR_BUFFER_FLOAT MaxCpuUsageHistory;
PPH_CIRCULAR_BUFFER_ULONG64 MaxIoReadOtherHistory;
PPH_CIRCULAR_BUFFER_ULONG64 MaxIoWriteHistory;
} PH_PLUGIN_SYSTEM_STATISTICS, *PPH_PLUGIN_SYSTEM_STATISTICS;
PHAPPAPI
VOID
NTAPI
PhPluginGetSystemStatistics(
_Out_ PPH_PLUGIN_SYSTEM_STATISTICS Statistics
);
PHAPPAPI
PPH_EMENU_ITEM
NTAPI
PhPluginCreateEMenuItem(
_In_ PPH_PLUGIN Plugin,
_In_ ULONG Flags,
_In_ ULONG Id,
_In_ PWSTR Text,
_In_opt_ PVOID Context
);
PHAPPAPI
BOOLEAN
NTAPI
PhPluginAddMenuHook(
_Inout_ PPH_PLUGIN_MENU_INFORMATION MenuInfo,
_In_ PPH_PLUGIN Plugin,
_In_opt_ PVOID Context
);
// end_phapppub
VOID
NTAPI
PhPluginInitializeMenuInfo(
_Out_ PPH_PLUGIN_MENU_INFORMATION MenuInfo,
_In_opt_ PPH_EMENU Menu,
_In_ HWND OwnerWindow,
_In_ ULONG Flags
);
BOOLEAN
NTAPI
PhPluginTriggerEMenuItem(
_In_ PPH_PLUGIN_MENU_INFORMATION MenuInfo,
_In_ PPH_EMENU_ITEM Item
);
// begin_phapppub
PHAPPAPI
BOOLEAN
NTAPI
PhPluginAddTreeNewColumn(
_In_ PPH_PLUGIN Plugin,
_In_ PVOID CmData,
_In_ PPH_TREENEW_COLUMN Column,
_In_ ULONG SubId,
_In_opt_ PVOID Context,
_In_opt_ PPH_PLUGIN_TREENEW_SORT_FUNCTION SortFunction
);
PHAPPAPI
VOID
NTAPI
PhPluginSetObjectExtension(
_In_ PPH_PLUGIN Plugin,
_In_ PH_EM_OBJECT_TYPE ObjectType,
_In_ ULONG ExtensionSize,
_In_opt_ PPH_EM_OBJECT_CALLBACK CreateCallback,
_In_opt_ PPH_EM_OBJECT_CALLBACK DeleteCallback
);
PHAPPAPI
PVOID
NTAPI
PhPluginGetObjectExtension(
_In_ PPH_PLUGIN Plugin,
_In_ PVOID Object,
_In_ PH_EM_OBJECT_TYPE ObjectType
);
PHAPPAPI
struct _PH_NF_ICON *
NTAPI
PhPluginRegisterIcon(
_In_ PPH_PLUGIN Plugin,
_In_ ULONG SubId,
_In_opt_ PVOID Context,
_In_ PWSTR Text,
_In_ ULONG Flags,
_In_ struct _PH_NF_ICON_REGISTRATION_DATA *RegistrationData
);
PHAPPAPI
VOID
NTAPI
PhPluginEnableTreeNewNotify(
_In_ PPH_PLUGIN Plugin,
_In_ PVOID CmData
);
PHAPPAPI
BOOLEAN
NTAPI
PhPluginQueryPhSvc(
_Out_ PPH_PLUGIN_PHSVC_CLIENT Client
);
PHAPPAPI
NTSTATUS
NTAPI
PhPluginCallPhSvc(
_In_ PPH_PLUGIN Plugin,
_In_ ULONG SubId,
_In_reads_bytes_opt_(InLength) PVOID InBuffer,
_In_ ULONG InLength,
_Out_writes_bytes_opt_(OutLength) PVOID OutBuffer,
_In_ ULONG OutLength
);
// end_phapppub
#endif

View File

@ -0,0 +1,238 @@
#ifndef PH_PHSVC_H
#define PH_PHSVC_H
#include <phsvcapi.h>
#define PHSVC_SHARED_SECTION_SIZE (512 * 1024)
// svcmain
typedef struct _PHSVC_STOP
{
BOOLEAN Stop;
HANDLE Event1;
HANDLE Event2;
} PHSVC_STOP, *PPHSVC_STOP;
NTSTATUS PhSvcMain(
_In_opt_ PUNICODE_STRING PortName,
_In_opt_ PLARGE_INTEGER Timeout,
_Inout_opt_ PPHSVC_STOP Stop
);
VOID PhSvcStop(
_Inout_ PPHSVC_STOP Stop
);
// svcclient
typedef struct _PHSVC_CLIENT
{
LIST_ENTRY ListEntry;
PH_EVENT ReadyEvent;
CLIENT_ID ClientId;
HANDLE PortHandle;
PVOID ClientViewBase;
PVOID ClientViewLimit;
} PHSVC_CLIENT, *PPHSVC_CLIENT;
NTSTATUS PhSvcClientInitialization(
VOID
);
PPHSVC_CLIENT PhSvcCreateClient(
_In_opt_ PCLIENT_ID ClientId
);
PPHSVC_CLIENT PhSvcReferenceClientByClientId(
_In_ PCLIENT_ID ClientId
);
PPHSVC_CLIENT PhSvcGetCurrentClient(
VOID
);
BOOLEAN PhSvcAttachClient(
_In_ PPHSVC_CLIENT Client
);
VOID PhSvcDetachClient(
_In_ PPHSVC_CLIENT Client
);
// svcapiport
typedef struct _PHSVC_THREAD_CONTEXT
{
PPHSVC_CLIENT CurrentClient;
PPHSVC_CLIENT OldClient;
} PHSVC_THREAD_CONTEXT, *PPHSVC_THREAD_CONTEXT;
NTSTATUS PhSvcApiPortInitialization(
_In_ PUNICODE_STRING PortName
);
PPHSVC_THREAD_CONTEXT PhSvcGetCurrentThreadContext(
VOID
);
VOID PhSvcHandleConnectionRequest(
_In_ PPORT_MESSAGE PortMessage
);
// svcapi
NTSTATUS PhSvcApiInitialization(
VOID
);
typedef NTSTATUS (NTAPI *PPHSVC_API_PROCEDURE)(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
VOID PhSvcDispatchApiCall(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload,
_Out_ PHANDLE ReplyPortHandle
);
PVOID PhSvcValidateString(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ ULONG Alignment
);
NTSTATUS PhSvcProbeBuffer(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ ULONG Alignment,
_In_ BOOLEAN AllowNull,
_Out_ PVOID *Pointer
);
NTSTATUS PhSvcCaptureBuffer(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_Out_ PVOID *CapturedBuffer
);
NTSTATUS PhSvcCaptureString(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_Out_ PPH_STRING *CapturedString
);
NTSTATUS PhSvcCaptureSid(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_Out_ PSID *CapturedSid
);
NTSTATUS PhSvcCaptureSecurityDescriptor(
_In_ PPH_RELATIVE_STRINGREF String,
_In_ BOOLEAN AllowNull,
_In_ SECURITY_INFORMATION RequiredInformation,
_Out_ PSECURITY_DESCRIPTOR *CapturedSecurityDescriptor
);
NTSTATUS PhSvcApiDefault(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiPlugin(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiExecuteRunAsCommand(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiUnloadDriver(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiControlProcess(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiControlService(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiCreateService(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiChangeServiceConfig(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiChangeServiceConfig2(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiSetTcpEntry(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiControlThread(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiAddAccountRight(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiInvokeRunAsService(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiIssueMemoryListCommand(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiPostMessage(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiSendMessage(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiCreateProcessIgnoreIfeoDebugger(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiSetServiceSecurity(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiLoadDbgHelp(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
NTSTATUS PhSvcApiWriteMiniDumpProcess(
_In_ PPHSVC_CLIENT Client,
_Inout_ PPHSVC_API_PAYLOAD Payload
);
#endif

View File

@ -0,0 +1,310 @@
#ifndef PH_PHSVCAPI_H
#define PH_PHSVCAPI_H
#define PHSVC_PORT_NAME (L"\\BaseNamedObjects\\PhSvcApiPort")
#define PHSVC_WOW64_PORT_NAME (L"\\BaseNamedObjects\\PhSvcWow64ApiPort")
typedef enum _PHSVC_API_NUMBER
{
PhSvcPluginApiNumber = 1,
PhSvcExecuteRunAsCommandApiNumber = 2,
PhSvcUnloadDriverApiNumber = 3,
PhSvcControlProcessApiNumber = 4,
PhSvcControlServiceApiNumber = 5,
PhSvcCreateServiceApiNumber = 6,
PhSvcChangeServiceConfigApiNumber = 7,
PhSvcChangeServiceConfig2ApiNumber = 8,
PhSvcSetTcpEntryApiNumber = 9,
PhSvcControlThreadApiNumber = 10,
PhSvcAddAccountRightApiNumber = 11,
PhSvcInvokeRunAsServiceApiNumber = 12,
PhSvcIssueMemoryListCommandApiNumber = 13,
PhSvcPostMessageApiNumber = 14,
PhSvcSendMessageApiNumber = 15,
PhSvcCreateProcessIgnoreIfeoDebuggerApiNumber = 16,
PhSvcSetServiceSecurityApiNumber = 17,
PhSvcLoadDbgHelpApiNumber = 18, // WOW64 compatible
PhSvcWriteMiniDumpProcessApiNumber = 19, // WOW64 compatible
PhSvcMaximumApiNumber
} PHSVC_API_NUMBER, *PPHSVC_API_NUMBER;
typedef struct _PHSVC_API_CONNECTINFO
{
ULONG ServerProcessId;
} PHSVC_API_CONNECTINFO, *PPHSVC_API_CONNECTINFO;
typedef union _PHSVC_API_PLUGIN
{
struct
{
PH_RELATIVE_STRINGREF ApiId;
ULONG Data[30];
} i;
struct
{
ULONG Data[32];
} o;
} PHSVC_API_PLUGIN, *PPHSVC_API_PLUGIN;
typedef union _PHSVC_API_EXECUTERUNASCOMMAND
{
struct
{
ULONG ProcessId;
PH_RELATIVE_STRINGREF UserName;
PH_RELATIVE_STRINGREF Password;
ULONG LogonType;
ULONG SessionId;
PH_RELATIVE_STRINGREF CurrentDirectory;
PH_RELATIVE_STRINGREF CommandLine;
PH_RELATIVE_STRINGREF FileName;
PH_RELATIVE_STRINGREF DesktopName;
BOOLEAN UseLinkedToken;
PH_RELATIVE_STRINGREF ServiceName;
} i;
} PHSVC_API_EXECUTERUNASCOMMAND, *PPHSVC_API_EXECUTERUNASCOMMAND;
typedef union _PHSVC_API_UNLOADDRIVER
{
struct
{
PVOID BaseAddress;
PH_RELATIVE_STRINGREF Name;
} i;
} PHSVC_API_UNLOADDRIVER, *PPHSVC_API_UNLOADDRIVER;
typedef enum _PHSVC_API_CONTROLPROCESS_COMMAND
{
PhSvcControlProcessTerminate = 1,
PhSvcControlProcessSuspend,
PhSvcControlProcessResume,
PhSvcControlProcessPriority,
PhSvcControlProcessIoPriority
} PHSVC_API_CONTROLPROCESS_COMMAND;
typedef union _PHSVC_API_CONTROLPROCESS
{
struct
{
HANDLE ProcessId;
PHSVC_API_CONTROLPROCESS_COMMAND Command;
ULONG Argument;
} i;
} PHSVC_API_CONTROLPROCESS, *PPHSVC_API_CONTROLPROCESS;
typedef enum _PHSVC_API_CONTROLSERVICE_COMMAND
{
PhSvcControlServiceStart = 1,
PhSvcControlServiceContinue,
PhSvcControlServicePause,
PhSvcControlServiceStop,
PhSvcControlServiceDelete
} PHSVC_API_CONTROLSERVICE_COMMAND;
typedef union _PHSVC_API_CONTROLSERVICE
{
struct
{
PH_RELATIVE_STRINGREF ServiceName;
PHSVC_API_CONTROLSERVICE_COMMAND Command;
} i;
} PHSVC_API_CONTROLSERVICE, *PPHSVC_API_CONTROLSERVICE;
typedef union _PHSVC_API_CREATESERVICE
{
struct
{
// ServiceName is the only required string.
PH_RELATIVE_STRINGREF ServiceName;
PH_RELATIVE_STRINGREF DisplayName;
ULONG ServiceType;
ULONG StartType;
ULONG ErrorControl;
PH_RELATIVE_STRINGREF BinaryPathName;
PH_RELATIVE_STRINGREF LoadOrderGroup;
PH_RELATIVE_STRINGREF Dependencies;
PH_RELATIVE_STRINGREF ServiceStartName;
PH_RELATIVE_STRINGREF Password;
BOOLEAN TagIdSpecified;
} i;
struct
{
ULONG TagId;
} o;
} PHSVC_API_CREATESERVICE, *PPHSVC_API_CREATESERVICE;
typedef union _PHSVC_API_CHANGESERVICECONFIG
{
struct
{
PH_RELATIVE_STRINGREF ServiceName;
ULONG ServiceType;
ULONG StartType;
ULONG ErrorControl;
PH_RELATIVE_STRINGREF BinaryPathName;
PH_RELATIVE_STRINGREF LoadOrderGroup;
PH_RELATIVE_STRINGREF Dependencies;
PH_RELATIVE_STRINGREF ServiceStartName;
PH_RELATIVE_STRINGREF Password;
PH_RELATIVE_STRINGREF DisplayName;
BOOLEAN TagIdSpecified;
} i;
struct
{
ULONG TagId;
} o;
} PHSVC_API_CHANGESERVICECONFIG, *PPHSVC_API_CHANGESERVICECONFIG;
typedef union _PHSVC_API_CHANGESERVICECONFIG2
{
struct
{
PH_RELATIVE_STRINGREF ServiceName;
ULONG InfoLevel;
PH_RELATIVE_STRINGREF Info;
} i;
} PHSVC_API_CHANGESERVICECONFIG2, *PPHSVC_API_CHANGESERVICECONFIG2;
typedef union _PHSVC_API_SETTCPENTRY
{
struct
{
ULONG State;
ULONG LocalAddress;
ULONG LocalPort;
ULONG RemoteAddress;
ULONG RemotePort;
} i;
} PHSVC_API_SETTCPENTRY, *PPHSVC_API_SETTCPENTRY;
typedef enum _PHSVC_API_CONTROLTHREAD_COMMAND
{
PhSvcControlThreadTerminate = 1,
PhSvcControlThreadSuspend,
PhSvcControlThreadResume,
PhSvcControlThreadIoPriority
} PHSVC_API_CONTROLTHREAD_COMMAND;
typedef union _PHSVC_API_CONTROLTHREAD
{
struct
{
HANDLE ThreadId;
PHSVC_API_CONTROLTHREAD_COMMAND Command;
ULONG Argument;
} i;
} PHSVC_API_CONTROLTHREAD, *PPHSVC_API_CONTROLTHREAD;
typedef union _PHSVC_API_ADDACCOUNTRIGHT
{
struct
{
PH_RELATIVE_STRINGREF AccountSid;
PH_RELATIVE_STRINGREF UserRight;
} i;
} PHSVC_API_ADDACCOUNTRIGHT, *PPHSVC_API_ADDACCOUNTRIGHT;
typedef union _PHSVC_API_ISSUEMEMORYLISTCOMMAND
{
struct
{
SYSTEM_MEMORY_LIST_COMMAND Command;
} i;
} PHSVC_API_ISSUEMEMORYLISTCOMMAND, *PPHSVC_API_ISSUEMEMORYLISTCOMMAND;
typedef union _PHSVC_API_POSTMESSAGE
{
struct
{
HWND hWnd;
UINT Msg;
WPARAM wParam;
LPARAM lParam;
} i;
} PHSVC_API_POSTMESSAGE, *PPHSVC_API_POSTMESSAGE;
typedef union _PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER
{
struct
{
PH_RELATIVE_STRINGREF FileName;
} i;
} PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER, *PPHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER;
typedef union _PHSVC_API_SETSERVICESECURITY
{
struct
{
PH_RELATIVE_STRINGREF ServiceName;
SECURITY_INFORMATION SecurityInformation;
PH_RELATIVE_STRINGREF SecurityDescriptor;
} i;
} PHSVC_API_SETSERVICESECURITY, *PPHSVC_API_SETSERVICESECURITY;
typedef union _PHSVC_API_LOADDBGHELP
{
struct
{
PH_RELATIVE_STRINGREF DbgHelpPath;
} i;
} PHSVC_API_LOADDBGHELP, *PPHSVC_API_LOADDBGHELP;
typedef union _PHSVC_API_WRITEMINIDUMPPROCESS
{
struct
{
ULONG LocalProcessHandle;
ULONG ProcessId;
ULONG LocalFileHandle;
ULONG DumpType;
} i;
} PHSVC_API_WRITEMINIDUMPPROCESS, *PPHSVC_API_WRITEMINIDUMPPROCESS;
typedef union _PHSVC_API_PAYLOAD
{
PHSVC_API_CONNECTINFO ConnectInfo;
struct
{
PHSVC_API_NUMBER ApiNumber;
NTSTATUS ReturnStatus;
union
{
PHSVC_API_PLUGIN Plugin;
PHSVC_API_EXECUTERUNASCOMMAND ExecuteRunAsCommand;
PHSVC_API_UNLOADDRIVER UnloadDriver;
PHSVC_API_CONTROLPROCESS ControlProcess;
PHSVC_API_CONTROLSERVICE ControlService;
PHSVC_API_CREATESERVICE CreateService;
PHSVC_API_CHANGESERVICECONFIG ChangeServiceConfig;
PHSVC_API_CHANGESERVICECONFIG2 ChangeServiceConfig2;
PHSVC_API_SETTCPENTRY SetTcpEntry;
PHSVC_API_CONTROLTHREAD ControlThread;
PHSVC_API_ADDACCOUNTRIGHT AddAccountRight;
PHSVC_API_ISSUEMEMORYLISTCOMMAND IssueMemoryListCommand;
PHSVC_API_POSTMESSAGE PostMessage;
PHSVC_API_CREATEPROCESSIGNOREIFEODEBUGGER CreateProcessIgnoreIfeoDebugger;
PHSVC_API_SETSERVICESECURITY SetServiceSecurity;
PHSVC_API_LOADDBGHELP LoadDbgHelp;
PHSVC_API_WRITEMINIDUMPPROCESS WriteMiniDumpProcess;
} u;
};
} PHSVC_API_PAYLOAD, *PPHSVC_API_PAYLOAD;
typedef struct _PHSVC_API_MSG
{
PORT_MESSAGE h;
PHSVC_API_PAYLOAD p;
} PHSVC_API_MSG, *PPHSVC_API_MSG;
typedef struct _PHSVC_API_MSG64
{
PORT_MESSAGE64 h;
PHSVC_API_PAYLOAD p;
} PHSVC_API_MSG64, *PPHSVC_API_MSG64;
C_ASSERT(FIELD_OFFSET(PHSVC_API_PAYLOAD, u) == 8);
C_ASSERT(sizeof(PHSVC_API_MSG) <= PORT_TOTAL_MAXIMUM_MESSAGE_LENGTH);
C_ASSERT(sizeof(PHSVC_API_MSG64) <= PORT_TOTAL_MAXIMUM_MESSAGE_LENGTH);
#endif

View File

@ -0,0 +1,155 @@
#ifndef PH_PHSVCCL_H
#define PH_PHSVCCL_H
#include <phsvcapi.h>
extern HANDLE PhSvcClServerProcessId;
NTSTATUS PhSvcConnectToServer(
_In_ PUNICODE_STRING PortName,
_In_opt_ SIZE_T PortSectionSize
);
VOID PhSvcDisconnectFromServer(
VOID
);
VOID PhSvcpFreeHeap(
_In_ PVOID Memory
);
PVOID PhSvcpCreateString(
_In_opt_ PVOID String,
_In_ SIZE_T Length,
_Out_ PPH_RELATIVE_STRINGREF StringRef
);
NTSTATUS PhSvcCallPlugin(
_In_ PPH_STRINGREF ApiId,
_In_reads_bytes_opt_(InLength) PVOID InBuffer,
_In_ ULONG InLength,
_Out_writes_bytes_opt_(OutLength) PVOID OutBuffer,
_In_ ULONG OutLength
);
NTSTATUS PhSvcCallExecuteRunAsCommand(
_In_ PPH_RUNAS_SERVICE_PARAMETERS Parameters
);
NTSTATUS PhSvcCallUnloadDriver(
_In_opt_ PVOID BaseAddress,
_In_opt_ PWSTR Name
);
NTSTATUS PhSvcCallControlProcess(
_In_ HANDLE ProcessId,
_In_ PHSVC_API_CONTROLPROCESS_COMMAND Command,
_In_ ULONG Argument
);
NTSTATUS PhSvcCallControlService(
_In_ PWSTR ServiceName,
_In_ PHSVC_API_CONTROLSERVICE_COMMAND Command
);
NTSTATUS PhSvcCallCreateService(
_In_ PWSTR ServiceName,
_In_opt_ PWSTR DisplayName,
_In_ ULONG ServiceType,
_In_ ULONG StartType,
_In_ ULONG ErrorControl,
_In_opt_ PWSTR BinaryPathName,
_In_opt_ PWSTR LoadOrderGroup,
_Out_opt_ PULONG TagId,
_In_opt_ PWSTR Dependencies,
_In_opt_ PWSTR ServiceStartName,
_In_opt_ PWSTR Password
);
// begin_phapppub
PHAPPAPI
NTSTATUS PhSvcCallChangeServiceConfig(
_In_ PWSTR ServiceName,
_In_ ULONG ServiceType,
_In_ ULONG StartType,
_In_ ULONG ErrorControl,
_In_opt_ PWSTR BinaryPathName,
_In_opt_ PWSTR LoadOrderGroup,
_Out_opt_ PULONG TagId,
_In_opt_ PWSTR Dependencies,
_In_opt_ PWSTR ServiceStartName,
_In_opt_ PWSTR Password,
_In_opt_ PWSTR DisplayName
);
PHAPPAPI
NTSTATUS PhSvcCallChangeServiceConfig2(
_In_ PWSTR ServiceName,
_In_ ULONG InfoLevel,
_In_ PVOID Info
);
// end_phapppub
NTSTATUS PhSvcCallSetTcpEntry(
_In_ PVOID TcpRow
);
NTSTATUS PhSvcCallControlThread(
_In_ HANDLE ThreadId,
_In_ PHSVC_API_CONTROLTHREAD_COMMAND Command,
_In_ ULONG Argument
);
NTSTATUS PhSvcCallAddAccountRight(
_In_ PSID AccountSid,
_In_ PUNICODE_STRING UserRight
);
NTSTATUS PhSvcCallInvokeRunAsService(
_In_ PPH_RUNAS_SERVICE_PARAMETERS Parameters
);
NTSTATUS PhSvcCallIssueMemoryListCommand(
_In_ SYSTEM_MEMORY_LIST_COMMAND Command
);
// begin_phapppub
PHAPPAPI
NTSTATUS PhSvcCallPostMessage(
_In_opt_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
PHAPPAPI
NTSTATUS PhSvcCallSendMessage(
_In_opt_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// end_phapppub
NTSTATUS PhSvcCallCreateProcessIgnoreIfeoDebugger(
_In_ PWSTR FileName
);
NTSTATUS PhSvcCallSetServiceSecurity(
_In_ PWSTR ServiceName,
_In_ SECURITY_INFORMATION SecurityInformation,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor
);
NTSTATUS PhSvcCallLoadDbgHelp(
_In_ PWSTR DbgHelpPath
);
NTSTATUS PhSvcCallWriteMiniDumpProcess(
_In_ HANDLE ProcessHandle,
_In_ HANDLE ProcessId,
_In_ HANDLE FileHandle,
_In_ ULONG DumpType
);
#endif

View File

@ -0,0 +1,213 @@
#ifndef PH_PHUISUP_H
#define PH_PHUISUP_H
// begin_phapppub
// Common state highlighting support
typedef struct _PH_SH_STATE
{
PH_ITEM_STATE State;
HANDLE StateListHandle;
ULONG TickCount;
} PH_SH_STATE, *PPH_SH_STATE;
// end_phapppub
FORCEINLINE VOID PhChangeShStateTn(
_Inout_ PPH_TREENEW_NODE Node,
_Inout_ PPH_SH_STATE ShState,
_Inout_ PPH_POINTER_LIST *StateList,
_In_ PH_ITEM_STATE NewState,
_In_ COLORREF NewTempBackColor,
_In_opt_ HWND TreeNewHandleForUpdate
)
{
if (!*StateList)
*StateList = PhCreatePointerList(4);
if (ShState->State == NormalItemState)
ShState->StateListHandle = PhAddItemPointerList(*StateList, Node);
ShState->TickCount = GetTickCount();
ShState->State = NewState;
Node->UseTempBackColor = TRUE;
Node->TempBackColor = NewTempBackColor;
if (TreeNewHandleForUpdate)
TreeNew_InvalidateNode(TreeNewHandleForUpdate, Node);
}
#define PH_TICK_SH_STATE_TN(NodeType, ShStateFieldName, StateList, RemoveFunction, HighlightingDuration, TreeNewHandleForUpdate, Invalidate, FullyInvalidated, ...) \
do { \
NodeType *node; \
ULONG enumerationKey = 0; \
ULONG tickCount; \
BOOLEAN preferFullInvalidate; \
HANDLE stateListHandle; \
BOOLEAN redrawDisabled = FALSE; \
BOOLEAN needsFullInvalidate = FALSE; \
\
if (!StateList || StateList->Count == 0) \
break; \
\
tickCount = GetTickCount(); \
preferFullInvalidate = StateList->Count > 8; \
\
while (PhEnumPointerList(StateList, &enumerationKey, &node)) \
{ \
if (PhRoundNumber(tickCount - node->ShStateFieldName.TickCount, 100) < (HighlightingDuration)) \
continue; \
\
stateListHandle = node->ShStateFieldName.StateListHandle; \
\
if (node->ShStateFieldName.State == NewItemState) \
{ \
node->ShStateFieldName.State = NormalItemState; \
((PPH_TREENEW_NODE)node)->UseTempBackColor = FALSE; \
if (Invalidate) \
{ \
if (preferFullInvalidate) \
{ \
needsFullInvalidate = TRUE; \
} \
else \
{ \
TreeNew_InvalidateNode(TreeNewHandleForUpdate, node); \
} \
} \
} \
else if (node->ShStateFieldName.State == RemovingItemState) \
{ \
if (TreeNewHandleForUpdate) \
{ \
if (!redrawDisabled) \
{ \
TreeNew_SetRedraw((TreeNewHandleForUpdate), FALSE); \
redrawDisabled = TRUE; \
} \
} \
\
RemoveFunction(node, __VA_ARGS__); \
needsFullInvalidate = TRUE; \
} \
\
PhRemoveItemPointerList(StateList, stateListHandle); \
} \
\
if (TreeNewHandleForUpdate) \
{ \
if (redrawDisabled) \
TreeNew_SetRedraw((TreeNewHandleForUpdate), TRUE); \
if (needsFullInvalidate) \
{ \
InvalidateRect((TreeNewHandleForUpdate), NULL, FALSE); \
if (FullyInvalidated) \
*((PBOOLEAN)FullyInvalidated) = TRUE; \
} \
} \
} while (0)
// Provider event queues
typedef enum _PH_PROVIDER_EVENT_TYPE
{
ProviderAddedEvent = 1,
ProviderModifiedEvent = 2,
ProviderRemovedEvent = 3
} PH_PROVIDER_EVENT_TYPE;
typedef struct _PH_PROVIDER_EVENT
{
ULONG_PTR TypeAndObject;
ULONG RunId;
} PH_PROVIDER_EVENT, *PPH_PROVIDER_EVENT;
#define PH_PROVIDER_EVENT_TYPE_MASK 0x3
#define PH_PROVIDER_EVENT_OBJECT_MASK (~(ULONG_PTR)0x3)
#define PH_PROVIDER_EVENT_TYPE(Event) ((ULONG)(Event).TypeAndObject & PH_PROVIDER_EVENT_TYPE_MASK)
#define PH_PROVIDER_EVENT_OBJECT(Event) ((PVOID)((Event).TypeAndObject & PH_PROVIDER_EVENT_OBJECT_MASK))
typedef struct _PH_PROVIDER_EVENT_QUEUE
{
PH_ARRAY Array;
PH_QUEUED_LOCK Lock;
} PH_PROVIDER_EVENT_QUEUE, *PPH_PROVIDER_EVENT_QUEUE;
FORCEINLINE VOID PhInitializeProviderEventQueue(
_Out_ PPH_PROVIDER_EVENT_QUEUE EventQueue,
_In_ SIZE_T InitialCapacity
)
{
PhInitializeArray(&EventQueue->Array, sizeof(PH_PROVIDER_EVENT), InitialCapacity);
PhInitializeQueuedLock(&EventQueue->Lock);
}
FORCEINLINE VOID PhDeleteProviderEventQueue(
_Inout_ PPH_PROVIDER_EVENT_QUEUE EventQueue
)
{
PPH_PROVIDER_EVENT events;
SIZE_T i;
events = EventQueue->Array.Items;
for (i = 0; i < EventQueue->Array.Count; i++)
{
if (PH_PROVIDER_EVENT_TYPE(events[i]) == ProviderAddedEvent)
PhDereferenceObject(PH_PROVIDER_EVENT_OBJECT(events[i]));
}
PhDeleteArray(&EventQueue->Array);
}
FORCEINLINE VOID PhPushProviderEventQueue(
_Inout_ PPH_PROVIDER_EVENT_QUEUE EventQueue,
_In_ PH_PROVIDER_EVENT_TYPE Type,
_In_opt_ PVOID Object,
_In_ ULONG RunId
)
{
PH_PROVIDER_EVENT event;
assert(!(PtrToUlong(Object) & PH_PROVIDER_EVENT_TYPE_MASK));
event.TypeAndObject = (ULONG_PTR)Object | Type;
event.RunId = RunId;
PhAcquireQueuedLockExclusive(&EventQueue->Lock);
PhAddItemArray(&EventQueue->Array, &event);
PhReleaseQueuedLockExclusive(&EventQueue->Lock);
}
FORCEINLINE PPH_PROVIDER_EVENT PhFlushProviderEventQueue(
_Inout_ PPH_PROVIDER_EVENT_QUEUE EventQueue,
_In_ ULONG UpToRunId,
_Out_ PULONG Count
)
{
PPH_PROVIDER_EVENT availableEvents;
PPH_PROVIDER_EVENT events = NULL;
SIZE_T count;
PhAcquireQueuedLockExclusive(&EventQueue->Lock);
availableEvents = EventQueue->Array.Items;
for (count = 0; count < EventQueue->Array.Count; count++)
{
if ((LONG)(UpToRunId - availableEvents[count].RunId) < 0)
break;
}
if (count != 0)
{
events = PhAllocateCopy(availableEvents, count * sizeof(PH_PROVIDER_EVENT));
PhRemoveItemsArray(&EventQueue->Array, 0, count);
}
PhReleaseQueuedLockExclusive(&EventQueue->Lock);
*Count = (ULONG)count;
return events;
}
#endif

View File

@ -0,0 +1,32 @@
#ifndef PH_PROCGRP_H
#define PH_PROCGRP_H
// begin_phapppub
typedef struct _PH_PROCESS_GROUP
{
PPH_PROCESS_ITEM Representative; // An element of Processes (no extra reference added)
PPH_LIST Processes; // List of PPH_PROCESS_ITEM
HWND WindowHandle; // Window handle of representative
} PH_PROCESS_GROUP, *PPH_PROCESS_GROUP;
// end_phapppub
typedef VOID (NTAPI *PPH_SORT_LIST_FUNCTION)(
_In_ PPH_LIST List,
_In_opt_ PVOID Context
);
#define PH_GROUP_PROCESSES_DONT_GROUP 0x1
#define PH_GROUP_PROCESSES_FILE_PATH 0x2
PPH_LIST PhCreateProcessGroupList(
_In_opt_ PPH_SORT_LIST_FUNCTION SortListFunction, // Sort a list of PPH_PROCESS_NODE
_In_opt_ PVOID Context,
_In_ ULONG MaximumGroups,
_In_ ULONG Flags
);
VOID PhFreeProcessGroupList(
_In_ PPH_LIST List
);
#endif

View File

@ -0,0 +1,31 @@
#ifndef PH_PROCMITIGATION_H
#define PH_PROCMITIGATION_H
typedef struct _PH_PROCESS_MITIGATION_POLICY_ALL_INFORMATION
{
PVOID Pointers[MaxProcessMitigationPolicy];
PROCESS_MITIGATION_DEP_POLICY DEPPolicy;
PROCESS_MITIGATION_ASLR_POLICY ASLRPolicy;
PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY StrictHandleCheckPolicy;
PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY SystemCallDisablePolicy;
PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY ExtensionPointDisablePolicy;
PROCESS_MITIGATION_DYNAMIC_CODE_POLICY DynamicCodePolicy;
PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY ControlFlowGuardPolicy;
PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY SignaturePolicy;
PROCESS_MITIGATION_FONT_DISABLE_POLICY FontDisablePolicy;
PROCESS_MITIGATION_IMAGE_LOAD_POLICY ImageLoadPolicy;
} PH_PROCESS_MITIGATION_POLICY_ALL_INFORMATION, *PPH_PROCESS_MITIGATION_POLICY_ALL_INFORMATION;
NTSTATUS PhGetProcessMitigationPolicy(
_In_ HANDLE ProcessHandle,
_Out_ PPH_PROCESS_MITIGATION_POLICY_ALL_INFORMATION Information
);
BOOLEAN PhDescribeProcessMitigationPolicy(
_In_ PROCESS_MITIGATION_POLICY Policy,
_In_ PVOID Data,
_Out_opt_ PPH_STRING *ShortDescription,
_Out_opt_ PPH_STRING *LongDescription
);
#endif

View File

@ -0,0 +1,341 @@
#ifndef PH_PROCPRPP_H
#define PH_PROCPRPP_H
#include <thrdlist.h>
#include <modlist.h>
#include <hndllist.h>
#include <memlist.h>
#include <memprv.h>
typedef struct _PH_PROCESS_PROPSHEETCONTEXT
{
WNDPROC OldWndProc;
PH_LAYOUT_MANAGER LayoutManager;
PPH_LAYOUT_ITEM TabPageItem;
BOOLEAN LayoutInitialized;
} PH_PROCESS_PROPSHEETCONTEXT, *PPH_PROCESS_PROPSHEETCONTEXT;
VOID NTAPI PhpProcessPropContextDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
);
INT CALLBACK PhpPropSheetProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ LPARAM lParam
);
PPH_PROCESS_PROPSHEETCONTEXT PhpGetPropSheetContext(
_In_ HWND hwnd
);
LRESULT CALLBACK PhpPropSheetWndProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID NTAPI PhpProcessPropPageContextDeleteProcedure(
_In_ PVOID Object,
_In_ ULONG Flags
);
INT CALLBACK PhpStandardPropPageProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ LPPROPSHEETPAGE ppsp
);
FORCEINLINE BOOLEAN PhpPropPageDlgProcHeader(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ LPARAM lParam,
_Out_ LPPROPSHEETPAGE *PropSheetPage,
_Out_ PPH_PROCESS_PROPPAGECONTEXT *PropPageContext,
_Out_ PPH_PROCESS_ITEM *ProcessItem
)
{
LPPROPSHEETPAGE propSheetPage;
PPH_PROCESS_PROPPAGECONTEXT propPageContext;
if (uMsg == WM_INITDIALOG)
{
// Save the context.
SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)lParam);
}
propSheetPage = (LPPROPSHEETPAGE)GetProp(hwndDlg, PhMakeContextAtom());
if (!propSheetPage)
return FALSE;
*PropSheetPage = propSheetPage;
*PropPageContext = propPageContext = (PPH_PROCESS_PROPPAGECONTEXT)propSheetPage->lParam;
*ProcessItem = propPageContext->PropContext->ProcessItem;
return TRUE;
}
FORCEINLINE VOID PhpPropPageDlgProcDestroy(
_In_ HWND hwndDlg
)
{
RemoveProp(hwndDlg, PhMakeContextAtom());
}
#define SET_BUTTON_ICON(Id, Icon) \
SendMessage(GetDlgItem(hwndDlg, (Id)), BM_SETIMAGE, IMAGE_ICON, (LPARAM)(Icon))
INT_PTR CALLBACK PhpProcessGeneralDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessStatisticsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessPerformanceDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessThreadsDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
NTSTATUS NTAPI PhpOpenProcessTokenForPage(
_Out_ PHANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ PVOID Context
);
INT_PTR CALLBACK PhpProcessTokenHookProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessModulesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessMemoryDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessEnvironmentDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessHandlesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
NTSTATUS NTAPI PhpOpenProcessJobForPage(
_Out_ PHANDLE Handle,
_In_ ACCESS_MASK DesiredAccess,
_In_opt_ PVOID Context
);
INT_PTR CALLBACK PhpProcessJobHookProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhpProcessServicesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
extern PH_STRINGREF PhpLoadingText;
#define WM_PH_THREADS_UPDATED (WM_APP + 200)
#define WM_PH_THREAD_SELECTION_CHANGED (WM_APP + 201)
// begin_phapppub
typedef struct _PH_THREADS_CONTEXT
{
PPH_THREAD_PROVIDER Provider;
PH_CALLBACK_REGISTRATION ProviderRegistration;
PH_CALLBACK_REGISTRATION AddedEventRegistration;
PH_CALLBACK_REGISTRATION ModifiedEventRegistration;
PH_CALLBACK_REGISTRATION RemovedEventRegistration;
PH_CALLBACK_REGISTRATION UpdatedEventRegistration;
PH_CALLBACK_REGISTRATION LoadingStateChangedEventRegistration;
HWND WindowHandle;
// end_phapppub
union
{
PH_THREAD_LIST_CONTEXT ListContext;
struct
{
HWND Private; // phapppub
HWND TreeNewHandle; // phapppub
} PublicUse;
};
PH_PROVIDER_EVENT_QUEUE EventQueue;
// begin_phapppub
} PH_THREADS_CONTEXT, *PPH_THREADS_CONTEXT;
// end_phapppub
#define WM_PH_MODULES_UPDATED (WM_APP + 210)
// begin_phapppub
typedef struct _PH_MODULES_CONTEXT
{
PPH_MODULE_PROVIDER Provider;
PH_PROVIDER_REGISTRATION ProviderRegistration;
PH_CALLBACK_REGISTRATION AddedEventRegistration;
PH_CALLBACK_REGISTRATION ModifiedEventRegistration;
PH_CALLBACK_REGISTRATION RemovedEventRegistration;
PH_CALLBACK_REGISTRATION UpdatedEventRegistration;
HWND WindowHandle;
// end_phapppub
union
{
PH_MODULE_LIST_CONTEXT ListContext;
struct
{
HWND Private; // phapppub
HWND TreeNewHandle; // phapppub
} PublicUse;
};
PH_PROVIDER_EVENT_QUEUE EventQueue;
NTSTATUS LastRunStatus;
PPH_STRING ErrorMessage;
// begin_phapppub
} PH_MODULES_CONTEXT, *PPH_MODULES_CONTEXT;
// end_phapppub
#define WM_PH_HANDLES_UPDATED (WM_APP + 220)
// begin_phapppub
typedef struct _PH_HANDLES_CONTEXT
{
PPH_HANDLE_PROVIDER Provider;
PH_PROVIDER_REGISTRATION ProviderRegistration;
PH_CALLBACK_REGISTRATION AddedEventRegistration;
PH_CALLBACK_REGISTRATION ModifiedEventRegistration;
PH_CALLBACK_REGISTRATION RemovedEventRegistration;
PH_CALLBACK_REGISTRATION UpdatedEventRegistration;
HWND WindowHandle;
// end_phapppub
union
{
PH_HANDLE_LIST_CONTEXT ListContext;
struct
{
HWND Private; // phapppub
HWND TreeNewHandle; // phapppub
} PublicUse;
};
PH_PROVIDER_EVENT_QUEUE EventQueue;
BOOLEAN SelectedHandleProtected;
BOOLEAN SelectedHandleInherit;
NTSTATUS LastRunStatus;
PPH_STRING ErrorMessage;
// begin_phapppub
} PH_HANDLES_CONTEXT, *PPH_HANDLES_CONTEXT;
// end_phapppub
// begin_phapppub
typedef struct _PH_MEMORY_CONTEXT
{
HANDLE ProcessId;
HWND WindowHandle;
// end_phapppub
union
{
PH_MEMORY_LIST_CONTEXT ListContext;
struct
{
HWND Private; // phapppub
HWND TreeNewHandle; // phapppub
} PublicUse;
};
PH_MEMORY_ITEM_LIST MemoryItemList;
BOOLEAN MemoryItemListValid;
NTSTATUS LastRunStatus;
PPH_STRING ErrorMessage;
// begin_phapppub
} PH_MEMORY_CONTEXT, *PPH_MEMORY_CONTEXT;
// end_phapppub
#define WM_PH_STATISTICS_UPDATE (WM_APP + 231)
typedef struct _PH_STATISTICS_CONTEXT
{
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
HWND WindowHandle;
BOOLEAN Enabled;
HANDLE ProcessHandle;
} PH_STATISTICS_CONTEXT, *PPH_STATISTICS_CONTEXT;
#define WM_PH_PERFORMANCE_UPDATE (WM_APP + 241)
typedef struct _PH_PERFORMANCE_CONTEXT
{
PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
HWND WindowHandle;
PH_GRAPH_STATE CpuGraphState;
PH_GRAPH_STATE PrivateGraphState;
PH_GRAPH_STATE IoGraphState;
HWND CpuGraphHandle;
HWND PrivateGraphHandle;
HWND IoGraphHandle;
} PH_PERFORMANCE_CONTEXT, *PPH_PERFORMANCE_CONTEXT;
typedef struct _PH_ENVIRONMENT_ITEM
{
PPH_STRING Name;
PPH_STRING Value;
} PH_ENVIRONMENT_ITEM, *PPH_ENVIRONMENT_ITEM;
typedef struct _PH_ENVIRONMENT_CONTEXT
{
HWND ListViewHandle;
PH_ARRAY Items;
} PH_ENVIRONMENT_CONTEXT, *PPH_ENVIRONMENT_CONTEXT;
#endif

View File

@ -0,0 +1,409 @@
#ifndef PH_PROCPRV_H
#define PH_PROCPRV_H
#define PH_RECORD_MAX_USAGE
#define PH_ENABLE_VERIFY_CACHE
extern PPH_OBJECT_TYPE PhProcessItemType;
PHAPPAPI extern PH_CALLBACK PhProcessAddedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhProcessModifiedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhProcessRemovedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhProcessesUpdatedEvent; // phapppub
extern PPH_LIST PhProcessRecordList;
extern PH_QUEUED_LOCK PhProcessRecordListLock;
extern ULONG PhStatisticsSampleCount;
extern BOOLEAN PhEnableProcessQueryStage2;
extern BOOLEAN PhEnablePurgeProcessRecords;
extern BOOLEAN PhEnableCycleCpuUsage;
extern PVOID PhProcessInformation; // only can be used if running on same thread as process provider
extern ULONG PhProcessInformationSequenceNumber;
extern SYSTEM_PERFORMANCE_INFORMATION PhPerfInformation;
extern PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PhCpuInformation;
extern SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION PhCpuTotals;
extern ULONG PhTotalProcesses;
extern ULONG PhTotalThreads;
extern ULONG PhTotalHandles;
extern ULONG64 PhCpuTotalCycleDelta;
extern PLARGE_INTEGER PhCpuIdleCycleTime; // cycle time for Idle
extern PLARGE_INTEGER PhCpuSystemCycleTime; // cycle time for DPCs and Interrupts
extern PH_UINT64_DELTA PhCpuIdleCycleDelta;
extern PH_UINT64_DELTA PhCpuSystemCycleDelta;
extern FLOAT PhCpuKernelUsage;
extern FLOAT PhCpuUserUsage;
extern PFLOAT PhCpusKernelUsage;
extern PFLOAT PhCpusUserUsage;
extern PH_UINT64_DELTA PhCpuKernelDelta;
extern PH_UINT64_DELTA PhCpuUserDelta;
extern PH_UINT64_DELTA PhCpuIdleDelta;
extern PPH_UINT64_DELTA PhCpusKernelDelta;
extern PPH_UINT64_DELTA PhCpusUserDelta;
extern PPH_UINT64_DELTA PhCpusIdleDelta;
extern PH_UINT64_DELTA PhIoReadDelta;
extern PH_UINT64_DELTA PhIoWriteDelta;
extern PH_UINT64_DELTA PhIoOtherDelta;
extern PH_CIRCULAR_BUFFER_FLOAT PhCpuKernelHistory;
extern PH_CIRCULAR_BUFFER_FLOAT PhCpuUserHistory;
//extern PH_CIRCULAR_BUFFER_FLOAT PhCpuOtherHistory;
extern PPH_CIRCULAR_BUFFER_FLOAT PhCpusKernelHistory;
extern PPH_CIRCULAR_BUFFER_FLOAT PhCpusUserHistory;
//extern PPH_CIRCULAR_BUFFER_FLOAT PhCpusOtherHistory;
extern PH_CIRCULAR_BUFFER_ULONG64 PhIoReadHistory;
extern PH_CIRCULAR_BUFFER_ULONG64 PhIoWriteHistory;
extern PH_CIRCULAR_BUFFER_ULONG64 PhIoOtherHistory;
extern PH_CIRCULAR_BUFFER_ULONG PhCommitHistory;
extern PH_CIRCULAR_BUFFER_ULONG PhPhysicalHistory;
extern PH_CIRCULAR_BUFFER_ULONG PhMaxCpuHistory;
extern PH_CIRCULAR_BUFFER_ULONG PhMaxIoHistory;
#ifdef PH_RECORD_MAX_USAGE
extern PH_CIRCULAR_BUFFER_FLOAT PhMaxCpuUsageHistory;
extern PH_CIRCULAR_BUFFER_ULONG64 PhMaxIoReadOtherHistory;
extern PH_CIRCULAR_BUFFER_ULONG64 PhMaxIoWriteHistory;
#endif
// begin_phapppub
#define DPCS_PROCESS_ID ((HANDLE)(LONG_PTR)-2)
#define INTERRUPTS_PROCESS_ID ((HANDLE)(LONG_PTR)-3)
// DPCs, Interrupts and System Idle Process are not real.
// Non-"real" processes can never be opened.
#define PH_IS_REAL_PROCESS_ID(ProcessId) ((LONG_PTR)(ProcessId) > 0)
// DPCs and Interrupts are fake, but System Idle Process is not.
#define PH_IS_FAKE_PROCESS_ID(ProcessId) ((LONG_PTR)(ProcessId) < 0)
// The process item has been removed.
#define PH_PROCESS_ITEM_REMOVED 0x1
// end_phapppub
#define PH_INTEGRITY_STR_LEN 10
#define PH_INTEGRITY_STR_LEN_1 (PH_INTEGRITY_STR_LEN + 1)
// begin_phapppub
typedef enum _VERIFY_RESULT VERIFY_RESULT;
typedef struct _PH_PROCESS_RECORD *PPH_PROCESS_RECORD;
typedef struct _PH_PROCESS_ITEM
{
PH_HASH_ENTRY HashEntry;
ULONG State;
PPH_PROCESS_RECORD Record;
// Basic
HANDLE ProcessId;
HANDLE ParentProcessId;
PPH_STRING ProcessName;
ULONG SessionId;
LARGE_INTEGER CreateTime;
// Handles
HANDLE QueryHandle;
// Parameters
PPH_STRING FileName;
PPH_STRING CommandLine;
// File
HICON SmallIcon;
HICON LargeIcon;
PH_IMAGE_VERSION_INFO VersionInfo;
// Security
PPH_STRING UserName;
TOKEN_ELEVATION_TYPE ElevationType;
MANDATORY_LEVEL IntegrityLevel;
PWSTR IntegrityString;
// Other
PPH_STRING JobName;
HANDLE ConsoleHostProcessId;
// Signature, Packed
VERIFY_RESULT VerifyResult;
PPH_STRING VerifySignerName;
ULONG ImportFunctions;
ULONG ImportModules;
// Flags
union
{
ULONG Flags;
struct
{
ULONG UpdateIsDotNet : 1;
ULONG IsBeingDebugged : 1;
ULONG IsDotNet : 1;
ULONG IsElevated : 1;
ULONG IsInJob : 1;
ULONG IsInSignificantJob : 1;
ULONG IsPacked : 1;
ULONG Reserved : 1;
ULONG IsSuspended : 1;
ULONG IsWow64 : 1;
ULONG IsImmersive : 1;
ULONG IsWow64Valid : 1;
ULONG IsPartiallySuspended : 1;
ULONG AddedEventSent : 1;
ULONG Spare : 18;
};
};
// Misc.
ULONG JustProcessed;
PH_EVENT Stage1Event;
PPH_POINTER_LIST ServiceList;
PH_QUEUED_LOCK ServiceListLock;
WCHAR ProcessIdString[PH_INT32_STR_LEN_1];
WCHAR ParentProcessIdString[PH_INT32_STR_LEN_1];
WCHAR SessionIdString[PH_INT32_STR_LEN_1];
// Dynamic
KPRIORITY BasePriority;
ULONG PriorityClass;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
ULONG NumberOfHandles;
ULONG NumberOfThreads;
FLOAT CpuUsage; // Below Windows 7, sum of kernel and user CPU usage; above Windows 7, cycle-based CPU usage.
FLOAT CpuKernelUsage;
FLOAT CpuUserUsage;
PH_UINT64_DELTA CpuKernelDelta;
PH_UINT64_DELTA CpuUserDelta;
PH_UINT64_DELTA IoReadDelta;
PH_UINT64_DELTA IoWriteDelta;
PH_UINT64_DELTA IoOtherDelta;
PH_UINT64_DELTA IoReadCountDelta;
PH_UINT64_DELTA IoWriteCountDelta;
PH_UINT64_DELTA IoOtherCountDelta;
PH_UINT32_DELTA ContextSwitchesDelta;
PH_UINT32_DELTA PageFaultsDelta;
PH_UINT64_DELTA CycleTimeDelta; // since WIN7
VM_COUNTERS_EX VmCounters;
IO_COUNTERS IoCounters;
SIZE_T WorkingSetPrivateSize; // since VISTA
ULONG PeakNumberOfThreads; // since WIN7
ULONG HardFaultCount; // since WIN7
ULONG SequenceNumber;
PH_CIRCULAR_BUFFER_FLOAT CpuKernelHistory;
PH_CIRCULAR_BUFFER_FLOAT CpuUserHistory;
PH_CIRCULAR_BUFFER_ULONG64 IoReadHistory;
PH_CIRCULAR_BUFFER_ULONG64 IoWriteHistory;
PH_CIRCULAR_BUFFER_ULONG64 IoOtherHistory;
PH_CIRCULAR_BUFFER_SIZE_T PrivateBytesHistory;
//PH_CIRCULAR_BUFFER_SIZE_T WorkingSetHistory;
// New fields
PH_UINTPTR_DELTA PrivateBytesDelta;
PPH_STRING PackageFullName;
PH_QUEUED_LOCK RemoveLock;
} PH_PROCESS_ITEM, *PPH_PROCESS_ITEM;
// end_phapppub
// begin_phapppub
// The process itself is dead.
#define PH_PROCESS_RECORD_DEAD 0x1
// An extra reference has been added to the process record for the statistics system.
#define PH_PROCESS_RECORD_STAT_REF 0x2
typedef struct _PH_PROCESS_RECORD
{
LIST_ENTRY ListEntry;
LONG RefCount;
ULONG Flags;
HANDLE ProcessId;
HANDLE ParentProcessId;
ULONG SessionId;
LARGE_INTEGER CreateTime;
LARGE_INTEGER ExitTime;
PPH_STRING ProcessName;
PPH_STRING FileName;
PPH_STRING CommandLine;
/*PPH_STRING UserName;*/
} PH_PROCESS_RECORD, *PPH_PROCESS_RECORD;
// end_phapppub
BOOLEAN PhProcessProviderInitialization(
VOID
);
// begin_phapppub
PHAPPAPI
PPH_STRING
NTAPI
PhGetClientIdName(
_In_ PCLIENT_ID ClientId
);
PHAPPAPI
PPH_STRING
NTAPI
PhGetClientIdNameEx(
_In_ PCLIENT_ID ClientId,
_In_opt_ PPH_STRING ProcessName
);
PHAPPAPI
PWSTR
NTAPI
PhGetProcessPriorityClassString(
_In_ ULONG PriorityClass
);
// end_phapppub
PPH_PROCESS_ITEM PhCreateProcessItem(
_In_ HANDLE ProcessId
);
// begin_phapppub
PHAPPAPI
PPH_PROCESS_ITEM
NTAPI
PhReferenceProcessItem(
_In_ HANDLE ProcessId
);
PHAPPAPI
VOID
NTAPI
PhEnumProcessItems(
_Out_opt_ PPH_PROCESS_ITEM **ProcessItems,
_Out_ PULONG NumberOfProcessItems
);
// end_phapppub
typedef struct _PH_VERIFY_FILE_INFO *PPH_VERIFY_FILE_INFO;
VERIFY_RESULT PhVerifyFileWithAdditionalCatalog(
_In_ PPH_VERIFY_FILE_INFO Information,
_In_opt_ PWSTR PackageFullName,
_Out_opt_ PPH_STRING *SignerName
);
VERIFY_RESULT PhVerifyFileCached(
_In_ PPH_STRING FileName,
_In_opt_ PWSTR PackageFullName,
_Out_opt_ PPH_STRING *SignerName,
_In_ BOOLEAN CachedOnly
);
// begin_phapppub
PHAPPAPI
BOOLEAN
NTAPI
PhGetStatisticsTime(
_In_opt_ PPH_PROCESS_ITEM ProcessItem,
_In_ ULONG Index,
_Out_ PLARGE_INTEGER Time
);
PHAPPAPI
PPH_STRING
NTAPI
PhGetStatisticsTimeString(
_In_opt_ PPH_PROCESS_ITEM ProcessItem,
_In_ ULONG Index
);
// end_phapppub
VOID PhFlushProcessQueryData(
_In_ BOOLEAN SendModifiedEvent
);
VOID PhProcessProviderUpdate(
_In_ PVOID Object
);
// begin_phapppub
PHAPPAPI
VOID
NTAPI
PhReferenceProcessRecord(
_In_ PPH_PROCESS_RECORD ProcessRecord
);
PHAPPAPI
BOOLEAN
NTAPI
PhReferenceProcessRecordSafe(
_In_ PPH_PROCESS_RECORD ProcessRecord
);
PHAPPAPI
VOID
NTAPI
PhReferenceProcessRecordForStatistics(
_In_ PPH_PROCESS_RECORD ProcessRecord
);
PHAPPAPI
VOID
NTAPI
PhDereferenceProcessRecord(
_In_ PPH_PROCESS_RECORD ProcessRecord
);
PHAPPAPI
PPH_PROCESS_RECORD
NTAPI
PhFindProcessRecord(
_In_opt_ HANDLE ProcessId,
_In_ PLARGE_INTEGER Time
);
// end_phapppub
VOID PhPurgeProcessRecords(
VOID
);
// begin_phapppub
PHAPPAPI
PPH_PROCESS_ITEM
NTAPI
PhReferenceProcessItemForParent(
_In_ HANDLE ParentProcessId,
_In_ HANDLE ProcessId,
_In_ PLARGE_INTEGER CreateTime
);
PHAPPAPI
PPH_PROCESS_ITEM
NTAPI
PhReferenceProcessItemForRecord(
_In_ PPH_PROCESS_RECORD Record
);
// end_phapppub
#endif

View File

@ -0,0 +1,362 @@
#ifndef PH_PROCTREE_H
#define PH_PROCTREE_H
#include <phuisup.h>
// Columns
// Default columns should go first
#define PHPRTLC_NAME 0
#define PHPRTLC_PID 1
#define PHPRTLC_CPU 2
#define PHPRTLC_IOTOTALRATE 3
#define PHPRTLC_PRIVATEBYTES 4
#define PHPRTLC_USERNAME 5
#define PHPRTLC_DESCRIPTION 6
#define PHPRTLC_COMPANYNAME 7
#define PHPRTLC_VERSION 8
#define PHPRTLC_FILENAME 9
#define PHPRTLC_COMMANDLINE 10
#define PHPRTLC_PEAKPRIVATEBYTES 11
#define PHPRTLC_WORKINGSET 12
#define PHPRTLC_PEAKWORKINGSET 13
#define PHPRTLC_PRIVATEWS 14
#define PHPRTLC_SHAREDWS 15
#define PHPRTLC_SHAREABLEWS 16
#define PHPRTLC_VIRTUALSIZE 17
#define PHPRTLC_PEAKVIRTUALSIZE 18
#define PHPRTLC_PAGEFAULTS 19
#define PHPRTLC_SESSIONID 20
#define PHPRTLC_PRIORITYCLASS 21
#define PHPRTLC_BASEPRIORITY 22
#define PHPRTLC_THREADS 23
#define PHPRTLC_HANDLES 24
#define PHPRTLC_GDIHANDLES 25
#define PHPRTLC_USERHANDLES 26
#define PHPRTLC_IORORATE 27
#define PHPRTLC_IOWRATE 28
#define PHPRTLC_INTEGRITY 29
#define PHPRTLC_IOPRIORITY 30
#define PHPRTLC_PAGEPRIORITY 31
#define PHPRTLC_STARTTIME 32
#define PHPRTLC_TOTALCPUTIME 33
#define PHPRTLC_KERNELCPUTIME 34
#define PHPRTLC_USERCPUTIME 35
#define PHPRTLC_VERIFICATIONSTATUS 36
#define PHPRTLC_VERIFIEDSIGNER 37
#define PHPRTLC_ASLR 38
#define PHPRTLC_RELATIVESTARTTIME 39
#define PHPRTLC_BITS 40
#define PHPRTLC_ELEVATION 41
#define PHPRTLC_WINDOWTITLE 42
#define PHPRTLC_WINDOWSTATUS 43
#define PHPRTLC_CYCLES 44
#define PHPRTLC_CYCLESDELTA 45
#define PHPRTLC_CPUHISTORY 46
#define PHPRTLC_PRIVATEBYTESHISTORY 47
#define PHPRTLC_IOHISTORY 48
#define PHPRTLC_DEP 49
#define PHPRTLC_VIRTUALIZED 50
#define PHPRTLC_CONTEXTSWITCHES 51
#define PHPRTLC_CONTEXTSWITCHESDELTA 52
#define PHPRTLC_PAGEFAULTSDELTA 53
#define PHPRTLC_IOREADS 54
#define PHPRTLC_IOWRITES 55
#define PHPRTLC_IOOTHER 56
#define PHPRTLC_IOREADBYTES 57
#define PHPRTLC_IOWRITEBYTES 58
#define PHPRTLC_IOOTHERBYTES 59
#define PHPRTLC_IOREADSDELTA 60
#define PHPRTLC_IOWRITESDELTA 61
#define PHPRTLC_IOOTHERDELTA 62
#define PHPRTLC_OSCONTEXT 63
#define PHPRTLC_PAGEDPOOL 64
#define PHPRTLC_PEAKPAGEDPOOL 65
#define PHPRTLC_NONPAGEDPOOL 66
#define PHPRTLC_PEAKNONPAGEDPOOL 67
#define PHPRTLC_MINIMUMWORKINGSET 68
#define PHPRTLC_MAXIMUMWORKINGSET 69
#define PHPRTLC_PRIVATEBYTESDELTA 70
#define PHPRTLC_SUBSYSTEM 71
#define PHPRTLC_PACKAGENAME 72
#define PHPRTLC_APPID 73
#define PHPRTLC_DPIAWARENESS 74
#define PHPRTLC_CFGUARD 75
#define PHPRTLC_TIMESTAMP 76
#define PHPRTLC_FILEMODIFIEDTIME 77
#define PHPRTLC_FILESIZE 78
#define PHPRTLC_MAXIMUM 79
#define PHPRTLC_IOGROUP_COUNT 9
#define PHPN_WSCOUNTERS 0x1
#define PHPN_GDIUSERHANDLES 0x2
#define PHPN_IOPAGEPRIORITY 0x4
#define PHPN_WINDOW 0x8
#define PHPN_DEPSTATUS 0x10
#define PHPN_TOKEN 0x20
#define PHPN_OSCONTEXT 0x40
#define PHPN_QUOTALIMITS 0x80
#define PHPN_IMAGE 0x100
#define PHPN_APPID 0x200
#define PHPN_DPIAWARENESS 0x400
#define PHPN_FILEATTRIBUTES 0x800
// begin_phapppub
typedef struct _PH_PROCESS_NODE
{
PH_TREENEW_NODE Node;
PH_HASH_ENTRY HashEntry;
PH_SH_STATE ShState;
HANDLE ProcessId;
PPH_PROCESS_ITEM ProcessItem;
struct _PH_PROCESS_NODE *Parent;
PPH_LIST Children;
// end_phapppub
PH_STRINGREF TextCache[PHPRTLC_MAXIMUM];
PH_STRINGREF DescriptionText;
// If the user has selected certain columns we need extra information that isn't retrieved by
// the process provider.
ULONG ValidMask;
// WS counters
PH_PROCESS_WS_COUNTERS WsCounters;
// GDI, USER handles
ULONG GdiHandles;
ULONG UserHandles;
// I/O, page priority
IO_PRIORITY_HINT IoPriority;
ULONG PagePriority;
// Window
HWND WindowHandle;
PPH_STRING WindowText;
BOOLEAN WindowHung;
// DEP status
ULONG DepStatus;
// Token
BOOLEAN VirtualizationAllowed;
BOOLEAN VirtualizationEnabled;
// OS Context
GUID OsContextGuid;
ULONG OsContextVersion;
// Quota limits
SIZE_T MinimumWorkingSetSize;
SIZE_T MaximumWorkingSetSize;
// Image
ULONG ImageTimeDateStamp;
USHORT ImageCharacteristics;
USHORT ImageReserved;
USHORT ImageSubsystem;
USHORT ImageDllCharacteristics;
// App ID
PPH_STRING AppIdText;
// Cycles (Vista only)
PH_UINT64_DELTA CyclesDelta;
// DPI awareness
ULONG DpiAwareness;
// File attributes
LARGE_INTEGER FileLastWriteTime;
LARGE_INTEGER FileEndOfFile;
PPH_STRING TooltipText;
ULONG TooltipTextValidToTickCount;
// Text buffers
WCHAR CpuUsageText[PH_INT32_STR_LEN_1];
PPH_STRING IoTotalRateText;
PPH_STRING PrivateBytesText;
PPH_STRING PeakPrivateBytesText;
PPH_STRING WorkingSetText;
PPH_STRING PeakWorkingSetText;
PPH_STRING PrivateWsText;
PPH_STRING SharedWsText;
PPH_STRING ShareableWsText;
PPH_STRING VirtualSizeText;
PPH_STRING PeakVirtualSizeText;
PPH_STRING PageFaultsText;
WCHAR BasePriorityText[PH_INT32_STR_LEN_1];
WCHAR ThreadsText[PH_INT32_STR_LEN_1 + 3];
WCHAR HandlesText[PH_INT32_STR_LEN_1 + 3];
WCHAR GdiHandlesText[PH_INT32_STR_LEN_1 + 3];
WCHAR UserHandlesText[PH_INT32_STR_LEN_1 + 3];
PPH_STRING IoRoRateText;
PPH_STRING IoWRateText;
WCHAR PagePriorityText[PH_INT32_STR_LEN_1];
PPH_STRING StartTimeText;
PPH_STRING TotalCpuTimeText;
PPH_STRING KernelCpuTimeText;
PPH_STRING UserCpuTimeText;
PPH_STRING RelativeStartTimeText;
PPH_STRING WindowTitleText;
PPH_STRING CyclesText;
PPH_STRING CyclesDeltaText;
PPH_STRING ContextSwitchesText;
PPH_STRING ContextSwitchesDeltaText;
PPH_STRING PageFaultsDeltaText;
PPH_STRING IoGroupText[PHPRTLC_IOGROUP_COUNT];
PPH_STRING PagedPoolText;
PPH_STRING PeakPagedPoolText;
PPH_STRING NonPagedPoolText;
PPH_STRING PeakNonPagedPoolText;
PPH_STRING MinimumWorkingSetText;
PPH_STRING MaximumWorkingSetText;
PPH_STRING PrivateBytesDeltaText;
PPH_STRING TimeStampText;
PPH_STRING FileModifiedTimeText;
PPH_STRING FileSizeText;
// Graph buffers
PH_GRAPH_BUFFERS CpuGraphBuffers;
PH_GRAPH_BUFFERS PrivateGraphBuffers;
PH_GRAPH_BUFFERS IoGraphBuffers;
// begin_phapppub
} PH_PROCESS_NODE, *PPH_PROCESS_NODE;
// end_phapppub
VOID PhProcessTreeListInitialization(
VOID
);
VOID PhInitializeProcessTreeList(
_In_ HWND hwnd
);
VOID PhLoadSettingsProcessTreeList(
VOID
);
VOID PhSaveSettingsProcessTreeList(
VOID
);
VOID PhReloadSettingsProcessTreeList(
VOID
);
// begin_phapppub
PHAPPAPI
struct _PH_TN_FILTER_SUPPORT *
NTAPI
PhGetFilterSupportProcessTreeList(
VOID
);
// end_phapppub
PPH_PROCESS_NODE PhAddProcessNode(
_In_ PPH_PROCESS_ITEM ProcessItem,
_In_ ULONG RunId
);
// begin_phapppub
PHAPPAPI
PPH_PROCESS_NODE
NTAPI
PhFindProcessNode(
_In_ HANDLE ProcessId
);
// end_phapppub
VOID PhRemoveProcessNode(
_In_ PPH_PROCESS_NODE ProcessNode
);
// begin_phapppub
PHAPPAPI
VOID
NTAPI
PhUpdateProcessNode(
_In_ PPH_PROCESS_NODE ProcessNode
);
// end_phapppub
VOID PhTickProcessNodes(
VOID
);
// begin_phapppub
PHAPPAPI
PPH_PROCESS_ITEM
NTAPI
PhGetSelectedProcessItem(
VOID
);
PHAPPAPI
VOID
NTAPI
PhGetSelectedProcessItems(
_Out_ PPH_PROCESS_ITEM **Processes,
_Out_ PULONG NumberOfProcesses
);
PHAPPAPI
VOID
NTAPI
PhDeselectAllProcessNodes(
VOID
);
PHAPPAPI
VOID
NTAPI
PhExpandAllProcessNodes(
_In_ BOOLEAN Expand
);
PHAPPAPI
VOID
NTAPI
PhInvalidateAllProcessNodes(
VOID
);
PHAPPAPI
VOID
NTAPI
PhSelectAndEnsureVisibleProcessNode(
_In_ PPH_PROCESS_NODE ProcessNode
);
// end_phapppub
VOID PhSelectAndEnsureVisibleProcessNodes(
_In_ PPH_PROCESS_NODE *ProcessNodes,
_In_ ULONG NumberOfProcessNodes
);
PPH_LIST PhGetProcessTreeListLines(
_In_ HWND TreeListHandle,
_In_ ULONG NumberOfNodes,
_In_ PPH_LIST RootNodes,
_In_ ULONG Mode
);
VOID PhCopyProcessTree(
VOID
);
VOID PhWriteProcessTree(
_Inout_ PPH_FILE_STREAM FileStream,
_In_ ULONG Mode
);
// begin_phapppub
PHAPPAPI
PPH_LIST
NTAPI
PhDuplicateProcessNodeList(
VOID
);
// end_phapppub
#endif

View File

@ -0,0 +1,227 @@
#ifndef PH_SETTINGS_H
#define PH_SETTINGS_H
// begin_phapppub
typedef enum _PH_SETTING_TYPE
{
StringSettingType,
IntegerSettingType,
IntegerPairSettingType,
ScalableIntegerPairSettingType
} PH_SETTING_TYPE, PPH_SETTING_TYPE;
// end_phapppub
typedef struct _PH_SETTING
{
PH_SETTING_TYPE Type;
PH_STRINGREF Name;
PH_STRINGREF DefaultValue;
union
{
PVOID Pointer;
ULONG Integer;
PH_INTEGER_PAIR IntegerPair;
} u;
} PH_SETTING, *PPH_SETTING;
VOID PhSettingsInitialization(
VOID
);
VOID PhUpdateCachedSettings(
VOID
);
// begin_phapppub
_May_raise_
PHAPPAPI
ULONG
NTAPI
PhGetIntegerSetting(
_In_ PWSTR Name
);
_May_raise_
PHAPPAPI
PH_INTEGER_PAIR
NTAPI
PhGetIntegerPairSetting(
_In_ PWSTR Name
);
_May_raise_
PHAPPAPI
PH_SCALABLE_INTEGER_PAIR
NTAPI
PhGetScalableIntegerPairSetting(
_In_ PWSTR Name,
_In_ BOOLEAN ScaleToCurrent
);
_May_raise_
PHAPPAPI
PPH_STRING
NTAPI
PhGetStringSetting(
_In_ PWSTR Name
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetIntegerSetting(
_In_ PWSTR Name,
_In_ ULONG Value
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetIntegerPairSetting(
_In_ PWSTR Name,
_In_ PH_INTEGER_PAIR Value
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetScalableIntegerPairSetting(
_In_ PWSTR Name,
_In_ PH_SCALABLE_INTEGER_PAIR Value
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetScalableIntegerPairSetting2(
_In_ PWSTR Name,
_In_ PH_INTEGER_PAIR Value
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetStringSetting(
_In_ PWSTR Name,
_In_ PWSTR Value
);
_May_raise_
PHAPPAPI
VOID
NTAPI
PhSetStringSetting2(
_In_ PWSTR Name,
_In_ PPH_STRINGREF Value
);
// end_phapppub
VOID PhClearIgnoredSettings(
VOID
);
VOID PhConvertIgnoredSettings(
VOID
);
NTSTATUS PhLoadSettings(
_In_ PWSTR FileName
);
NTSTATUS PhSaveSettings(
_In_ PWSTR FileName
);
VOID PhResetSettings(
VOID
);
#define PhaGetStringSetting(Name) PH_AUTO_T(PH_STRING, PhGetStringSetting(Name)) // phapppub
// begin_phapppub
// High-level settings creation
typedef struct _PH_SETTING_CREATE
{
PH_SETTING_TYPE Type;
PWSTR Name;
PWSTR DefaultValue;
} PH_SETTING_CREATE, *PPH_SETTING_CREATE;
PHAPPAPI
VOID
NTAPI
PhAddSettings(
_In_ PPH_SETTING_CREATE Settings,
_In_ ULONG NumberOfSettings
);
// end_phapppub
// Cached settings
#undef EXT
#ifdef PH_SETTINGS_PRIVATE
#define EXT
#else
#define EXT extern
#endif
EXT ULONG PhCsCollapseServicesOnStart;
EXT ULONG PhCsForceNoParent;
EXT ULONG PhCsHighlightingDuration;
EXT ULONG PhCsPropagateCpuUsage;
EXT ULONG PhCsScrollToNewProcesses;
EXT ULONG PhCsShowCpuBelow001;
EXT ULONG PhCsUpdateInterval;
EXT ULONG PhCsColorNew;
EXT ULONG PhCsColorRemoved;
EXT ULONG PhCsUseColorOwnProcesses;
EXT ULONG PhCsColorOwnProcesses;
EXT ULONG PhCsUseColorSystemProcesses;
EXT ULONG PhCsColorSystemProcesses;
EXT ULONG PhCsUseColorServiceProcesses;
EXT ULONG PhCsColorServiceProcesses;
EXT ULONG PhCsUseColorJobProcesses;
EXT ULONG PhCsColorJobProcesses;
EXT ULONG PhCsUseColorWow64Processes;
EXT ULONG PhCsColorWow64Processes;
EXT ULONG PhCsUseColorDebuggedProcesses;
EXT ULONG PhCsColorDebuggedProcesses;
EXT ULONG PhCsUseColorElevatedProcesses;
EXT ULONG PhCsColorElevatedProcesses;
EXT ULONG PhCsUseColorImmersiveProcesses;
EXT ULONG PhCsColorImmersiveProcesses;
EXT ULONG PhCsUseColorSuspended;
EXT ULONG PhCsColorSuspended;
EXT ULONG PhCsUseColorDotNet;
EXT ULONG PhCsColorDotNet;
EXT ULONG PhCsUseColorPacked;
EXT ULONG PhCsColorPacked;
EXT ULONG PhCsUseColorGuiThreads;
EXT ULONG PhCsColorGuiThreads;
EXT ULONG PhCsUseColorRelocatedModules;
EXT ULONG PhCsColorRelocatedModules;
EXT ULONG PhCsUseColorProtectedHandles;
EXT ULONG PhCsColorProtectedHandles;
EXT ULONG PhCsUseColorInheritHandles;
EXT ULONG PhCsColorInheritHandles;
EXT ULONG PhCsGraphShowText;
EXT ULONG PhCsGraphColorMode;
EXT ULONG PhCsColorCpuKernel;
EXT ULONG PhCsColorCpuUser;
EXT ULONG PhCsColorIoReadOther;
EXT ULONG PhCsColorIoWrite;
EXT ULONG PhCsColorPrivate;
EXT ULONG PhCsColorPhysical;
#define PH_SET_INTEGER_CACHED_SETTING(Name, Value) (PhSetIntegerSetting(L#Name, PhCs##Name = (Value)))
#endif

View File

@ -0,0 +1,46 @@
#ifndef PH_SETTINGSP_H
#define PH_SETTINGSP_H
#include <shlobj.h>
BOOLEAN NTAPI PhpSettingsHashtableEqualFunction(
_In_ PVOID Entry1,
_In_ PVOID Entry2
);
ULONG NTAPI PhpSettingsHashtableHashFunction(
_In_ PVOID Entry
);
VOID PhpAddSetting(
_In_ PH_SETTING_TYPE Type,
_In_ PPH_STRINGREF Name,
_In_ PPH_STRINGREF DefaultValue
);
ULONG PhpGetCurrentScale(
VOID
);
PPH_STRING PhpSettingToString(
_In_ PH_SETTING_TYPE Type,
_In_ PPH_SETTING Setting
);
BOOLEAN PhpSettingFromString(
_In_ PH_SETTING_TYPE Type,
_In_ PPH_STRINGREF StringRef,
_In_opt_ PPH_STRING String,
_Inout_ PPH_SETTING Setting
);
VOID PhpFreeSettingValue(
_In_ PH_SETTING_TYPE Type,
_In_ PPH_SETTING Setting
);
PVOID PhpLookupSetting(
_In_ PPH_STRINGREF Name
);
#endif

View File

@ -0,0 +1,153 @@
#ifndef PH_SRVLIST_H
#define PH_SRVLIST_H
#include <phuisup.h>
// Columns
#define PHSVTLC_NAME 0
#define PHSVTLC_DISPLAYNAME 1
#define PHSVTLC_TYPE 2
#define PHSVTLC_STATUS 3
#define PHSVTLC_STARTTYPE 4
#define PHSVTLC_PID 5
#define PHSVTLC_BINARYPATH 6
#define PHSVTLC_ERRORCONTROL 7
#define PHSVTLC_GROUP 8
#define PHSVTLC_DESCRIPTION 9
#define PHSVTLC_KEYMODIFIEDTIME 10
#define PHSVTLC_MAXIMUM 11
#define PHSN_CONFIG 0x1
#define PHSN_DESCRIPTION 0x2
#define PHSN_KEY 0x4
// begin_phapppub
typedef struct _PH_SERVICE_NODE
{
PH_TREENEW_NODE Node;
PH_SH_STATE ShState;
PPH_SERVICE_ITEM ServiceItem;
// end_phapppub
PH_STRINGREF TextCache[PHSVTLC_MAXIMUM];
ULONG ValidMask;
WCHAR StartTypeText[12 + 24 + 1];
// Config
PPH_STRING BinaryPath;
PPH_STRING LoadOrderGroup;
// Description
PPH_STRING Description;
// Key
LARGE_INTEGER KeyLastWriteTime;
PPH_STRING TooltipText;
PPH_STRING KeyModifiedTimeText;
// begin_phapppub
} PH_SERVICE_NODE, *PPH_SERVICE_NODE;
// end_phapppub
VOID PhServiceTreeListInitialization(
VOID
);
VOID PhInitializeServiceTreeList(
_In_ HWND hwnd
);
VOID PhLoadSettingsServiceTreeList(
VOID
);
VOID PhSaveSettingsServiceTreeList(
VOID
);
// begin_phapppub
PHAPPAPI
struct _PH_TN_FILTER_SUPPORT *
NTAPI
PhGetFilterSupportServiceTreeList(
VOID
);
// end_phapppub
PPH_SERVICE_NODE PhAddServiceNode(
_In_ PPH_SERVICE_ITEM ServiceItem,
_In_ ULONG RunId
);
// begin_phapppub
PHAPPAPI
PPH_SERVICE_NODE
NTAPI
PhFindServiceNode(
_In_ PPH_SERVICE_ITEM ServiceItem
);
// end_phapppub
VOID PhRemoveServiceNode(
_In_ PPH_SERVICE_NODE ServiceNode
);
// begin_phapppub
PHAPPAPI
VOID
NTAPI
PhUpdateServiceNode(
_In_ PPH_SERVICE_NODE ServiceNode
);
// end_phapppub
VOID PhTickServiceNodes(
VOID
);
// begin_phapppub
PHAPPAPI
PPH_SERVICE_ITEM
NTAPI
PhGetSelectedServiceItem(
VOID
);
PHAPPAPI
VOID
NTAPI
PhGetSelectedServiceItems(
_Out_ PPH_SERVICE_ITEM **Services,
_Out_ PULONG NumberOfServices
);
PHAPPAPI
VOID
NTAPI
PhDeselectAllServiceNodes(
VOID
);
PHAPPAPI
VOID
NTAPI
PhSelectAndEnsureVisibleServiceNode(
_In_ PPH_SERVICE_NODE ServiceNode
);
// end_phapppub
VOID PhCopyServiceList(
VOID
);
VOID PhWriteServiceList(
_Inout_ PPH_FILE_STREAM FileStream,
_In_ ULONG Mode
);
#endif

View File

@ -0,0 +1,96 @@
#ifndef PH_SRVPRV_H
#define PH_SRVPRV_H
extern PPH_OBJECT_TYPE PhServiceItemType;
PHAPPAPI extern PH_CALLBACK PhServiceAddedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhServiceModifiedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhServiceRemovedEvent; // phapppub
PHAPPAPI extern PH_CALLBACK PhServicesUpdatedEvent; // phapppub
extern BOOLEAN PhEnableServiceNonPoll;
// begin_phapppub
typedef struct _PH_SERVICE_ITEM
{
PH_STRINGREF Key; // points to Name
PPH_STRING Name;
PPH_STRING DisplayName;
// State
ULONG Type;
ULONG State;
ULONG ControlsAccepted;
ULONG Flags; // e.g. SERVICE_RUNS_IN_SYSTEM_PROCESS
HANDLE ProcessId;
// Config
ULONG StartType;
ULONG ErrorControl;
// end_phapppub
BOOLEAN DelayedStart;
BOOLEAN HasTriggers;
BOOLEAN PendingProcess;
BOOLEAN NeedsConfigUpdate;
WCHAR ProcessIdString[PH_INT32_STR_LEN_1];
// begin_phapppub
} PH_SERVICE_ITEM, *PPH_SERVICE_ITEM;
// end_phapppub
// begin_phapppub
typedef struct _PH_SERVICE_MODIFIED_DATA
{
PPH_SERVICE_ITEM Service;
PH_SERVICE_ITEM OldService;
} PH_SERVICE_MODIFIED_DATA, *PPH_SERVICE_MODIFIED_DATA;
typedef enum _PH_SERVICE_CHANGE
{
ServiceStarted,
ServiceContinued,
ServicePaused,
ServiceStopped
} PH_SERVICE_CHANGE, *PPH_SERVICE_CHANGE;
// end_phapppub
BOOLEAN PhServiceProviderInitialization(
VOID
);
PPH_SERVICE_ITEM PhCreateServiceItem(
_In_opt_ LPENUM_SERVICE_STATUS_PROCESS Information
);
// begin_phapppub
PHAPPAPI
PPH_SERVICE_ITEM
NTAPI
PhReferenceServiceItem(
_In_ PWSTR Name
);
// end_phapppub
VOID PhMarkNeedsConfigUpdateServiceItem(
_In_ PPH_SERVICE_ITEM ServiceItem
);
// begin_phapppub
PHAPPAPI
PH_SERVICE_CHANGE
NTAPI
PhGetServiceChange(
_In_ PPH_SERVICE_MODIFIED_DATA Data
);
// end_phapppub
VOID PhUpdateProcessItemServices(
_In_ PPH_PROCESS_ITEM ProcessItem
);
VOID PhServiceProviderUpdate(
_In_ PVOID Object
);
#endif

View File

@ -0,0 +1,166 @@
#ifndef PH_SYSINFO_H
#define PH_SYSINFO_H
// begin_phapppub
typedef enum _PH_SYSINFO_VIEW_TYPE
{
SysInfoSummaryView,
SysInfoSectionView
} PH_SYSINFO_VIEW_TYPE;
typedef VOID (NTAPI *PPH_SYSINFO_COLOR_SETUP_FUNCTION)(
_Out_ PPH_GRAPH_DRAW_INFO DrawInfo,
_In_ COLORREF Color1,
_In_ COLORREF Color2
);
typedef struct _PH_SYSINFO_PARAMETERS
{
HWND SysInfoWindowHandle;
HWND ContainerWindowHandle;
HFONT Font;
HFONT MediumFont;
HFONT LargeFont;
ULONG FontHeight;
ULONG FontAverageWidth;
ULONG MediumFontHeight;
ULONG MediumFontAverageWidth;
COLORREF GraphBackColor;
COLORREF PanelForeColor;
PPH_SYSINFO_COLOR_SETUP_FUNCTION ColorSetupFunction;
ULONG MinimumGraphHeight;
ULONG SectionViewGraphHeight;
ULONG PanelWidth;
// end_phapppub
ULONG PanelPadding;
ULONG WindowPadding;
ULONG GraphPadding;
ULONG SmallGraphWidth;
ULONG SmallGraphPadding;
ULONG SeparatorWidth;
ULONG CpuPadding;
ULONG MemoryPadding;
// begin_phapppub
} PH_SYSINFO_PARAMETERS, *PPH_SYSINFO_PARAMETERS;
typedef enum _PH_SYSINFO_SECTION_MESSAGE
{
SysInfoCreate,
SysInfoDestroy,
SysInfoTick,
SysInfoViewChanging, // PH_SYSINFO_VIEW_TYPE Parameter1, PPH_SYSINFO_SECTION Parameter2
SysInfoCreateDialog, // PPH_SYSINFO_CREATE_DIALOG Parameter1
SysInfoGraphGetDrawInfo, // PPH_GRAPH_DRAW_INFO Parameter1
SysInfoGraphGetTooltipText, // PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT Parameter1
SysInfoGraphDrawPanel, // PPH_SYSINFO_DRAW_PANEL Parameter1
MaxSysInfoMessage
} PH_SYSINFO_SECTION_MESSAGE;
typedef BOOLEAN (NTAPI *PPH_SYSINFO_SECTION_CALLBACK)(
_In_ struct _PH_SYSINFO_SECTION *Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
typedef struct _PH_SYSINFO_CREATE_DIALOG
{
BOOLEAN CustomCreate;
// Parameters for default create
PVOID Instance;
PWSTR Template;
DLGPROC DialogProc;
PVOID Parameter;
} PH_SYSINFO_CREATE_DIALOG, *PPH_SYSINFO_CREATE_DIALOG;
typedef struct _PH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT
{
ULONG Index;
PH_STRINGREF Text;
} PH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT, *PPH_SYSINFO_GRAPH_GET_TOOLTIP_TEXT;
typedef struct _PH_SYSINFO_DRAW_PANEL
{
HDC hdc;
RECT Rect;
BOOLEAN CustomDraw;
// Parameters for default draw
PPH_STRING Title;
PPH_STRING SubTitle;
PPH_STRING SubTitleOverflow;
} PH_SYSINFO_DRAW_PANEL, *PPH_SYSINFO_DRAW_PANEL;
// end_phapppub
// begin_phapppub
typedef struct _PH_SYSINFO_SECTION
{
// Public
// Initialization
PH_STRINGREF Name;
ULONG Flags;
PPH_SYSINFO_SECTION_CALLBACK Callback;
PVOID Context;
PVOID Reserved[3];
// State
HWND GraphHandle;
PH_GRAPH_STATE GraphState;
PPH_SYSINFO_PARAMETERS Parameters;
PVOID Reserved2[3];
// end_phapppub
// Private
struct
{
ULONG GraphHot : 1;
ULONG PanelHot : 1;
ULONG HasFocus : 1;
ULONG HideFocus : 1;
ULONG SpareFlags : 28;
};
HWND DialogHandle;
HWND PanelHandle;
ULONG PanelId;
WNDPROC GraphOldWndProc;
WNDPROC PanelOldWndProc;
// begin_phapppub
} PH_SYSINFO_SECTION, *PPH_SYSINFO_SECTION;
// end_phapppub
VOID PhSiNotifyChangeSettings(
VOID
);
// begin_phapppub
PHAPPAPI
VOID
NTAPI
PhSiSetColorsGraphDrawInfo(
_Out_ PPH_GRAPH_DRAW_INFO DrawInfo,
_In_ COLORREF Color1,
_In_ COLORREF Color2
);
PHAPPAPI
PPH_STRING
NTAPI
PhSiSizeLabelYFunction(
_In_ PPH_GRAPH_DRAW_INFO DrawInfo,
_In_ ULONG DataIndex,
_In_ FLOAT Value,
_In_ FLOAT Parameter
);
// end_phapppub
VOID PhShowSystemInformationDialog(
_In_opt_ PWSTR SectionName
);
#endif

View File

@ -0,0 +1,439 @@
#ifndef PH_SYSINFOP_H
#define PH_SYSINFOP_H
// Constants
#define PH_SYSINFO_FADE_ADD 50
#define PH_SYSINFO_PANEL_PADDING 3
#define PH_SYSINFO_WINDOW_PADDING 13
#define PH_SYSINFO_GRAPH_PADDING 9
#define PH_SYSINFO_SMALL_GRAPH_WIDTH 48
#define PH_SYSINFO_SMALL_GRAPH_PADDING 5
#define PH_SYSINFO_SEPARATOR_WIDTH 2
#define PH_SYSINFO_CPU_PADDING 5
#define PH_SYSINFO_MEMORY_PADDING 3
#define SI_MSG_SYSINFO_FIRST (WM_APP + 150)
#define SI_MSG_SYSINFO_ACTIVATE (WM_APP + 150)
#define SI_MSG_SYSINFO_UPDATE (WM_APP + 151)
#define SI_MSG_SYSINFO_CHANGE_SETTINGS (WM_APP + 152)
#define SI_MSG_SYSINFO_LAST (WM_APP + 152)
#define SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER (SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)
#define SWP_SHOWWINDOW_ONLY (SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER | SWP_SHOWWINDOW)
#define SWP_HIDEWINDOW_ONLY (SWP_NO_ACTIVATE_MOVE_SIZE_ZORDER | SWP_HIDEWINDOW)
// Thread & window
extern HWND PhSipWindow;
NTSTATUS PhSipSysInfoThreadStart(
_In_ PVOID Parameter
);
INT_PTR CALLBACK PhSipSysInfoDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhSipContainerDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// Event handlers
VOID PhSipOnInitDialog(
VOID
);
VOID PhSipOnDestroy(
VOID
);
VOID PhSipOnNcDestroy(
VOID
);
VOID PhSipOnShowWindow(
_In_ BOOLEAN Showing,
_In_ ULONG State
);
BOOLEAN PhSipOnSysCommand(
_In_ ULONG Type,
_In_ LONG CursorScreenX,
_In_ LONG CursorScreenY
);
VOID PhSipOnSize(
VOID
);
VOID PhSipOnSizing(
_In_ ULONG Edge,
_In_ PRECT DragRectangle
);
VOID PhSipOnThemeChanged(
VOID
);
VOID PhSipOnCommand(
_In_ ULONG Id,
_In_ ULONG Code
);
BOOLEAN PhSipOnNotify(
_In_ NMHDR *Header,
_Out_ LRESULT *Result
);
BOOLEAN PhSipOnDrawItem(
_In_ ULONG_PTR Id,
_In_ DRAWITEMSTRUCT *DrawItemStruct
);
VOID PhSipOnUserMessage(
_In_ ULONG Message,
_In_ ULONG_PTR WParam,
_In_ ULONG_PTR LParam
);
// Framework
VOID PhSipRegisterDialog(
_In_ HWND DialogWindowHandle
);
VOID PhSipUnregisterDialog(
_In_ HWND DialogWindowHandle
);
VOID PhSipInitializeParameters(
VOID
);
VOID PhSipDeleteParameters(
VOID
);
VOID PhSipUpdateColorParameters(
VOID
);
PPH_SYSINFO_SECTION PhSipCreateSection(
_In_ PPH_SYSINFO_SECTION Template
);
VOID PhSipDestroySection(
_In_ PPH_SYSINFO_SECTION Section
);
PPH_SYSINFO_SECTION PhSipFindSection(
_In_ PPH_STRINGREF Name
);
PPH_SYSINFO_SECTION PhSipCreateInternalSection(
_In_ PWSTR Name,
_In_ ULONG Flags,
_In_ PPH_SYSINFO_SECTION_CALLBACK Callback
);
VOID PhSipDrawRestoreSummaryPanel(
_In_ HDC hdc,
_In_ PRECT Rect
);
VOID PhSipDrawSeparator(
_In_ HDC hdc,
_In_ PRECT Rect
);
VOID PhSipDrawPanel(
_In_ PPH_SYSINFO_SECTION Section,
_In_ HDC hdc,
_In_ PRECT Rect
);
VOID PhSipDefaultDrawPanel(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PPH_SYSINFO_DRAW_PANEL DrawPanel
);
VOID PhSipLayoutSummaryView(
VOID
);
VOID PhSipLayoutSectionView(
VOID
);
VOID PhSipEnterSectionView(
_In_ PPH_SYSINFO_SECTION NewSection
);
VOID PhSipEnterSectionViewInner(
_In_ PPH_SYSINFO_SECTION Section,
_In_ BOOLEAN FromSummaryView,
_Inout_ HDWP *DeferHandle,
_Inout_ HDWP *ContainerDeferHandle
);
VOID PhSipRestoreSummaryView(
VOID
);
VOID PhSipCreateSectionDialog(
_In_ PPH_SYSINFO_SECTION Section
);
LRESULT CALLBACK PhSipGraphHookWndProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
LRESULT CALLBACK PhSipPanelHookWndProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
// Misc.
VOID PhSipUpdateThemeData(
VOID
);
VOID PhSipSetAlwaysOnTop(
VOID
);
VOID PhSipSaveWindowState(
VOID
);
VOID NTAPI PhSipSysInfoUpdateHandler(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
);
PPH_STRING PhSipFormatSizeWithPrecision(
_In_ ULONG64 Size,
_In_ USHORT Precision
);
// CPU section
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT_WIN8
{
ULONG Hits;
UCHAR PercentFrequency;
} SYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT_WIN8, *PSYSTEM_PROCESSOR_PERFORMANCE_HITCOUNT_WIN8;
BOOLEAN PhSipCpuSectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
VOID PhSipInitializeCpuDialog(
VOID
);
VOID PhSipUninitializeCpuDialog(
VOID
);
VOID PhSipTickCpuDialog(
VOID
);
INT_PTR CALLBACK PhSipCpuDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhSipCpuPanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhSipCreateCpuGraphs(
VOID
);
VOID PhSipLayoutCpuGraphs(
VOID
);
VOID PhSipSetOneGraphPerCpu(
VOID
);
VOID PhSipNotifyCpuGraph(
_In_ ULONG Index,
_In_ NMHDR *Header
);
VOID PhSipUpdateCpuGraphs(
VOID
);
VOID PhSipUpdateCpuPanel(
VOID
);
PPH_PROCESS_RECORD PhSipReferenceMaxCpuRecord(
_In_ LONG Index
);
PPH_STRING PhSipGetMaxCpuString(
_In_ LONG Index
);
VOID PhSipGetCpuBrandString(
_Out_writes_(49) PWSTR BrandString
);
BOOLEAN PhSipGetCpuFrequencyFromDistribution(
_Out_ DOUBLE *Fraction
);
NTSTATUS PhSipQueryProcessorPerformanceDistribution(
_Out_ PVOID *Buffer
);
// Memory section
BOOLEAN PhSipMemorySectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
VOID PhSipInitializeMemoryDialog(
VOID
);
VOID PhSipUninitializeMemoryDialog(
VOID
);
VOID PhSipTickMemoryDialog(
VOID
);
INT_PTR CALLBACK PhSipMemoryDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhSipMemoryPanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhSipLayoutMemoryGraphs(
VOID
);
VOID PhSipNotifyCommitGraph(
_In_ NMHDR *Header
);
VOID PhSipNotifyPhysicalGraph(
_In_ NMHDR *Header
);
VOID PhSipUpdateMemoryGraphs(
VOID
);
VOID PhSipUpdateMemoryPanel(
VOID
);
NTSTATUS PhSipLoadMmAddresses(
_In_ PVOID Parameter
);
VOID PhSipGetPoolLimits(
_Out_ PSIZE_T Paged,
_Out_ PSIZE_T NonPaged
);
// I/O section
BOOLEAN PhSipIoSectionCallback(
_In_ PPH_SYSINFO_SECTION Section,
_In_ PH_SYSINFO_SECTION_MESSAGE Message,
_In_opt_ PVOID Parameter1,
_In_opt_ PVOID Parameter2
);
VOID PhSipInitializeIoDialog(
VOID
);
VOID PhSipUninitializeIoDialog(
VOID
);
VOID PhSipTickIoDialog(
VOID
);
INT_PTR CALLBACK PhSipIoDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
INT_PTR CALLBACK PhSipIoPanelDialogProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
VOID PhSipNotifyIoGraph(
_In_ NMHDR *Header
);
VOID PhSipUpdateIoGraph(
VOID
);
VOID PhSipUpdateIoPanel(
VOID
);
PPH_PROCESS_RECORD PhSipReferenceMaxIoRecord(
_In_ LONG Index
);
PPH_STRING PhSipGetMaxIoString(
_In_ LONG Index
);
#endif

Some files were not shown because too many files have changed in this diff Show More