diff --git a/trunk/CHANGELOG.txt b/trunk/CHANGELOG.txt
index 4b814ea84..761fcc1b3 100644
--- a/trunk/CHANGELOG.txt
+++ b/trunk/CHANGELOG.txt
@@ -4,6 +4,7 @@ Process Hacker
* NEW/IMPROVED:
* POSIX process support, including command lines and
highlighting
+ * Hidden processes scanner can now detect FUTo
* Ability to set DEP status of processes in other sessions
* Automatic tree text coloring, allowing for dark highlighting
colors
diff --git a/trunk/KProcessHacker/hook.c b/trunk/KProcessHacker/hook.c
index d34e7a4e2..e2cd60cf3 100644
--- a/trunk/KProcessHacker/hook.c
+++ b/trunk/KProcessHacker/hook.c
@@ -30,13 +30,13 @@ typedef struct _MAPPED_MDL
} MAPPED_MDL, *PMAPPED_MDL;
NTSTATUS KphpCreateMappedMdl(
- PVOID Address,
- ULONG Length,
- PMAPPED_MDL MappedMdl
+ __in PVOID Address,
+ __in ULONG Length,
+ __out PMAPPED_MDL MappedMdl
);
VOID KphpFreeMappedMdl(
- PMAPPED_MDL MappedMdl
+ __in PMAPPED_MDL MappedMdl
);
static KPH_PROCESSOR_LOCK HookProcessorLock;
@@ -57,9 +57,9 @@ NTSTATUS KphHookInit()
* Initializes a hook structure.
*/
VOID KphInitializeHook(
- PKPH_HOOK Hook,
- PVOID Function,
- PVOID Target
+ __out PKPH_HOOK Hook,
+ __in PVOID Function,
+ __in PVOID Target
)
{
memset(Hook, 0, sizeof(KPH_HOOK));
@@ -76,7 +76,7 @@ VOID KphInitializeHook(
* IRQL: <= APC_LEVEL
*/
NTSTATUS KphHook(
- PKPH_HOOK Hook
+ __inout PKPH_HOOK Hook
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -131,7 +131,7 @@ NTSTATUS KphHook(
* IRQL: <= APC_LEVEL
*/
NTSTATUS KphUnhook(
- PKPH_HOOK Hook
+ __inout PKPH_HOOK Hook
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -176,13 +176,13 @@ NTSTATUS KphUnhook(
* AccessMode: If this argument is unavailable, specify KernelMode.
*/
NTSTATUS NTAPI KphObOpenCall(
- PKPH_OB_OPEN_HOOK ObOpenHook,
- OB_OPEN_REASON OpenReason,
- KPROCESSOR_MODE AccessMode,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in PKPH_OB_OPEN_HOOK ObOpenHook,
+ __in OB_OPEN_REASON OpenReason,
+ __in KPROCESSOR_MODE AccessMode,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
)
{
/* If there wasn't any original open procedure, exit. */
@@ -220,10 +220,10 @@ NTSTATUS NTAPI KphObOpenCall(
}
VOID KphInitializeObOpenHook(
- PKPH_OB_OPEN_HOOK ObOpenHook,
- POBJECT_TYPE ObjectType,
- PVOID Target51,
- PVOID Target60
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook,
+ __in POBJECT_TYPE ObjectType,
+ __in PVOID Target51,
+ __in PVOID Target60
)
{
memset(ObOpenHook, 0, sizeof(KPH_OB_OPEN_HOOK));
@@ -240,7 +240,7 @@ VOID KphInitializeObOpenHook(
* IRQL: <= APC_LEVEL
*/
NTSTATUS KphObOpenHook(
- PKPH_OB_OPEN_HOOK ObOpenHook
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -310,7 +310,7 @@ NTSTATUS KphObOpenHook(
* IRQL: <= APC_LEVEL
*/
NTSTATUS KphObOpenUnhook(
- PKPH_OB_OPEN_HOOK ObOpenHook
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -359,9 +359,9 @@ NTSTATUS KphObOpenUnhook(
* IRQL: Any
*/
NTSTATUS KphpCreateMappedMdl(
- PVOID Address,
- ULONG Length,
- PMAPPED_MDL MappedMdl
+ __in PVOID Address,
+ __in ULONG Length,
+ __out PMAPPED_MDL MappedMdl
)
{
PMDL mdl;
@@ -403,7 +403,7 @@ NTSTATUS KphpCreateMappedMdl(
* IRQL: Any
*/
VOID KphpFreeMappedMdl(
- PMAPPED_MDL MappedMdl
+ __in PMAPPED_MDL MappedMdl
)
{
if (MappedMdl->Mdl != NULL)
diff --git a/trunk/KProcessHacker/i386/kprocesshacker.sys b/trunk/KProcessHacker/i386/kprocesshacker.sys
index 0ba031e8d..cb52e38d4 100644
Binary files a/trunk/KProcessHacker/i386/kprocesshacker.sys and b/trunk/KProcessHacker/i386/kprocesshacker.sys differ
diff --git a/trunk/KProcessHacker/include/ex.h b/trunk/KProcessHacker/include/ex.h
index 8c130abb7..80c5b3307 100644
--- a/trunk/KProcessHacker/include/ex.h
+++ b/trunk/KProcessHacker/include/ex.h
@@ -35,10 +35,10 @@ typedef BOOLEAN (NTAPI *PEX_ENUM_HANDLE_CALLBACK)(
);
BOOLEAN NTAPI ExEnumHandleTable(
- struct _HANDLE_TABLE *HandleTable,
- PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
- PVOID Context,
- PHANDLE Handle
+ __in struct _HANDLE_TABLE *HandleTable,
+ __in PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
+ __inout PVOID Context,
+ __out_opt PHANDLE Handle
);
typedef NTSTATUS (NTAPI *_ExpGetProcessInformation)(
diff --git a/trunk/KProcessHacker/include/hook.h b/trunk/KProcessHacker/include/hook.h
index 25e666cc3..ecc4bc499 100644
--- a/trunk/KProcessHacker/include/hook.h
+++ b/trunk/KProcessHacker/include/hook.h
@@ -67,42 +67,42 @@ typedef struct _KPH_OB_OPEN_HOOK
NTSTATUS KphHookInit();
VOID KphInitializeHook(
- PKPH_HOOK Hook,
- PVOID Function,
- PVOID Target
+ __out PKPH_HOOK Hook,
+ __in PVOID Function,
+ __in PVOID Target
);
NTSTATUS KphHook(
- PKPH_HOOK Hook
+ __inout PKPH_HOOK Hook
);
NTSTATUS KphUnhook(
- PKPH_HOOK Hook
+ __inout PKPH_HOOK Hook
);
NTSTATUS NTAPI KphObOpenCall(
- PKPH_OB_OPEN_HOOK ObOpenHook,
- OB_OPEN_REASON OpenReason,
- KPROCESSOR_MODE AccessMode,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in PKPH_OB_OPEN_HOOK ObOpenHook,
+ __in OB_OPEN_REASON OpenReason,
+ __in KPROCESSOR_MODE AccessMode,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
);
VOID KphInitializeObOpenHook(
- PKPH_OB_OPEN_HOOK ObOpenHook,
- POBJECT_TYPE ObjectType,
- PVOID Target51,
- PVOID Target60
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook,
+ __in POBJECT_TYPE ObjectType,
+ __in PVOID Target51,
+ __in PVOID Target60
);
NTSTATUS KphObOpenHook(
- PKPH_OB_OPEN_HOOK ObOpenHook
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook
);
NTSTATUS KphObOpenUnhook(
- PKPH_OB_OPEN_HOOK ObOpenHook
+ __inout PKPH_OB_OPEN_HOOK ObOpenHook
);
#endif
diff --git a/trunk/KProcessHacker/include/kph.h b/trunk/KProcessHacker/include/kph.h
index 88152152a..1d2c07004 100644
--- a/trunk/KProcessHacker/include/kph.h
+++ b/trunk/KProcessHacker/include/kph.h
@@ -64,247 +64,262 @@ PVOID GetSystemRoutineAddress(
WCHAR *Name
);
-NTSTATUS OpenProcess(
- PHANDLE ProcessHandle,
- ULONG DesiredAccess,
- HANDLE ProcessId
- );
-
VOID KphAttachProcess(
- PEPROCESS Process,
- PKPH_ATTACH_STATE AttachState
+ __in PEPROCESS Process,
+ __out PKPH_ATTACH_STATE AttachState
);
NTSTATUS KphAttachProcessHandle(
- HANDLE ProcessHandle,
- PKPH_ATTACH_STATE AttachState
+ __in HANDLE ProcessHandle,
+ __out PKPH_ATTACH_STATE AttachState
);
NTSTATUS KphAttachProcessId(
- HANDLE ProcessId,
- PKPH_ATTACH_STATE AttachState
+ __in HANDLE ProcessId,
+ __out PKPH_ATTACH_STATE AttachState
);
VOID KphDetachProcess(
- PKPH_ATTACH_STATE AttachState
+ __in PKPH_ATTACH_STATE AttachState
+ );
+
+NTSTATUS OpenProcess(
+ __out PHANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in HANDLE ProcessId
);
NTSTATUS SetProcessToken(
- HANDLE sourcePid,
- HANDLE targetPid
+ __in HANDLE sourcePid,
+ __in HANDLE targetPid
);
/* KProcessHacker */
BOOLEAN KphAcquireProcessRundownProtection(
- PEPROCESS Process
+ __in PEPROCESS Process
);
NTSTATUS KphAssignImpersonationToken(
- HANDLE ThreadHandle,
- HANDLE TokenHandle
+ __in HANDLE ThreadHandle,
+ __in HANDLE TokenHandle
);
NTSTATUS KphDuplicateObject(
- HANDLE SourceProcessHandle,
- HANDLE SourceHandle,
- HANDLE TargetProcessHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG HandleAttributes,
- ULONG Options,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE SourceProcessHandle,
+ __in HANDLE SourceHandle,
+ __in_opt HANDLE TargetProcessHandle,
+ __out_opt PHANDLE TargetHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG HandleAttributes,
+ __in ULONG Options,
+ __in KPROCESSOR_MODE AccessMode
);
BOOLEAN KphEnumProcessHandleTable(
- PEPROCESS Process,
- PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
- PVOID Context,
- PHANDLE Handle
+ __in PEPROCESS Process,
+ __in PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
+ __inout PVOID Context,
+ __out_opt PHANDLE Handle
);
NTSTATUS KphGetContextThread(
- HANDLE ThreadHandle,
- PCONTEXT ThreadContext,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __inout PCONTEXT ThreadContext,
+ __in KPROCESSOR_MODE AccessMode
);
HANDLE KphGetProcessId(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
);
HANDLE KphGetThreadId(
- HANDLE ThreadHandle,
- PHANDLE ProcessId
+ __in HANDLE ThreadHandle,
+ __out_opt PHANDLE ProcessId
);
NTSTATUS KphGetThreadWin32Thread(
- HANDLE ThreadHandle,
- PVOID *Win32Thread,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __out PVOID *Win32Thread,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphOpenProcess(
- PHANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PCLIENT_ID ClientId,
- KPROCESSOR_MODE AccessMode
+ __out PHANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in POBJECT_ATTRIBUTES ObjectAttributes,
+ __in PCLIENT_ID ClientId,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphOpenProcessJob(
- HANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- PHANDLE JobHandle,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __out PHANDLE JobHandle,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphOpenProcessTokenEx(
- HANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- ULONG ObjectAttributes,
- PHANDLE TokenHandle,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG ObjectAttributes,
+ __out PHANDLE TokenHandle,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphOpenThread(
- PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PCLIENT_ID ClientId,
- KPROCESSOR_MODE AccessMode
+ __out PHANDLE ThreadHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in POBJECT_ATTRIBUTES ObjectAttributes,
+ __in PCLIENT_ID ClientId,
+ __in KPROCESSOR_MODE AccessMode
+ );
+
+NTSTATUS KphOpenThreadProcess(
+ __in HANDLE ThreadHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __out PHANDLE ProcessHandle,
+ __in KPROCESSOR_MODE AccessMode
+ );
+
+NTSTATUS KphQueryProcessHandles(
+ __in HANDLE ProcessHandle,
+ __out_bcount_opt(BufferLength) PPROCESS_HANDLE_INFORMATION Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphReadVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __out_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
);
VOID KphReleaseProcessRundownProtection(
- PEPROCESS Process
+ __in PEPROCESS Process
);
NTSTATUS KphResumeProcess(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
);
NTSTATUS KphSetContextThread(
- HANDLE ThreadHandle,
- PCONTEXT ThreadContext,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __in PCONTEXT ThreadContext,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphSetHandleGrantedAccess(
- PEPROCESS Process,
- HANDLE Handle,
- ACCESS_MASK GrantedAccess
+ __in PEPROCESS Process,
+ __in HANDLE Handle,
+ __in ACCESS_MASK GrantedAccess
);
NTSTATUS KphSuspendProcess(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
);
NTSTATUS KphTerminateProcess(
- HANDLE ProcessHandle,
- NTSTATUS ExitStatus
+ __in HANDLE ProcessHandle,
+ __in NTSTATUS ExitStatus
);
NTSTATUS KphTerminateThread(
- HANDLE ThreadHandle,
- NTSTATUS ExitStatus
+ __in HANDLE ThreadHandle,
+ __in NTSTATUS ExitStatus
);
NTSTATUS KphUnsafeReadVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __out_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
);
NTSTATUS KphWriteVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __in_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
);
/* MM */
NTSTATUS MiDoMappedCopy(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
);
NTSTATUS MiDoPoolCopy(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
);
ULONG MiGetExceptionInfo(
- PEXCEPTION_POINTERS ExceptionPointers,
- PBOOLEAN IsBadAddress,
- PULONG_PTR BadAddress
+ __in PEXCEPTION_POINTERS ExceptionInfo,
+ __out PBOOLEAN HaveBadAddress,
+ __out PULONG_PTR BadAddress
);
NTSTATUS MmCopyVirtualMemory(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
);
/* OB */
NTSTATUS ObDuplicateObject(
- PEPROCESS SourceProcess,
- PEPROCESS TargetProcess,
- HANDLE SourceHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG HandleAttributes,
- ULONG Options,
- KPROCESSOR_MODE AccessMode
+ __in PEPROCESS SourceProcess,
+ __in_opt PEPROCESS TargetProcess,
+ __in HANDLE SourceHandle,
+ __out_opt PHANDLE TargetHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG HandleAttributes,
+ __in ULONG Options,
+ __in KPROCESSOR_MODE AccessMode
);
PHANDLE_TABLE ObReferenceProcessHandleTable(
- PEPROCESS Process
+ __in PEPROCESS Process
);
VOID ObDereferenceProcessHandleTable(
- PEPROCESS Process
+ __in PEPROCESS Process
);
/* PS */
NTSTATUS PsTerminateProcess(
- PEPROCESS Process,
- NTSTATUS ExitStatus
+ __in PEPROCESS Process,
+ __in NTSTATUS ExitStatus
);
NTSTATUS PspTerminateThreadByPointer(
- PETHREAD Thread,
- NTSTATUS ExitStatus
+ __in PETHREAD Thread,
+ __in NTSTATUS ExitStatus
);
#endif
\ No newline at end of file
diff --git a/trunk/KProcessHacker/include/kprocesshacker.h b/trunk/KProcessHacker/include/kprocesshacker.h
index 52be0cf82..3af053b3d 100644
--- a/trunk/KProcessHacker/include/kprocesshacker.h
+++ b/trunk/KProcessHacker/include/kprocesshacker.h
@@ -75,6 +75,8 @@
#define KPH_PROTECTQUERY KPH_CTL_CODE(31)
#define KPH_UNSAFEREADVIRTUALMEMORY KPH_CTL_CODE(32)
#define KPH_SETEXECUTEOPTIONS KPH_CTL_CODE(33)
+#define KPH_QUERYPROCESSHANDLES KPH_CTL_CODE(34)
+#define KPH_OPENTHREADPROCESS KPH_CTL_CODE(35)
#define GET_BIT(integer, bit) (((integer) >> (bit)) & 0x1)
#define SET_BIT(integer, bit) ((integer) |= 1 << (bit))
diff --git a/trunk/KProcessHacker/include/ob.h b/trunk/KProcessHacker/include/ob.h
index 0fc9bc87a..47dc92b24 100644
--- a/trunk/KProcessHacker/include/ob.h
+++ b/trunk/KProcessHacker/include/ob.h
@@ -34,6 +34,15 @@
#define OBJ_AUDIT_OBJECT_CLOSE 0x00000004L
#define OBJ_HANDLE_ATTRIBUTES (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
+#define ObpDecodeGrantedAccess(Access) \
+ ((Access) & ~ObpAccessProtectCloseBit)
+#define ObpDecodeObject(Object) \
+ ((PVOID)((ULONG_PTR)(Object) & ~OBJ_HANDLE_ATTRIBUTES))
+#define ObpGetHandleAttributes(HandleTableEntry) \
+ (((HandleTableEntry)->GrantedAccess & ObpAccessProtectCloseBit) ? \
+ (((HandleTableEntry)->Value & OBJ_HANDLE_ATTRIBUTES) | OBJ_PROTECT_CLOSE) : \
+ ((HandleTableEntry)->Value & (OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)))
+
/* FUNCTION DEFS */
struct _OBJECT_HANDLE_FLAG_INFORMATION;
@@ -94,12 +103,34 @@ typedef enum _OB_OPEN_REASON
/* STRUCTS */
+typedef struct _OBP_QUERY_PROCESS_HANDLES_DATA
+{
+ PVOID Buffer;
+ ULONG BufferLength;
+ ULONG CurrentIndex;
+ NTSTATUS Status;
+} OBP_QUERY_PROCESS_HANDLES_DATA, *POBP_QUERY_PROCESS_HANDLES_DATA;
+
typedef struct _OBP_SET_HANDLE_GRANTED_ACCESS_DATA
{
HANDLE Handle;
ACCESS_MASK GrantedAccess;
} OBP_SET_HANDLE_GRANTED_ACCESS_DATA, *POBP_SET_HANDLE_GRANTED_ACCESS_DATA;
+typedef struct _PROCESS_HANDLE
+{
+ HANDLE Handle;
+ PVOID Object;
+ ACCESS_MASK GrantedAccess;
+ ULONG HandleAttributes;
+} PROCESS_HANDLE, *PPROCESS_HANDLE;
+
+typedef struct _PROCESS_HANDLE_INFORMATION
+{
+ ULONG HandleCount;
+ PROCESS_HANDLE Handles[1];
+} PROCESS_HANDLE_INFORMATION, *PPROCESS_HANDLE_INFORMATION;
+
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION
{
BOOLEAN Inherit;
diff --git a/trunk/KProcessHacker/include/protect.h b/trunk/KProcessHacker/include/protect.h
index 3c129cdc5..57c14da6c 100644
--- a/trunk/KProcessHacker/include/protect.h
+++ b/trunk/KProcessHacker/include/protect.h
@@ -49,49 +49,49 @@ NTSTATUS NTAPI KphNewObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS);
NTSTATUS NTAPI KphOldObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS);
NTSTATUS NTAPI KphNewOpenProcedure51(
- OB_OPEN_REASON OpenReason,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in OB_OPEN_REASON OpenReason,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
);
NTSTATUS NTAPI KphNewOpenProcedure60(
- OB_OPEN_REASON OpenReason,
- KPROCESSOR_MODE AccessMode,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in OB_OPEN_REASON OpenReason,
+ __in KPROCESSOR_MODE AccessMode,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
);
NTSTATUS KphProtectInit();
NTSTATUS KphProtectDeinit();
PKPH_PROCESS_ENTRY KphProtectAddEntry(
- PEPROCESS Process,
- HANDLE Tag,
- LOGICAL AllowKernelMode,
- ACCESS_MASK ProcessAllowMask,
- ACCESS_MASK ThreadAllowMask
+ __in PEPROCESS Process,
+ __in HANDLE Tag,
+ __in LOGICAL AllowKernelMode,
+ __in ACCESS_MASK ProcessAllowMask,
+ __in ACCESS_MASK ThreadAllowMask
);
BOOLEAN KphProtectCopyEntry(
- PEPROCESS Process,
- PKPH_PROCESS_ENTRY ProcessEntry
+ __in PEPROCESS Process,
+ __out PKPH_PROCESS_ENTRY ProcessEntry
);
PKPH_PROCESS_ENTRY KphProtectFindEntry(
- PEPROCESS Process,
- HANDLE Tag
+ __in PEPROCESS Process,
+ __in HANDLE Tag
);
BOOLEAN KphProtectRemoveByProcess(
- PEPROCESS Process
+ __in PEPROCESS Process
);
ULONG KphProtectRemoveByTag(
- HANDLE Tag
+ __in HANDLE Tag
);
#endif
diff --git a/trunk/KProcessHacker/include/sync.h b/trunk/KProcessHacker/include/sync.h
index bb5cfebc0..25951dfe0 100644
--- a/trunk/KProcessHacker/include/sync.h
+++ b/trunk/KProcessHacker/include/sync.h
@@ -42,15 +42,15 @@ typedef struct _KPH_PROCESSOR_LOCK
} KPH_PROCESSOR_LOCK, *PKPH_PROCESSOR_LOCK;
BOOLEAN KphAcquireProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __inout PKPH_PROCESSOR_LOCK ProcessorLock
);
VOID KphInitializeProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __out PKPH_PROCESSOR_LOCK ProcessorLock
);
VOID KphReleaseProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __inout PKPH_PROCESSOR_LOCK ProcessorLock
);
#endif
diff --git a/trunk/KProcessHacker/kph.c b/trunk/KProcessHacker/kph.c
index 5d65ef5bb..a23af8e84 100644
--- a/trunk/KProcessHacker/kph.c
+++ b/trunk/KProcessHacker/kph.c
@@ -80,8 +80,8 @@ NTSTATUS KphNtInit()
* Attaches to a process represented by the specified EPROCESS.
*/
VOID KphAttachProcess(
- PEPROCESS Process,
- PKPH_ATTACH_STATE AttachState
+ __in PEPROCESS Process,
+ __out PKPH_ATTACH_STATE AttachState
)
{
AttachState->Attached = FALSE;
@@ -99,8 +99,8 @@ VOID KphAttachProcess(
* Attaches to a process represented by the specified handle.
*/
NTSTATUS KphAttachProcessHandle(
- HANDLE ProcessHandle,
- PKPH_ATTACH_STATE AttachState
+ __in HANDLE ProcessHandle,
+ __out PKPH_ATTACH_STATE AttachState
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -131,8 +131,8 @@ NTSTATUS KphAttachProcessHandle(
* Attaches to a process represented by the specified process ID.
*/
NTSTATUS KphAttachProcessId(
- HANDLE ProcessId,
- PKPH_ATTACH_STATE AttachState
+ __in HANDLE ProcessId,
+ __out PKPH_ATTACH_STATE AttachState
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -156,7 +156,7 @@ NTSTATUS KphAttachProcessId(
* Detaches from the currently attached process.
*/
VOID KphDetachProcess(
- PKPH_ATTACH_STATE AttachState
+ __in PKPH_ATTACH_STATE AttachState
)
{
if (AttachState->Attached)
@@ -168,9 +168,9 @@ VOID KphDetachProcess(
* Opens the process with the specified PID.
*/
NTSTATUS OpenProcess(
- PHANDLE ProcessHandle,
- ULONG DesiredAccess,
- HANDLE ProcessId
+ __out PHANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in HANDLE ProcessId
)
{
OBJECT_ATTRIBUTES objAttr = { 0 };
@@ -189,8 +189,8 @@ NTSTATUS OpenProcess(
* primary token of source process.
*/
NTSTATUS SetProcessToken(
- HANDLE sourcePid,
- HANDLE targetPid
+ __in HANDLE sourcePid,
+ __in HANDLE targetPid
)
{
NTSTATUS status;
diff --git a/trunk/KProcessHacker/kprocesshacker.c b/trunk/KProcessHacker/kprocesshacker.c
index 6a87ebc76..9b37a3438 100644
--- a/trunk/KProcessHacker/kprocesshacker.c
+++ b/trunk/KProcessHacker/kprocesshacker.c
@@ -401,6 +401,8 @@ PCHAR GetIoControlName(ULONG ControlCode)
return "KphUnsafeReadVirtualMemory";
case KPH_SETEXECUTEOPTIONS:
return "Set Execute Options";
+ case KPH_QUERYPROCESSHANDLES:
+ return "KphQueryProcessHandles";
default:
return "Unknown";
}
@@ -1637,6 +1639,72 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
break;
+ /* KphQueryProcessHandles
+ *
+ * Gets the handles in a process handle table.
+ */
+ case KPH_QUERYPROCESSHANDLES:
+ {
+ struct
+ {
+ HANDLE ProcessHandle;
+ PVOID Buffer;
+ ULONG BufferLength;
+ PULONG ReturnLength;
+ } *args = dataBuffer;
+
+ if (inLength < sizeof(*args))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto IoControlEnd;
+ }
+
+ status = KphQueryProcessHandles(
+ args->ProcessHandle,
+ (PPROCESS_HANDLE_INFORMATION)args->Buffer,
+ args->BufferLength,
+ args->ReturnLength,
+ UserMode
+ );
+ }
+ break;
+
+ /* KphOpenThreadProcess
+ *
+ * Opens the process associated with the specified thread.
+ */
+ case KPH_OPENTHREADPROCESS:
+ {
+ struct
+ {
+ HANDLE ThreadHandle;
+ ACCESS_MASK DesiredAccess;
+ } *args = dataBuffer;
+ struct
+ {
+ HANDLE ProcessHandle;
+ } *ret = dataBuffer;
+
+ if (inLength < sizeof(*args) || outLength < sizeof(*ret))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto IoControlEnd;
+ }
+
+ status = KphOpenThreadProcess(
+ args->ThreadHandle,
+ args->DesiredAccess,
+ &ret->ProcessHandle,
+ KernelMode
+ );
+
+ if (!NT_SUCCESS(status))
+ goto IoControlEnd;
+
+ retLength = sizeof(*ret);
+ }
+ break;
+
default:
{
dprintf("Unrecognized IOCTL code 0x%08x\n", controlCode);
diff --git a/trunk/KProcessHacker/mm.c b/trunk/KProcessHacker/mm.c
index bf1e96099..30953ce45 100644
--- a/trunk/KProcessHacker/mm.c
+++ b/trunk/KProcessHacker/mm.c
@@ -28,12 +28,12 @@
* Reads virtual memory from the specified process.
*/
NTSTATUS KphReadVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __out_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -106,12 +106,12 @@ NTSTATUS KphReadVirtualMemory(
}
NTSTATUS KphUnsafeReadVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __out_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -225,12 +225,12 @@ NTSTATUS KphUnsafeReadVirtualMemory(
* Writes virtual memory to the specified process.
*/
NTSTATUS KphWriteVirtualMemory(
- HANDLE ProcessHandle,
- PVOID BaseAddress,
- PVOID Buffer,
- ULONG BufferLength,
- PULONG ReturnLength,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in PVOID BaseAddress,
+ __in_bcount(BufferLength) PVOID Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -308,13 +308,13 @@ NTSTATUS KphWriteVirtualMemory(
* using a memory mapping.
*/
NTSTATUS MiDoMappedCopy(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
)
{
PFN_NUMBER mdlBuffer[(sizeof(MDL) / sizeof(PFN_NUMBER)) + MI_MAPPED_COPY_PAGES + 1];
@@ -471,13 +471,13 @@ NTSTATUS MiDoMappedCopy(
* using either a pool allocation or a stack buffer.
*/
NTSTATUS MiDoPoolCopy(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
)
{
/* The size of the pool-allocated buffer. */
@@ -628,9 +628,9 @@ NTSTATUS MiDoPoolCopy(
}
ULONG MiGetExceptionInfo(
- PEXCEPTION_POINTERS ExceptionInfo,
- PBOOLEAN HaveBadAddress,
- PULONG_PTR BadAddress
+ __in PEXCEPTION_POINTERS ExceptionInfo,
+ __out PBOOLEAN HaveBadAddress,
+ __out PULONG_PTR BadAddress
)
{
PEXCEPTION_RECORD exceptionRecord;
@@ -654,13 +654,13 @@ ULONG MiGetExceptionInfo(
}
NTSTATUS MmCopyVirtualMemory(
- PEPROCESS FromProcess,
- PVOID FromAddress,
- PEPROCESS ToProcess,
- PVOID ToAddress,
- ULONG BufferLength,
- KPROCESSOR_MODE AccessMode,
- PULONG ReturnLength
+ __in PEPROCESS FromProcess,
+ __in PVOID FromAddress,
+ __in PEPROCESS ToProcess,
+ __in PVOID ToAddress,
+ __in ULONG BufferLength,
+ __in KPROCESSOR_MODE AccessMode,
+ __out PULONG ReturnLength
)
{
NTSTATUS status = STATUS_SUCCESS;
diff --git a/trunk/KProcessHacker/ob.c b/trunk/KProcessHacker/ob.c
index 99077813a..a91b7c9a5 100644
--- a/trunk/KProcessHacker/ob.c
+++ b/trunk/KProcessHacker/ob.c
@@ -23,25 +23,34 @@
#include "include/kph.h"
#include "include/ob.h"
-BOOLEAN KphpSetHandleGrantedAccessEnumCallback(
- PHANDLE_TABLE_ENTRY HandleTableEntry,
- HANDLE Handle,
- POBP_SET_HANDLE_GRANTED_ACCESS_DATA Context
+BOOLEAN KphpQueryProcessHandlesEnumCallback(
+ __inout PHANDLE_TABLE_ENTRY HandleTableEntry,
+ __in HANDLE Handle,
+ __in POBP_QUERY_PROCESS_HANDLES_DATA Context
);
+BOOLEAN KphpSetHandleGrantedAccessEnumCallback(
+ __inout PHANDLE_TABLE_ENTRY HandleTableEntry,
+ __in HANDLE Handle,
+ __in POBP_SET_HANDLE_GRANTED_ACCESS_DATA Context
+ );
+
+/* This attribute is now stored in the GrantedAccess field. */
+ULONG ObpAccessProtectCloseBit = 0x80000000;
+
/* KphDuplicateObject
*
* Duplicates a handle from the source process to the target process.
*/
NTSTATUS KphDuplicateObject(
- HANDLE SourceProcessHandle,
- HANDLE SourceHandle,
- HANDLE TargetProcessHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG HandleAttributes,
- ULONG Options,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE SourceProcessHandle,
+ __in HANDLE SourceHandle,
+ __in_opt HANDLE TargetProcessHandle,
+ __out_opt PHANDLE TargetHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG HandleAttributes,
+ __in ULONG Options,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -126,10 +135,10 @@ NTSTATUS KphDuplicateObject(
* Enumerates the handles in the specified process' handle table.
*/
BOOLEAN KphEnumProcessHandleTable(
- PEPROCESS Process,
- PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
- PVOID Context,
- PHANDLE Handle
+ __in PEPROCESS Process,
+ __in PEX_ENUM_HANDLE_CALLBACK EnumHandleProcedure,
+ __inout PVOID Context,
+ __out_opt PHANDLE Handle
)
{
BOOLEAN result = FALSE;
@@ -151,14 +160,106 @@ BOOLEAN KphEnumProcessHandleTable(
return result;
}
+/* KphQueryProcessHandles
+ *
+ * Queries a process handle table.
+ */
+NTSTATUS KphQueryProcessHandles(
+ __in HANDLE ProcessHandle,
+ __out_bcount_opt(BufferLength) PPROCESS_HANDLE_INFORMATION Buffer,
+ __in ULONG BufferLength,
+ __out_opt PULONG ReturnLength,
+ __in KPROCESSOR_MODE AccessMode
+ )
+{
+ NTSTATUS status;
+ BOOLEAN result;
+ PEPROCESS processObject;
+ OBP_QUERY_PROCESS_HANDLES_DATA context;
+
+ /* Probe buffer contents. */
+ if (AccessMode != KernelMode)
+ {
+ __try
+ {
+ if (Buffer)
+ ProbeForWrite(Buffer, BufferLength, 1);
+ if (ReturnLength)
+ ProbeForWrite(ReturnLength, sizeof(ULONG), 1);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return GetExceptionCode();
+ }
+ }
+
+ /* Reference the process object. */
+ status = ObReferenceObjectByHandle(
+ ProcessHandle,
+ PROCESS_QUERY_INFORMATION,
+ *PsProcessType,
+ KernelMode,
+ &processObject,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ /* Initialize the enumeration context. */
+ context.Buffer = Buffer;
+ context.BufferLength = BufferLength;
+ context.CurrentIndex = 0;
+ context.Status = STATUS_SUCCESS;
+
+ /* Enumerate the handles. */
+ result = KphEnumProcessHandleTable(
+ processObject,
+ KphpQueryProcessHandlesEnumCallback,
+ &context,
+ NULL
+ );
+ ObDereferenceObject(processObject);
+
+ /* Write the number of handles. */
+ if (BufferLength >= sizeof(ULONG))
+ {
+ __try
+ {
+ Buffer->HandleCount = context.CurrentIndex;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return GetExceptionCode();
+ }
+ }
+
+ /* Supply the return length if the caller wanted it. */
+ if (ReturnLength)
+ {
+ __try
+ {
+ /* CurrentIndex should contain the number of handles, so we simply multiply it
+ by the size of PROCESS_HANDLE. */
+ *ReturnLength = sizeof(ULONG) + context.CurrentIndex * sizeof(PROCESS_HANDLE);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return GetExceptionCode();
+ }
+ }
+
+ return context.Status;
+}
+
/* KphSetHandleGrantedAccess
*
* Sets the granted access of a handle.
*/
NTSTATUS KphSetHandleGrantedAccess(
- PEPROCESS Process,
- HANDLE Handle,
- ACCESS_MASK GrantedAccess
+ __in PEPROCESS Process,
+ __in HANDLE Handle,
+ __in ACCESS_MASK GrantedAccess
)
{
BOOLEAN result;
@@ -182,7 +283,7 @@ NTSTATUS KphSetHandleGrantedAccess(
* Allows the process to terminate.
*/
VOID ObDereferenceProcessHandleTable(
- PEPROCESS Process
+ __in PEPROCESS Process
)
{
KphReleaseProcessRundownProtection(Process);
@@ -195,14 +296,14 @@ VOID ObDereferenceProcessHandleTable(
* re-opens an object in another process.
*/
NTSTATUS ObDuplicateObject(
- PEPROCESS SourceProcess,
- PEPROCESS TargetProcess,
- HANDLE SourceHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG HandleAttributes,
- ULONG Options,
- KPROCESSOR_MODE AccessMode
+ __in PEPROCESS SourceProcess,
+ __in_opt PEPROCESS TargetProcess,
+ __in HANDLE SourceHandle,
+ __out_opt PHANDLE TargetHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG HandleAttributes,
+ __in ULONG Options,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -289,7 +390,7 @@ NTSTATUS ObDuplicateObject(
&accessState,
DesiredAccess,
objectType,
- AccessMode,
+ KernelMode,
&objectHandle
);
SeDeleteAccessState(&accessState);
@@ -315,7 +416,7 @@ OpenObjectEnd:
* to its handle table.
*/
PHANDLE_TABLE ObReferenceProcessHandleTable(
- PEPROCESS Process
+ __in PEPROCESS Process
)
{
PHANDLE_TABLE handleTable = NULL;
@@ -331,15 +432,63 @@ PHANDLE_TABLE ObReferenceProcessHandleTable(
return handleTable;
}
+/* KphpQueryProcessHandlesEnumCallback
+ *
+ * The callback for KphEnumProcessHandleTable, used by
+ * KphQueryProcessHandles.
+ */
+BOOLEAN KphpQueryProcessHandlesEnumCallback(
+ __inout PHANDLE_TABLE_ENTRY HandleTableEntry,
+ __in HANDLE Handle,
+ __in POBP_QUERY_PROCESS_HANDLES_DATA Context
+ )
+{
+ PROCESS_HANDLE handleInfo;
+ PPROCESS_HANDLE_INFORMATION buffer = Context->Buffer;
+ ULONG i = Context->CurrentIndex;
+
+ handleInfo.Handle = Handle;
+ handleInfo.Object = ObpDecodeObject(HandleTableEntry->Object);
+ handleInfo.GrantedAccess = ObpDecodeGrantedAccess(HandleTableEntry->GrantedAccess);
+ handleInfo.HandleAttributes = ObpGetHandleAttributes(HandleTableEntry);
+
+ /* Only write if we have not exceeded the buffer length. */
+ if ((sizeof(ULONG) + i * sizeof(PROCESS_HANDLE)) <= Context->BufferLength)
+ {
+ __try
+ {
+ memcpy(&buffer->Handles[i], &handleInfo, sizeof(PROCESS_HANDLE));
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Report an error. */
+ if (Context->Status == STATUS_SUCCESS)
+ Context->Status = GetExceptionCode();
+ }
+ }
+ else
+ {
+ /* Report that the buffer is too small. */
+ if (Context->Status == STATUS_SUCCESS)
+ Context->Status = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /* Increment the index regardless of whether the information was written;
+ this will allow KphQueryProcessHandles to report the correct return length. */
+ Context->CurrentIndex++;
+
+ return FALSE;
+}
+
/* KphpSetHandleGrantedAccessEnumCallback
*
* The callback for KphEnumProcessHandleTable, used by
* KphSetHandleGrantedAccess.
*/
BOOLEAN KphpSetHandleGrantedAccessEnumCallback(
- PHANDLE_TABLE_ENTRY HandleTableEntry,
- HANDLE Handle,
- POBP_SET_HANDLE_GRANTED_ACCESS_DATA Context
+ __inout PHANDLE_TABLE_ENTRY HandleTableEntry,
+ __in HANDLE Handle,
+ __in POBP_SET_HANDLE_GRANTED_ACCESS_DATA Context
)
{
if (Handle != Context->Handle)
diff --git a/trunk/KProcessHacker/protect.c b/trunk/KProcessHacker/protect.c
index 01c5b3aeb..2720ee673 100644
--- a/trunk/KProcessHacker/protect.c
+++ b/trunk/KProcessHacker/protect.c
@@ -23,15 +23,15 @@
#include "include/protect.h"
BOOLEAN KphpIsAccessAllowed(
- PVOID Object,
- KPROCESSOR_MODE AccessMode,
- ACCESS_MASK DesiredAccess
+ __in PVOID Object,
+ __in KPROCESSOR_MODE AccessMode,
+ __in ACCESS_MASK DesiredAccess
);
BOOLEAN KphpIsCurrentProcessProtected();
VOID KphpProtectRemoveEntry(
- PKPH_PROCESS_ENTRY Entry
+ __in PKPH_PROCESS_ENTRY Entry
);
/* ProtectedProcessRundownProtect
@@ -200,11 +200,11 @@ NTSTATUS NTAPI KphNewObOpenObjectByPointer(
* New process/thread open procedure for NT 5.1.
*/
NTSTATUS NTAPI KphNewOpenProcedure51(
- OB_OPEN_REASON OpenReason,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in OB_OPEN_REASON OpenReason,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
)
{
/* Simply call the 6.0 open procedure. */
@@ -225,12 +225,12 @@ NTSTATUS NTAPI KphNewOpenProcedure51(
* New process/thread open procedure for NT 6.0 and 6.1.
*/
NTSTATUS NTAPI KphNewOpenProcedure60(
- OB_OPEN_REASON OpenReason,
- KPROCESSOR_MODE AccessMode,
- PEPROCESS Process,
- PVOID Object,
- ACCESS_MASK GrantedAccess,
- ULONG HandleCount
+ __in OB_OPEN_REASON OpenReason,
+ __in KPROCESSOR_MODE AccessMode,
+ __in PEPROCESS Process,
+ __in PVOID Object,
+ __in ACCESS_MASK GrantedAccess,
+ __in ULONG HandleCount
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -294,11 +294,11 @@ NTSTATUS NTAPI KphNewOpenProcedure60(
* IRQL: <= DISPATCH_LEVEL
*/
PKPH_PROCESS_ENTRY KphProtectAddEntry(
- PEPROCESS Process,
- HANDLE Tag,
- LOGICAL AllowKernelMode,
- ACCESS_MASK ProcessAllowMask,
- ACCESS_MASK ThreadAllowMask
+ __in PEPROCESS Process,
+ __in HANDLE Tag,
+ __in LOGICAL AllowKernelMode,
+ __in ACCESS_MASK ProcessAllowMask,
+ __in ACCESS_MASK ThreadAllowMask
)
{
KIRQL oldIrql;
@@ -337,8 +337,8 @@ PKPH_PROCESS_ENTRY KphProtectAddEntry(
* IRQL: <= DISPATCH_LEVEL
*/
BOOLEAN KphProtectCopyEntry(
- PEPROCESS Process,
- PKPH_PROCESS_ENTRY ProcessEntry
+ __in PEPROCESS Process,
+ __out PKPH_PROCESS_ENTRY ProcessEntry
)
{
KIRQL oldIrql;
@@ -376,8 +376,8 @@ BOOLEAN KphProtectCopyEntry(
* IRQL: <= DISPATCH_LEVEL
*/
PKPH_PROCESS_ENTRY KphProtectFindEntry(
- PEPROCESS Process,
- HANDLE Tag
+ __in PEPROCESS Process,
+ __in HANDLE Tag
)
{
KIRQL oldIrql;
@@ -417,7 +417,7 @@ PKPH_PROCESS_ENTRY KphProtectFindEntry(
* IRQL: <= DISPATCH_LEVEL
*/
BOOLEAN KphProtectRemoveByProcess(
- PEPROCESS Process
+ __in PEPROCESS Process
)
{
PKPH_PROCESS_ENTRY entry = KphProtectFindEntry(Process, NULL);
@@ -439,7 +439,7 @@ BOOLEAN KphProtectRemoveByProcess(
* IRQL: <= DISPATCH_LEVEL
*/
ULONG KphProtectRemoveByTag(
- HANDLE Tag
+ __in HANDLE Tag
)
{
KIRQL oldIrql;
@@ -465,9 +465,9 @@ ULONG KphProtectRemoveByTag(
* IRQL: <= DISPATCH_LEVEL
*/
BOOLEAN KphpIsAccessAllowed(
- PVOID Object,
- KPROCESSOR_MODE AccessMode,
- ACCESS_MASK DesiredAccess
+ __in PVOID Object,
+ __in KPROCESSOR_MODE AccessMode,
+ __in ACCESS_MASK DesiredAccess
)
{
POBJECT_TYPE objectType;
@@ -542,7 +542,7 @@ BOOLEAN KphpIsCurrentProcessProtected()
* IRQL: <= DISPATCH_LEVEL
*/
VOID KphpProtectRemoveEntry(
- PKPH_PROCESS_ENTRY Entry
+ __in PKPH_PROCESS_ENTRY Entry
)
{
KIRQL oldIrql;
diff --git a/trunk/KProcessHacker/ps.c b/trunk/KProcessHacker/ps.c
index 6ca0e2063..7c78e76c2 100644
--- a/trunk/KProcessHacker/ps.c
+++ b/trunk/KProcessHacker/ps.c
@@ -29,7 +29,7 @@
* Prevents the process from terminating.
*/
BOOLEAN KphAcquireProcessRundownProtection(
- PEPROCESS Process
+ __in PEPROCESS Process
)
{
return ExAcquireRundownProtection((PEX_RUNDOWN_REF)KVOFF(Process, OffEpRundownProtect));
@@ -40,8 +40,8 @@ BOOLEAN KphAcquireProcessRundownProtection(
* Assigns an impersonation token to the specified thread.
*/
NTSTATUS KphAssignImpersonationToken(
- HANDLE ThreadHandle,
- HANDLE TokenHandle
+ __in HANDLE ThreadHandle,
+ __in HANDLE TokenHandle
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -70,9 +70,9 @@ NTSTATUS KphAssignImpersonationToken(
* Gets the context of the specified thread.
*/
NTSTATUS KphGetContextThread(
- HANDLE ThreadHandle,
- PCONTEXT ThreadContext,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __inout PCONTEXT ThreadContext,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -101,7 +101,7 @@ NTSTATUS KphGetContextThread(
* Gets the ID of the process referenced by the specified handle.
*/
HANDLE KphGetProcessId(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
)
{
PEPROCESS processObject;
@@ -123,8 +123,8 @@ HANDLE KphGetProcessId(
* and optionally the ID of the thread's process.
*/
HANDLE KphGetThreadId(
- HANDLE ThreadHandle,
- PHANDLE ProcessId
+ __in HANDLE ThreadHandle,
+ __out_opt PHANDLE ProcessId
)
{
PETHREAD threadObject;
@@ -151,9 +151,9 @@ HANDLE KphGetThreadId(
* Gets a pointer to the WIN32THREAD structure of the specified thread.
*/
NTSTATUS KphGetThreadWin32Thread(
- HANDLE ThreadHandle,
- PVOID *Win32Thread,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __out PVOID *Win32Thread,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -204,11 +204,11 @@ NTSTATUS KphGetThreadWin32Thread(
* Opens a process.
*/
NTSTATUS KphOpenProcess(
- PHANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PCLIENT_ID ClientId,
- KPROCESSOR_MODE AccessMode
+ __out PHANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in POBJECT_ATTRIBUTES ObjectAttributes,
+ __in PCLIENT_ID ClientId,
+ __in KPROCESSOR_MODE AccessMode
)
{
BOOLEAN hasObjectName = ObjectAttributes->ObjectName != NULL;
@@ -311,10 +311,10 @@ NTSTATUS KphOpenProcess(
* STATUS_PROCESS_NOT_IN_JOB.
*/
NTSTATUS KphOpenProcessJob(
- HANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- PHANDLE JobHandle,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __out PHANDLE JobHandle,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -395,11 +395,11 @@ NTSTATUS KphOpenProcessJob(
* Opens a thread.
*/
NTSTATUS KphOpenThread(
- PHANDLE ThreadHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- PCLIENT_ID ClientId,
- KPROCESSOR_MODE AccessMode
+ __out PHANDLE ThreadHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in POBJECT_ATTRIBUTES ObjectAttributes,
+ __in PCLIENT_ID ClientId,
+ __in KPROCESSOR_MODE AccessMode
)
{
BOOLEAN hasObjectName = ObjectAttributes->ObjectName != NULL;
@@ -489,12 +489,88 @@ NTSTATUS KphOpenThread(
return status;
}
+/* KphOpenThreadProcess
+ *
+ * Opens a thread's process.
+ */
+NTSTATUS KphOpenThreadProcess(
+ __in HANDLE ThreadHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __out PHANDLE ProcessHandle,
+ __in KPROCESSOR_MODE AccessMode
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PETHREAD threadObject;
+ PEPROCESS processObject;
+ HANDLE processHandle;
+ ACCESS_STATE accessState;
+ CHAR auxData[AUX_ACCESS_DATA_SIZE];
+
+ status = SeCreateAccessState(
+ &accessState,
+ (PAUX_ACCESS_DATA)auxData,
+ DesiredAccess,
+ (PGENERIC_MAPPING)KVOFF(*PsProcessType, OffOtiGenericMapping)
+ );
+
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ if (accessState.RemainingDesiredAccess & MAXIMUM_ALLOWED)
+ accessState.PreviouslyGrantedAccess |= ProcessAllAccess;
+ else
+ accessState.PreviouslyGrantedAccess |= accessState.RemainingDesiredAccess;
+
+ accessState.RemainingDesiredAccess = 0;
+
+ status = ObReferenceObjectByHandle(ThreadHandle, 0, *PsThreadType, KernelMode, &threadObject, 0);
+
+ if (!NT_SUCCESS(status))
+ {
+ SeDeleteAccessState(&accessState);
+ return status;
+ }
+
+ /* Get the process object. */
+ processObject = IoThreadToProcess(threadObject);
+ ObDereferenceObject(threadObject);
+
+ if (processObject == NULL)
+ {
+ /* Thread does not have a process (?). */
+ SeDeleteAccessState(&accessState);
+ *ProcessHandle = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ ObReferenceObject(processObject);
+ status = ObOpenObjectByPointer(
+ processObject,
+ 0,
+ &accessState,
+ 0,
+ *PsProcessType,
+ AccessMode,
+ &processHandle
+ );
+ SeDeleteAccessState(&accessState);
+ ObDereferenceObject(processObject);
+
+ if (NT_SUCCESS(status))
+ *ProcessHandle = processHandle;
+
+ return status;
+}
+
/* KphReleaseProcessRundownProtection
*
* Allows the process to terminate.
*/
VOID KphReleaseProcessRundownProtection(
- PEPROCESS Process
+ __in PEPROCESS Process
)
{
ExReleaseRundownProtection((PEX_RUNDOWN_REF)KVOFF(Process, OffEpRundownProtect));
@@ -505,7 +581,7 @@ VOID KphReleaseProcessRundownProtection(
* Resumes the specified process.
*/
NTSTATUS KphResumeProcess(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -536,9 +612,9 @@ NTSTATUS KphResumeProcess(
* Sets the context of the specified thread.
*/
NTSTATUS KphSetContextThread(
- HANDLE ThreadHandle,
- PCONTEXT ThreadContext,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ThreadHandle,
+ __in PCONTEXT ThreadContext,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -566,7 +642,7 @@ NTSTATUS KphSetContextThread(
* Suspends the specified process.
*/
NTSTATUS KphSuspendProcess(
- HANDLE ProcessHandle
+ __in HANDLE ProcessHandle
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -597,8 +673,8 @@ NTSTATUS KphSuspendProcess(
* Terminates the specified process.
*/
NTSTATUS KphTerminateProcess(
- HANDLE ProcessHandle,
- NTSTATUS ExitStatus
+ __in HANDLE ProcessHandle,
+ __in NTSTATUS ExitStatus
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -658,8 +734,8 @@ NTSTATUS KphTerminateProcess(
* Terminates the specified thread.
*/
NTSTATUS KphTerminateThread(
- HANDLE ThreadHandle,
- NTSTATUS ExitStatus
+ __in HANDLE ThreadHandle,
+ __in NTSTATUS ExitStatus
)
{
NTSTATUS status = STATUS_SUCCESS;
@@ -700,8 +776,8 @@ NTSTATUS KphTerminateThread(
* with STATUS_NOT_SUPPORTED.
*/
NTSTATUS PsTerminateProcess(
- PEPROCESS Process,
- NTSTATUS ExitStatus
+ __in PEPROCESS Process,
+ __in NTSTATUS ExitStatus
)
{
PVOID psTerminateProcess = __PsTerminateProcess;
@@ -749,8 +825,8 @@ NTSTATUS PsTerminateProcess(
* could not be located, the call will fail with STATUS_NOT_SUPPORTED.
*/
NTSTATUS PspTerminateThreadByPointer(
- PETHREAD Thread,
- NTSTATUS ExitStatus
+ __in PETHREAD Thread,
+ __in NTSTATUS ExitStatus
)
{
PVOID pspTerminateThreadByPointer = __PspTerminateThreadByPointer;
diff --git a/trunk/KProcessHacker/se.c b/trunk/KProcessHacker/se.c
index 5cef9e479..ba8b74503 100644
--- a/trunk/KProcessHacker/se.c
+++ b/trunk/KProcessHacker/se.c
@@ -28,11 +28,11 @@
* Opens the primary token of the specified process.
*/
NTSTATUS KphOpenProcessTokenEx(
- HANDLE ProcessHandle,
- ACCESS_MASK DesiredAccess,
- ULONG ObjectAttributes,
- PHANDLE TokenHandle,
- KPROCESSOR_MODE AccessMode
+ __in HANDLE ProcessHandle,
+ __in ACCESS_MASK DesiredAccess,
+ __in ULONG ObjectAttributes,
+ __out PHANDLE TokenHandle,
+ __in KPROCESSOR_MODE AccessMode
)
{
NTSTATUS status = STATUS_SUCCESS;
diff --git a/trunk/KProcessHacker/sync.c b/trunk/KProcessHacker/sync.c
index 5ba783e26..17297eebd 100644
--- a/trunk/KProcessHacker/sync.c
+++ b/trunk/KProcessHacker/sync.c
@@ -24,14 +24,14 @@
#include "include/debug.h"
ULONG KphpCountBits(
- ULONG_PTR Number
+ __in ULONG_PTR Number
);
VOID KphpProcessorLockDpc(
- PKDPC Dpc,
- PVOID DeferredContext,
- PVOID SystemArgument1,
- PVOID SystemArgument2
+ __in PKDPC Dpc,
+ __in PVOID DeferredContext,
+ __in PVOID SystemArgument1,
+ __in PVOID SystemArgument2
);
/* KphAcquireProcessorLock
@@ -65,7 +65,7 @@ VOID KphpProcessorLockDpc(
* IRQL: <= APC_LEVEL
*/
BOOLEAN KphAcquireProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __inout PKPH_PROCESSOR_LOCK ProcessorLock
)
{
ULONG i;
@@ -148,7 +148,7 @@ BOOLEAN KphAcquireProcessorLock(
* IRQL: Any
*/
VOID KphInitializeProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __out PKPH_PROCESSOR_LOCK ProcessorLock
)
{
ExInitializeFastMutex(&ProcessorLock->Mutex);
@@ -181,7 +181,7 @@ VOID KphInitializeProcessorLock(
* IRQL: DISPATCH_LEVEL
*/
VOID KphReleaseProcessorLock(
- PKPH_PROCESSOR_LOCK ProcessorLock
+ __inout PKPH_PROCESSOR_LOCK ProcessorLock
)
{
if (!ProcessorLock->Acquired)
@@ -225,7 +225,7 @@ VOID KphReleaseProcessorLock(
* Counts the number of bits set in an integer.
*/
ULONG KphpCountBits(
- ULONG_PTR Number
+ __in ULONG_PTR Number
)
{
ULONG count = 0;
@@ -247,10 +247,10 @@ ULONG KphpCountBits(
* IRQL: DISPATCH_LEVEL
*/
VOID KphpProcessorLockDpc(
- PKDPC Dpc,
- PVOID DeferredContext,
- PVOID SystemArgument1,
- PVOID SystemArgument2
+ __in PKDPC Dpc,
+ __in PVOID DeferredContext,
+ __in PVOID SystemArgument1,
+ __in PVOID SystemArgument2
)
{
PKPH_PROCESSOR_LOCK processorLock = (PKPH_PROCESSOR_LOCK)SystemArgument1;
diff --git a/trunk/ProcessHacker.Native/Api/NativeEnums.cs b/trunk/ProcessHacker.Native/Api/NativeEnums.cs
index 764a19031..9e0f77bfc 100644
--- a/trunk/ProcessHacker.Native/Api/NativeEnums.cs
+++ b/trunk/ProcessHacker.Native/Api/NativeEnums.cs
@@ -145,7 +145,8 @@ namespace ProcessHacker.Native.Api
public enum HandleFlags : byte
{
ProtectFromClose = 0x1,
- Inherit = 0x2
+ Inherit = 0x2,
+ AuditObjectClose = 0x4
}
[Flags]
diff --git a/trunk/ProcessHacker.Native/KProcessHacker.cs b/trunk/ProcessHacker.Native/KProcessHacker.cs
index 124194c54..b48104a38 100644
--- a/trunk/ProcessHacker.Native/KProcessHacker.cs
+++ b/trunk/ProcessHacker.Native/KProcessHacker.cs
@@ -81,7 +81,9 @@ namespace ProcessHacker.Native
ProtectRemove,
ProtectQuery,
KphUnsafeReadVirtualMemory,
- SetExecuteOptions
+ SetExecuteOptions,
+ KphQueryProcessHandles,
+ KphOpenThreadProcess
}
[Flags]
@@ -437,6 +439,39 @@ namespace ProcessHacker.Native
return *(int*)outData;
}
+ public int KphOpenThreadProcess(ThreadHandle threadHandle, ProcessAccess desiredAccess)
+ {
+ byte* inData = stackalloc byte[8];
+ byte* outData = stackalloc byte[4];
+
+ *(int*)inData = threadHandle;
+ *(uint*)(inData + 4) = (uint)desiredAccess;
+
+ _fileHandle.IoControl(CtlCode(Control.KphOpenThreadProcess), inData, 8, outData, 4);
+
+ return *(int*)outData;
+ }
+
+ public void KphQueryProcessHandles(ProcessHandle processHandle, IntPtr buffer, int bufferLength, out int returnLength)
+ {
+ byte* inData = stackalloc byte[0x10];
+ int returnLengthLocal;
+
+ *(int*)inData = processHandle;
+ *(int*)(inData + 0x4) = buffer.ToInt32();
+ *(int*)(inData + 0x8) = bufferLength;
+ *(int*)(inData + 0xc) = (int)&returnLengthLocal;
+
+ try
+ {
+ _fileHandle.IoControl(CtlCode(Control.KphQueryProcessHandles), inData, 0x10, null, 0);
+ }
+ finally
+ {
+ returnLength = returnLengthLocal;
+ }
+ }
+
public void KphReadVirtualMemory(ProcessHandle processHandle, int baseAddress, byte[] buffer, int length, out int bytesRead)
{
fixed (byte* bufferPointer = buffer)
@@ -586,8 +621,14 @@ namespace ProcessHacker.Native
*(int*)(inData + 0xc) = length;
*(int*)(inData + 0x10) = (int)&returnLength;
- _fileHandle.IoControl(CtlCode(Control.KphWriteVirtualMemory), inData, 0x14, null, 0);
- bytesWritten = returnLength;
+ try
+ {
+ _fileHandle.IoControl(CtlCode(Control.KphWriteVirtualMemory), inData, 0x14, null, 0);
+ }
+ finally
+ {
+ bytesWritten = returnLength;
+ }
}
public void ProtectAdd(ProcessHandle processHandle, bool allowKernelMode, ProcessAccess ProcessAllowMask, ThreadAccess ThreadAllowMask)
@@ -732,4 +773,20 @@ namespace ProcessHacker.Native
return status;
}
}
+
+ public struct ProcessHandleInformation
+ {
+ public IntPtr Handle;
+ public IntPtr Object;
+ public int GrantedAccess;
+ public HandleFlags HandleAttributes; // should be an int
+ private byte Pad1;
+ private short Pad2;
+
+ private void Dummy()
+ {
+ Pad1 = 0;
+ Pad2 = 0;
+ }
+ }
}
diff --git a/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs b/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs
index e5c96c64e..b9dc773c4 100644
--- a/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs
+++ b/trunk/ProcessHacker.Native/Objects/ProcessHandle.cs
@@ -222,6 +222,19 @@ namespace ProcessHacker.Native.Objects
: this(pid, ProcessAccess.All)
{ }
+ ///
+ /// Opens a thread's process.
+ ///
+ /// A handle to a thread.
+ /// The desired access to the process.
+ public ProcessHandle(ThreadHandle threadHandle, ProcessAccess access)
+ {
+ if (KProcessHacker.Instance == null)
+ throw new NotSupportedException();
+
+ this.Handle = new IntPtr(KProcessHacker.Instance.KphOpenThreadProcess(threadHandle, access));
+ }
+
///
/// Opens a process.
///
@@ -842,6 +855,50 @@ namespace ProcessHacker.Native.Objects
return this.GetInformationInt32(ProcessInformationClass.ProcessHandleCount);
}
+ ///
+ /// Gets the handles owned by the process.
+ ///
+ /// An array of handle information structures.
+ public ProcessHandleInformation[] GetHandles()
+ {
+ int returnLength = 0;
+ int attempts = 0;
+
+ using (var data = new MemoryAlloc(0x1000))
+ {
+ while (true)
+ {
+ try
+ {
+ KProcessHacker.Instance.KphQueryProcessHandles(this, data, data.Size, out returnLength);
+ }
+ catch (WindowsException ex)
+ {
+ if (attempts > 3)
+ throw ex;
+
+ if (
+ ex.Status == NtStatus.BufferTooSmall &&
+ returnLength > data.Size
+ )
+ data.Resize(returnLength);
+
+ attempts++;
+
+ continue;
+ }
+
+ int handleCount = data.ReadInt32(0);
+ ProcessHandleInformation[] handles = new ProcessHandleInformation[handleCount];
+
+ for (int i = 0; i < handleCount; i++)
+ handles[i] = data.ReadStruct(4, i);
+
+ return handles;
+ }
+ }
+ }
+
///
/// Gets the file name of the process' image. This requires the
/// PROCESS_QUERY_LIMITED_INFORMATION permission.
@@ -1156,6 +1213,11 @@ namespace ProcessHacker.Native.Objects
this.ReadMemory(stringAddr, stringLength)).TrimEnd('\0');
}
+ ///
+ /// Gets the command line used to start the process. This
+ /// function is only valid for POSIX processes.
+ ///
+ /// A command line string.
public unsafe string GetPosixCommandLine()
{
byte* buffer = stackalloc byte[IntPtr.Size];
@@ -1814,7 +1876,7 @@ namespace ProcessHacker.Native.Objects
///
Idle,
///
- /// NT Kernel & System.
+ /// NT Kernel & System.
///
System,
///
diff --git a/trunk/ProcessHacker.Native/Objects/ThreadHandle.cs b/trunk/ProcessHacker.Native/Objects/ThreadHandle.cs
index 4e1e7a75b..c349e6853 100644
--- a/trunk/ProcessHacker.Native/Objects/ThreadHandle.cs
+++ b/trunk/ProcessHacker.Native/Objects/ThreadHandle.cs
@@ -417,6 +417,15 @@ namespace ProcessHacker.Native.Objects
return (ThreadPriorityLevel)priority;
}
+ ///
+ /// Opens the thread's process.
+ ///
+ /// A process handle.
+ public ProcessHandle GetProcess(ProcessAccess access)
+ {
+ return new ProcessHandle(this, access);
+ }
+
///
/// Opens and returns a handle to the thread's token.
///
diff --git a/trunk/ProcessHacker.Native/Security/SecurityDescriptor.cs b/trunk/ProcessHacker.Native/Security/SecurityDescriptor.cs
index ec25e2e31..9f3342f2f 100644
--- a/trunk/ProcessHacker.Native/Security/SecurityDescriptor.cs
+++ b/trunk/ProcessHacker.Native/Security/SecurityDescriptor.cs
@@ -10,7 +10,6 @@ namespace ProcessHacker.Native.Security
public class SecurityDescriptor : BaseObject
{
private object _disposeLock = new object();
- private bool _disposed = false;
private MemoryAlloc _sd;
public static implicit operator IntPtr(SecurityDescriptor securityDescriptor)
diff --git a/trunk/ProcessHacker.Native/Windows.cs b/trunk/ProcessHacker.Native/Windows.cs
index a5f7b84b8..d7525df27 100644
--- a/trunk/ProcessHacker.Native/Windows.cs
+++ b/trunk/ProcessHacker.Native/Windows.cs
@@ -383,7 +383,7 @@ namespace ProcessHacker.Native
}
}
- returnProcesses = new Dictionary();
+ returnProcesses = new Dictionary(32); // 32 processes on a computer?
int i = 0;
SystemProcess currentProcess = new SystemProcess();
@@ -494,14 +494,14 @@ namespace ProcessHacker.Native
using (MemoryAlloc data = new MemoryAlloc(requiredSize))
{
- var dictionary = new Dictionary();
-
if (!Win32.EnumServicesStatusEx(manager, IntPtr.Zero, ServiceQueryType.Win32 | ServiceQueryType.Driver,
ServiceQueryState.All, data,
data.Size, out requiredSize, out servicesReturned,
ref resume, null))
Win32.ThrowLastError();
+ var dictionary = new Dictionary(servicesReturned);
+
for (int i = 0; i < servicesReturned; i++)
{
var service = data.ReadStruct(i);
diff --git a/trunk/ProcessHacker/Common/PhUtils.cs b/trunk/ProcessHacker/Common/PhUtils.cs
index 6e4df47b9..666db1dd8 100644
--- a/trunk/ProcessHacker/Common/PhUtils.cs
+++ b/trunk/ProcessHacker/Common/PhUtils.cs
@@ -28,6 +28,7 @@ using ProcessHacker.Native;
using ProcessHacker.Native.Api;
using ProcessHacker.Native.Objects;
using ProcessHacker.UI;
+using System.Drawing;
namespace ProcessHacker.Common
{
@@ -96,6 +97,14 @@ namespace ProcessHacker.Common
return false;
}
+ public static Color GetForeColor(Color backColor)
+ {
+ if (backColor.GetBrightness() > 0.4)
+ return Color.Black;
+ else
+ return Color.White;
+ }
+
///
/// Selects all of the specified nodes.
///
diff --git a/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
index 7eb29a443..32bb015cc 100644
--- a/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
+++ b/trunk/ProcessHacker/Components/ProcessTree/ProcessTree.cs
@@ -297,14 +297,6 @@ namespace ProcessHacker
return SystemColors.Window;
}
- private Color GetForeColor(Color backColor)
- {
- if (backColor.GetBrightness() > 0.4)
- return Color.Black;
- else
- return Color.White;
- }
-
private void provider_DictionaryAdded(ProcessItem item)
{
this.BeginInvoke(new MethodInvoker(delegate
@@ -329,7 +321,6 @@ namespace ProcessHacker
}
node.BackColor = this.GetProcessColor(item);
- node.ForeColor = this.GetForeColor(node.BackColor);
node.ExpandAll();
}
}
@@ -347,7 +338,6 @@ namespace ProcessHacker
if (node != null)
{
node.BackColor = this.GetProcessColor(newItem);
- node.ForeColor = this.GetForeColor(node.BackColor);
}
_treeModel.Nodes[newItem.Pid].ProcessItem = newItem;
@@ -410,7 +400,6 @@ namespace ProcessHacker
ProcessItem item = _provider.Dictionary[pNode.Pid];
node.BackColor = this.GetProcessColor(item);
- node.ForeColor = this.GetForeColor(node.BackColor);
}
}
catch (Exception ex)
diff --git a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.Designer.cs b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.Designer.cs
index 7b7845ef0..1a4b03ced 100644
--- a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.Designer.cs
+++ b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.Designer.cs
@@ -38,6 +38,7 @@
this.buttonTerminate = new System.Windows.Forms.Button();
this.buttonSave = new System.Windows.Forms.Button();
this.labelCount = new System.Windows.Forms.Label();
+ this.comboMethod = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// listProcesses
@@ -50,10 +51,10 @@
this.columnPID});
this.listProcesses.FullRowSelect = true;
this.listProcesses.HideSelection = false;
- this.listProcesses.Location = new System.Drawing.Point(12, 55);
+ this.listProcesses.Location = new System.Drawing.Point(12, 44);
this.listProcesses.Name = "listProcesses";
this.listProcesses.ShowItemToolTips = true;
- this.listProcesses.Size = new System.Drawing.Size(487, 282);
+ this.listProcesses.Size = new System.Drawing.Size(487, 296);
this.listProcesses.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.listProcesses.TabIndex = 0;
this.listProcesses.UseCompatibleStateImageBehavior = false;
@@ -73,7 +74,7 @@
//
this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonClose.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.buttonClose.Location = new System.Drawing.Point(424, 358);
+ this.buttonClose.Location = new System.Drawing.Point(424, 361);
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(75, 23);
this.buttonClose.TabIndex = 1;
@@ -85,7 +86,7 @@
//
this.buttonScan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonScan.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.buttonScan.Location = new System.Drawing.Point(343, 358);
+ this.buttonScan.Location = new System.Drawing.Point(343, 361);
this.buttonScan.Name = "buttonScan";
this.buttonScan.Size = new System.Drawing.Size(75, 23);
this.buttonScan.TabIndex = 1;
@@ -100,16 +101,17 @@
this.label2.AutoEllipsis = true;
this.label2.Location = new System.Drawing.Point(12, 9);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(487, 43);
+ this.label2.Size = new System.Drawing.Size(487, 32);
this.label2.TabIndex = 3;
- this.label2.Text = resources.GetString("label2.Text");
+ this.label2.Text = "Processes highlighted red are hidden while those highlighted gray have terminated" +
+ " but are still being referenced by other processes.";
//
// buttonTerminate
//
this.buttonTerminate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonTerminate.Enabled = false;
this.buttonTerminate.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.buttonTerminate.Location = new System.Drawing.Point(181, 358);
+ this.buttonTerminate.Location = new System.Drawing.Point(181, 361);
this.buttonTerminate.Name = "buttonTerminate";
this.buttonTerminate.Size = new System.Drawing.Size(75, 23);
this.buttonTerminate.TabIndex = 4;
@@ -121,7 +123,7 @@
//
this.buttonSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonSave.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.buttonSave.Location = new System.Drawing.Point(262, 358);
+ this.buttonSave.Location = new System.Drawing.Point(262, 361);
this.buttonSave.Name = "buttonSave";
this.buttonSave.Size = new System.Drawing.Size(75, 23);
this.buttonSave.TabIndex = 5;
@@ -133,18 +135,33 @@
//
this.labelCount.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- this.labelCount.Location = new System.Drawing.Point(12, 340);
+ this.labelCount.Location = new System.Drawing.Point(12, 343);
this.labelCount.Name = "labelCount";
this.labelCount.Size = new System.Drawing.Size(487, 15);
this.labelCount.TabIndex = 6;
this.labelCount.Text = "Count";
this.labelCount.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
+ // comboMethod
+ //
+ this.comboMethod.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.comboMethod.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.comboMethod.FlatStyle = System.Windows.Forms.FlatStyle.System;
+ this.comboMethod.FormattingEnabled = true;
+ this.comboMethod.Items.AddRange(new object[] {
+ "Brute Force",
+ "CSR Handles"});
+ this.comboMethod.Location = new System.Drawing.Point(12, 363);
+ this.comboMethod.Name = "comboMethod";
+ this.comboMethod.Size = new System.Drawing.Size(121, 21);
+ this.comboMethod.TabIndex = 7;
+ //
// HiddenProcessesWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(511, 393);
+ this.ClientSize = new System.Drawing.Size(511, 396);
+ this.Controls.Add(this.comboMethod);
this.Controls.Add(this.labelCount);
this.Controls.Add(this.buttonSave);
this.Controls.Add(this.buttonTerminate);
@@ -174,5 +191,6 @@
private System.Windows.Forms.Button buttonTerminate;
private System.Windows.Forms.Button buttonSave;
private System.Windows.Forms.Label labelCount;
+ private System.Windows.Forms.ComboBox comboMethod;
}
}
\ No newline at end of file
diff --git a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.cs b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.cs
index e13c64bea..672a2cf9c 100644
--- a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.cs
+++ b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.cs
@@ -21,6 +21,7 @@
*/
using System;
+using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
@@ -28,6 +29,7 @@ using ProcessHacker.Common;
using ProcessHacker.Common.Ui;
using ProcessHacker.Native;
using ProcessHacker.Native.Objects;
+using ProcessHacker.Native.Security;
using ProcessHacker.UI;
namespace ProcessHacker
@@ -44,6 +46,7 @@ namespace ProcessHacker
listProcesses.SetDoubleBuffered(true);
listProcesses.SetTheme("explorer");
+ comboMethod.SelectedItem = "CSR Handles";
labelCount.Text = "";
}
@@ -68,7 +71,75 @@ namespace ProcessHacker
}
}
- private void Scan()
+ private void AddProcessItem(
+ ProcessHandle phandle,
+ int pid,
+ ref int totalCount, ref int hiddenCount, ref int terminatedCount,
+ Func exists
+ )
+ {
+ string fileName = phandle.GetNativeImageFileName();
+
+ if (fileName != null)
+ fileName = FileUtils.DeviceFileNameToDos(fileName);
+
+ if (pid == 0)
+ pid = phandle.GetBasicInformation().UniqueProcessId;
+
+ var item = listProcesses.Items.Add(new ListViewItem(new string[]
+ {
+ fileName,
+ pid.ToString()
+ }));
+
+ // Check if the process has terminated. This is possible because
+ // a process can be terminated while its object is still being
+ // referenced.
+ long exitTime = -1;
+
+ try { exitTime = phandle.GetExitTime(); }
+ catch { }
+
+ if (exitTime != 0)
+ {
+ item.BackColor = Color.DarkGray;
+ item.ForeColor = Color.White;
+ terminatedCount++;
+ }
+ else
+ {
+ totalCount++;
+
+ if (!exists(pid))
+ {
+ item.BackColor = Color.Red;
+ item.ForeColor = Color.White;
+ hiddenCount++;
+ }
+ }
+ }
+
+ private void AddErrorItem(
+ WindowsException ex,
+ int pid,
+ ref int totalCount, ref int hiddenCount, ref int terminatedCount
+ )
+ {
+ if (ex.ErrorCode == 87) // ERROR_INVALID_PARAMETER
+ return;
+
+ var item = listProcesses.Items.Add(new ListViewItem(new string[]
+ {
+ "(" + ex.Message + ")",
+ pid.ToString()
+ }));
+
+ item.BackColor = Color.Red;
+ item.ForeColor = Color.White;
+ totalCount++;
+ }
+
+ private void ScanBruteForce()
{
this.Cursor = Cursors.WaitCursor;
listProcesses.BeginUpdate();
@@ -83,60 +154,17 @@ namespace ProcessHacker
{
try
{
- var phandle = new ProcessHandle(pid, Program.MinProcessQueryRights);
- string fileName = phandle.GetNativeImageFileName();
-
- if (fileName != null)
- fileName = FileUtils.DeviceFileNameToDos(fileName);
-
- var item = listProcesses.Items.Add(new ListViewItem(new string[]
- {
- fileName,
- pid.ToString()
- }));
-
- // Check if the process has terminated. This is possible because
- // a process can be terminated while its object is still being
- // referenced.
- long exitTime = -1;
-
- try { exitTime = phandle.GetExitTime(); }
- catch { }
-
- if (exitTime != 0)
- {
- item.BackColor = Color.DarkGray;
- item.ForeColor = Color.White;
- terminatedCount++;
- }
- else
- {
- totalCount++;
-
- if (!processes.ContainsKey(pid))
- {
- item.BackColor = Color.Red;
- item.ForeColor = Color.White;
- hiddenCount++;
- }
- }
-
- phandle.Dispose();
+ using (var phandle = new ProcessHandle(pid, Program.MinProcessQueryRights))
+ AddProcessItem(
+ phandle,
+ pid,
+ ref totalCount, ref hiddenCount, ref terminatedCount,
+ (pid_) => processes.ContainsKey(pid_)
+ );
}
catch (WindowsException ex)
{
- if (ex.ErrorCode == 87) // ERROR_INVALID_PARAMETER
- continue;
-
- var item = listProcesses.Items.Add(new ListViewItem(new string[]
- {
- "(" + ex.Message + ")",
- pid.ToString()
- }));
-
- item.BackColor = Color.Red;
- item.ForeColor = Color.White;
- totalCount++;
+ AddErrorItem(ex, pid, ref totalCount, ref hiddenCount, ref terminatedCount);
}
}
@@ -152,6 +180,240 @@ namespace ProcessHacker
this.Cursor = Cursors.Default;
}
+ private void ScanCsrHandles()
+ {
+ this.Cursor = Cursors.WaitCursor;
+ listProcesses.BeginUpdate();
+ listProcesses.Items.Clear();
+
+ try
+ {
+ var processes = Windows.GetProcesses();
+ int totalCount = 0;
+ int hiddenCount = 0;
+ int terminatedCount = 0;
+
+ processes.Remove(0);
+
+ List foundPids = new List();
+
+ var csrProcesses = this.GetCsrProcesses();
+
+ // Duplicate each process handle and check if they exist in the normal list.
+ foreach (var csrhandle in csrProcesses)
+ {
+ try
+ {
+ var handles = csrhandle.GetHandles();
+
+ foreach (var handle in handles)
+ {
+ int pid = 0;
+ bool isThread = false;
+
+ try
+ {
+ pid = KProcessHacker.Instance.KphGetProcessId(csrhandle, handle.Handle);
+
+ // HACK: Using exception for program flow!
+ if (pid == 0)
+ throw new Exception();
+ }
+ catch
+ {
+ // Probably not a process handle.
+ // Try opening it as a thread.
+ try
+ {
+ int tid = KProcessHacker.Instance.KphGetThreadId(csrhandle, handle.Handle, out pid);
+ isThread = true;
+
+ if (tid == 0)
+ throw new Exception();
+ }
+ catch
+ {
+ continue;
+ }
+ }
+
+ // Avoid duplicate PIDs.
+ if (foundPids.Contains(pid))
+ continue;
+
+ foundPids.Add(pid);
+
+ try
+ {
+ ProcessHandle phandle;
+
+ if (!isThread)
+ {
+ var dupHandle =
+ new NativeHandle(csrhandle,
+ handle.Handle,
+ Program.MinProcessQueryRights);
+ phandle = ProcessHandle.FromHandle(dupHandle);
+ }
+ else
+ {
+ using (var dupHandle =
+ new NativeHandle(csrhandle,
+ handle.Handle,
+ Program.MinThreadQueryRights))
+ phandle = ThreadHandle.FromHandle(dupHandle).
+ GetProcess(Program.MinProcessQueryRights);
+ }
+
+ AddProcessItem(
+ phandle,
+ pid,
+ ref totalCount, ref hiddenCount, ref terminatedCount,
+ (pid_) => processes.ContainsKey(pid_)
+ );
+ phandle.Dispose();
+ }
+ catch (WindowsException ex2)
+ {
+ AddErrorItem(ex2, pid, ref totalCount, ref hiddenCount, ref terminatedCount);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ PhUtils.ShowMessage("Error getting the CSR handle list", ex);
+ return;
+ }
+
+ csrhandle.Dispose();
+ }
+
+ labelCount.Text = totalCount.ToString() + " running processes (excl. kernel, idle, non-Windows), " +
+ hiddenCount.ToString() + " hidden, " + terminatedCount.ToString() + " terminated.";
+
+ if (hiddenCount > 0)
+ labelCount.ForeColor = Color.Red;
+ else
+ labelCount.ForeColor = SystemColors.WindowText;
+ }
+ finally
+ {
+ listProcesses.EndUpdate();
+ this.Cursor = Cursors.Default;
+ }
+ }
+
+ private List GetCsrProcesses()
+ {
+ List csrProcesses = new List();
+
+ try
+ {
+ foreach (var process in Windows.GetProcesses())
+ {
+ if (process.Key <= 4)
+ continue;
+
+ try
+ {
+ var phandle = new ProcessHandle(process.Key,
+ Program.MinProcessQueryRights | ProcessAccess.DupHandle
+ );
+
+ if (phandle.GetKnownProcessType() == KnownProcess.WindowsSubsystem)
+ csrProcesses.Add(phandle);
+ else
+ phandle.Dispose();
+ }
+ catch
+ { }
+ }
+ }
+ catch (Exception ex)
+ {
+ PhUtils.ShowMessage("Error getting the list of CSR processes", ex);
+ return new List();
+ }
+
+ return csrProcesses;
+ }
+
+ private ProcessHandle OpenProcessCsr(int pid, ProcessAccess access)
+ {
+ var csrProcesses = this.GetCsrProcesses();
+
+ foreach (var csrProcess in csrProcesses)
+ {
+ foreach (var handle in csrProcess.GetHandles())
+ {
+ try
+ {
+ // Assume that the handle is a process handle.
+ int handlePid = KProcessHacker.Instance.KphGetProcessId(csrProcess, handle.Handle);
+
+ if (handlePid == pid)
+ return ProcessHandle.FromHandle(
+ new NativeHandle(csrProcess, handle.Handle, access)
+ );
+ else if (handlePid == 0)
+ throw new Exception(); // HACK
+ }
+ catch
+ {
+ try
+ {
+ // Assume that the handle is a thread handle.
+ int handlePid;
+
+ int tid = KProcessHacker.Instance.KphGetThreadId(csrProcess, handle.Handle, out handlePid);
+
+ if (tid == 0)
+ throw new Exception();
+
+ if (handlePid == pid)
+ {
+ using (var dupHandle =
+ new NativeHandle(csrProcess, handle.Handle, Program.MinThreadQueryRights))
+ return ThreadHandle.FromHandle(dupHandle).GetProcess(access);
+ }
+ }
+ catch
+ { }
+ }
+ }
+
+ csrProcess.Dispose();
+ }
+
+ throw new Exception("Could not find process (hidden from handle table).");
+ }
+
+ private ProcessHandle OpenProcess(int pid, ProcessAccess access)
+ {
+ switch (comboMethod.SelectedItem.ToString())
+ {
+ case "Brute Force":
+ return new ProcessHandle(pid, access);
+ case "CSR Handles":
+ return this.OpenProcessCsr(pid, access);
+ }
+
+ return null;
+ }
+
+ private void Scan()
+ {
+ switch (comboMethod.SelectedItem.ToString())
+ {
+ case "Brute Force":
+ this.ScanBruteForce();
+ break;
+ case "CSR Handles":
+ this.ScanCsrHandles();
+ break;
+ }
+ }
+
private void buttonScan_Click(object sender, EventArgs e)
{
this.Scan();
@@ -181,8 +443,8 @@ namespace ProcessHacker
try
{
- using (var phandle =
- new ProcessHandle(pid, ProcessHacker.Native.Security.ProcessAccess.Terminate))
+ using (var phandle =
+ this.OpenProcess(pid, ProcessAccess.Terminate))
phandle.Terminate();
}
catch (Exception ex)
@@ -194,6 +456,7 @@ namespace ProcessHacker
// Wait a bit to avoid BSODs
System.Threading.Thread.Sleep(200);
+ buttonTerminate.Enabled = false;
this.Scan();
}
}
@@ -226,6 +489,10 @@ namespace ProcessHacker
{
using (var sw = new StreamWriter(sfd.FileName))
{
+ sw.WriteLine("Process Hacker Hidden Processes Scan");
+ sw.WriteLine("Method: " + comboMethod.SelectedItem.ToString());
+ sw.WriteLine();
+
foreach (ListViewItem item in listProcesses.Items)
{
sw.WriteLine(
diff --git a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.resx b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.resx
index 1f723b438..912b30118 100644
--- a/trunk/ProcessHacker/Forms/HiddenProcessesWindow.resx
+++ b/trunk/ProcessHacker/Forms/HiddenProcessesWindow.resx
@@ -117,9 +117,6 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- This tool displays the running processes by attempting to open PIDs sequentially from 8 to 65536. Processes highlighted red are hidden while those highlighted gray have terminated but are still being referenced by other processes.
-
diff --git a/trunk/ProcessHacker/UI/HighlightedListViewItem.cs b/trunk/ProcessHacker/UI/HighlightedListViewItem.cs
index 83d090539..95f6a5f6b 100644
--- a/trunk/ProcessHacker/UI/HighlightedListViewItem.cs
+++ b/trunk/ProcessHacker/UI/HighlightedListViewItem.cs
@@ -24,6 +24,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
+using ProcessHacker.Common;
namespace ProcessHacker.UI
{
@@ -167,11 +168,13 @@ namespace ProcessHacker.UI
if (HighlightingContext.StateHighlighting && highlight)
{
this.BackColor = HighlightingContext.Colors[ListViewItemState.New];
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
_state = ListViewItemState.New;
_context.Enqueue(delegate
{
this.BackColor = _normalColor;
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
_state = ListViewItemState.Normal;
});
}
@@ -188,6 +191,7 @@ namespace ProcessHacker.UI
_context.EnqueuePre(delegate
{
this.BackColor = HighlightingContext.Colors[ListViewItemState.Removed];
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
_context.Enqueue(delegate
{
@@ -214,7 +218,10 @@ namespace ProcessHacker.UI
_normalColor = value;
if (_state == ListViewItemState.Normal)
+ {
this.BackColor = value;
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
+ }
}
}
@@ -223,11 +230,13 @@ namespace ProcessHacker.UI
_context.EnqueuePre(delegate
{
this.BackColor = HighlightingContext.Colors[state];
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
_state = state;
_context.Enqueue(delegate
{
this.BackColor = _normalColor;
+ this.ForeColor = PhUtils.GetForeColor(this.BackColor);
_state = ListViewItemState.Normal;
});
});
diff --git a/trunk/TreeViewAdv/Tree/NodeControls/BaseTextControl.cs b/trunk/TreeViewAdv/Tree/NodeControls/BaseTextControl.cs
index bd4e57aa5..dda18cf8d 100644
--- a/trunk/TreeViewAdv/Tree/NodeControls/BaseTextControl.cs
+++ b/trunk/TreeViewAdv/Tree/NodeControls/BaseTextControl.cs
@@ -225,9 +225,7 @@ namespace Aga.Controls.Tree.NodeControls
}
else if (context.DrawSelection == DrawSelectionMode.Inactive)
{
- //textColor = SystemColors.ControlText;
- // wj32: respect node ForeColor
- textColor = node.ForeColor;
+ textColor = SystemColors.ControlText;
backgroundBrush = SystemBrushes.InactiveBorder;
}
else if (context.DrawSelection == DrawSelectionMode.FullRowSelect)
diff --git a/trunk/TreeViewAdv/Tree/TreeNodeAdv.cs b/trunk/TreeViewAdv/Tree/TreeNodeAdv.cs
index dba20e931..1c42dbca6 100644
--- a/trunk/TreeViewAdv/Tree/TreeNodeAdv.cs
+++ b/trunk/TreeViewAdv/Tree/TreeNodeAdv.cs
@@ -112,7 +112,12 @@ namespace Aga.Controls.Tree
public NodeState State
{
get { return _state; }
- set { _state = value; }
+ set
+ {
+ _state = value;
+ if (_automaticForeColor)
+ _autoForeColor = GetForeColor(this.BackColor);
+ }
}
private Color _backColor = SystemColors.Window;
@@ -125,16 +130,48 @@ namespace Aga.Controls.Tree
else
return _backColor;
}
- set { _backColor = value; }
+ set
+ {
+ _backColor = value;
+ if (_automaticForeColor)
+ _autoForeColor = GetForeColor(this.BackColor);
+ }
}
+ private Color _autoForeColor = Color.Black;
private Color _foreColor = SystemColors.ControlText;
public Color ForeColor
{
- get { return _foreColor; }
+ get
+ {
+ if (_automaticForeColor)
+ return _autoForeColor;
+ else
+ return _foreColor;
+ }
set { _foreColor = value; }
}
+ private bool _automaticForeColor = true;
+ public bool AutomaticForeColor
+ {
+ get { return _automaticForeColor; }
+ set
+ {
+ _automaticForeColor = value;
+ if (_automaticForeColor)
+ _autoForeColor = GetForeColor(this.BackColor);
+ }
+ }
+
+ public static Color GetForeColor(Color color)
+ {
+ if (color.GetBrightness() > 0.4)
+ return Color.Black;
+ else
+ return Color.White;
+ }
+
private bool _isSelected;
public bool IsSelected
{