diff --git a/trunk/CHANGELOG.txt b/trunk/CHANGELOG.txt
index 1b0a2bef4..52b8a8c09 100644
--- a/trunk/CHANGELOG.txt
+++ b/trunk/CHANGELOG.txt
@@ -5,6 +5,7 @@ Process Hacker
* KProcessHacker can now perform process memory reading/writing
by itself and does not require MmCopyVirtualMemory
* KProcessHacker can now bypass all handle-opening protections
+ * Experimental process protection feature
* Ability to set handle flags such as protect-from-close and inherit
* Better highlighting
* Terminator test: TD1 (debugs a process and closes the debug object)
diff --git a/trunk/KProcessHacker/hook.c b/trunk/KProcessHacker/hook.c
new file mode 100644
index 000000000..93b440524
--- /dev/null
+++ b/trunk/KProcessHacker/hook.c
@@ -0,0 +1,177 @@
+/*
+ * Process Hacker Driver -
+ * hooks
+ *
+ * Copyright (C) 2009 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include "include/hook.h"
+
+typedef struct _MAPPED_MDL
+{
+ PMDL Mdl;
+ PVOID Address;
+} MAPPED_MDL, *PMAPPED_MDL;
+
+NTSTATUS KphpCreateMappedMdl(
+ PVOID Address,
+ ULONG Length,
+ PMAPPED_MDL MappedMdl
+ );
+
+VOID KphpFreeMappedMdl(
+ PMAPPED_MDL MappedMdl
+ );
+
+/* KphHook
+ *
+ * Hooks a kernel-mode function.
+ * WARNING: DO NOT HOOK A FUNCTION THAT IS CALLABLE ABOVE PASSIVE_LEVEL.
+ */
+NTSTATUS KphHook(
+ PKPH_HOOK Hook
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ KIRQL oldIrql;
+ MAPPED_MDL mappedMdl;
+ PCHAR function;
+
+ status = KphpCreateMappedMdl(
+ Hook->Function,
+ 5,
+ &mappedMdl
+ );
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ function = (PCHAR)mappedMdl.Address;
+ /* Raise to APC_LEVEL to prevent drivers calling the function while we're patching it. */
+ /* If they do, it's their problem because the function we're patching should only be
+ called at PASSIVE_LEVEL anyway (see hook.h for definition of KPH_HOOK). */
+ KeRaiseIrql(APC_LEVEL, &oldIrql);
+ memcpy(Hook->Bytes, function, 5);
+ Hook->Hooked = TRUE;
+ /* jmp Target */
+ *function = 0xe9;
+ *(PULONG_PTR)(function + 1) = (ULONG_PTR)Hook->Target - (ULONG_PTR)Hook->Function - 5;
+ /* Lower the IRQL back. */
+ KeLowerIrql(oldIrql);
+
+ KphpFreeMappedMdl(&mappedMdl);
+
+ return status;
+}
+
+/* KphUnhook
+ *
+ * Unhooks a kernel-mode function.
+ * WARNING: DO NOT UNHOOK A FUNCTION THAT IS CALLABLE ABOVE PASSIVE_LEVEL.
+ */
+NTSTATUS KphUnhook(
+ PKPH_HOOK Hook
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ KIRQL oldIrql;
+ MAPPED_MDL mappedMdl;
+
+ if (!Hook->Hooked)
+ return STATUS_UNSUCCESSFUL;
+
+ status = KphpCreateMappedMdl(
+ Hook->Function,
+ 5,
+ &mappedMdl
+ );
+
+ if (!NT_SUCCESS(status))
+ return status;
+
+ KeRaiseIrql(APC_LEVEL, &oldIrql);
+ memcpy(mappedMdl.Address, Hook->Bytes, 5);
+ Hook->Hooked = FALSE;
+ KeLowerIrql(oldIrql);
+
+ KphpFreeMappedMdl(&mappedMdl);
+
+ return status;
+}
+
+/* KphpCreateMappedMdl
+ *
+ * Creates and maps a MDL.
+ */
+NTSTATUS KphpCreateMappedMdl(
+ PVOID Address,
+ ULONG Length,
+ PMAPPED_MDL MappedMdl
+ )
+{
+ PMDL mdl;
+
+ MappedMdl->Mdl = NULL;
+ MappedMdl->Address = NULL;
+
+ mdl = IoAllocateMdl(Address, Length, FALSE, FALSE, NULL);
+
+ if (mdl == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ MmBuildMdlForNonPagedPool(mdl);
+ mdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA;
+ MappedMdl->Address = MmMapLockedPagesSpecifyCache(
+ mdl,
+ KernelMode,
+ MmNonCached,
+ NULL,
+ FALSE,
+ HighPagePriority
+ );
+ MappedMdl->Mdl = mdl;
+
+ if (!MappedMdl->Address)
+ {
+ KphpFreeMappedMdl(MappedMdl);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/* KphpFreeMappedMdl
+ *
+ * Unmaps and frees a MDL.
+ */
+VOID KphpFreeMappedMdl(
+ PMAPPED_MDL MappedMdl
+ )
+{
+ if (MappedMdl->Mdl != NULL)
+ {
+ if (MappedMdl->Address != NULL)
+ {
+ MmUnmapLockedPages(MappedMdl->Address, MappedMdl->Mdl);
+ MappedMdl->Address = NULL;
+ }
+
+ IoFreeMdl(MappedMdl->Mdl);
+ MappedMdl->Mdl = NULL;
+ }
+}
diff --git a/trunk/KProcessHacker/i386/kprocesshacker.sys b/trunk/KProcessHacker/i386/kprocesshacker.sys
index ca1b9d535..300961714 100644
Binary files a/trunk/KProcessHacker/i386/kprocesshacker.sys and b/trunk/KProcessHacker/i386/kprocesshacker.sys differ
diff --git a/trunk/KProcessHacker/include/hook.h b/trunk/KProcessHacker/include/hook.h
new file mode 100644
index 000000000..072acc3a5
--- /dev/null
+++ b/trunk/KProcessHacker/include/hook.h
@@ -0,0 +1,60 @@
+/*
+ * Process Hacker Driver -
+ * hooks
+ *
+ * Copyright (C) 2009 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 .
+ */
+
+#ifndef _HOOK_H
+#define _HOOK_H
+
+#include "kph.h"
+
+#define KPH_DEFINE_HOOK_CALL(Name, Arguments, Hook) \
+ __declspec(naked) Name(Arguments) \
+ { \
+ __asm lea eax, Hook \
+ __asm mov eax, [eax+KPH_HOOK.Function] \
+ __asm add eax, 5 \
+ __asm push ebp \
+ __asm mov ebp, esp \
+ __asm jmp eax \
+ } \
+
+typedef struct _KPH_HOOK
+{
+ /* The address of the hooked function.
+ Should NOT be a function that is callable above PASSIVE_LEVEL. */
+ PVOID Function;
+ /* The address of the new function. */
+ PVOID Target;
+ /* Whether the function is hooked. */
+ BOOLEAN Hooked;
+ /* The original first 5 bytes. */
+ CHAR Bytes[5];
+} KPH_HOOK, *PKPH_HOOK;
+
+NTSTATUS KphHook(
+ PKPH_HOOK Hook
+ );
+
+NTSTATUS KphUnhook(
+ PKPH_HOOK Hook
+ );
+
+#endif
diff --git a/trunk/KProcessHacker/include/kprocesshacker.h b/trunk/KProcessHacker/include/kprocesshacker.h
index c5419bf58..851389ff3 100644
--- a/trunk/KProcessHacker/include/kprocesshacker.h
+++ b/trunk/KProcessHacker/include/kprocesshacker.h
@@ -70,11 +70,17 @@
#define KPH_GETFEATURES KPH_CTL_CODE(26)
#define KPH_SETHANDLEGRANTEDACCESS KPH_CTL_CODE(27)
#define KPH_ASSIGNIMPERSONATIONTOKEN KPH_CTL_CODE(28)
+#define KPH_PROTECTADD KPH_CTL_CODE(29)
+#define KPH_PROTECTREMOVE KPH_CTL_CODE(30)
+#define KPH_PROTECTQUERY KPH_CTL_CODE(31)
#define GET_BIT(integer, bit) (((integer) >> (bit)) & 0x1)
#define SET_BIT(integer, bit) ((integer) |= 1 << (bit))
#define CLEAR_BIT(integer, bit) ((integer) &= ~(1 << (bit)))
+#define KPH_TIMEOUT_TO_SEC ((LONGLONG) 1 * 10 * 1000 * 1000)
+#define KPH_REL_TIMEOUT_IN_SEC(Time) (Time * -1 * KPH_TIMEOUT_TO_SEC)
+
NTSTATUS KphDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS KphDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
diff --git a/trunk/KProcessHacker/include/protect.h b/trunk/KProcessHacker/include/protect.h
new file mode 100644
index 000000000..e180adacf
--- /dev/null
+++ b/trunk/KProcessHacker/include/protect.h
@@ -0,0 +1,77 @@
+/*
+ * Process Hacker Driver -
+ * process protection
+ *
+ * Copyright (C) 2009 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 .
+ */
+
+#ifndef _PROTECT_H
+#define _PROTECT_H
+
+#include "hook.h"
+
+#define OBOPENOBJECTBYPOINTER_ARGS \
+ PVOID Object, \
+ ULONG HandleAttributes, \
+ PACCESS_STATE PassedAccessState, \
+ ACCESS_MASK DesiredAccess, \
+ POBJECT_TYPE ObjectType, \
+ KPROCESSOR_MODE AccessMode, \
+ PHANDLE Handle
+
+typedef struct _KPH_PROCESS_ENTRY
+{
+ LIST_ENTRY ListEntry;
+ PEPROCESS Process;
+ HANDLE Tag;
+ ACCESS_MASK ProcessAllowMask;
+ ACCESS_MASK ThreadAllowMask;
+} KPH_PROCESS_ENTRY, *PKPH_PROCESS_ENTRY;
+
+NTSTATUS NTAPI KphNewObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS);
+NTSTATUS NTAPI KphOldObOpenObjectByPointer(OBOPENOBJECTBYPOINTER_ARGS);
+
+NTSTATUS KphProtectInit();
+NTSTATUS KphProtectDeinit();
+
+PKPH_PROCESS_ENTRY KphProtectAddEntry(
+ PEPROCESS Process,
+ HANDLE Tag,
+ ACCESS_MASK ProcessAllowMask,
+ ACCESS_MASK ThreadAllowMask
+ );
+
+BOOLEAN KphProtectCopyEntry(
+ PEPROCESS Process,
+ PKPH_PROCESS_ENTRY ProcessEntry
+ );
+
+PKPH_PROCESS_ENTRY KphProtectFindEntry(
+ PEPROCESS Process,
+ HANDLE Tag
+ );
+
+BOOLEAN KphProtectRemoveByProcess(
+ PEPROCESS Process
+ );
+
+ULONG KphProtectRemoveByTag(
+ HANDLE Tag
+ );
+
+#endif
diff --git a/trunk/KProcessHacker/include/ps.h b/trunk/KProcessHacker/include/ps.h
index 0280bead0..7d73b6e8a 100644
--- a/trunk/KProcessHacker/include/ps.h
+++ b/trunk/KProcessHacker/include/ps.h
@@ -29,6 +29,44 @@
#include "ob.h"
#include "se.h"
+#define PROCESS_TERMINATE (0x0001)
+#define PROCESS_CREATE_THREAD (0x0002)
+#define PROCESS_SET_SESSIONID (0x0004)
+#define PROCESS_VM_OPERATION (0x0008)
+#define PROCESS_VM_READ (0x0010)
+#define PROCESS_VM_WRITE (0x0020)
+#define PROCESS_DUP_HANDLE (0x0040)
+#define PROCESS_CREATE_PROCESS (0x0080)
+#define PROCESS_SET_QUOTA (0x0100)
+#define PROCESS_SET_INFORMATION (0x0200)
+#define PROCESS_QUERY_INFORMATION (0x0400)
+#define PROCESS_SUSPEND_RESUME (0x0800)
+#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
+#ifndef PROCESS_ALL_ACCESS
+#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff)
+#endif
+
+#define THREAD_TERMINATE (0x0001)
+#define THREAD_SUSPEND_RESUME (0x0002)
+#define THREAD_ALERT (0x0004)
+#define THREAD_GET_CONTEXT (0x0008)
+#define THREAD_SET_CONTEXT (0x0010)
+#define THREAD_SET_INFORMATION (0x0020)
+#define THREAD_QUERY_INFORMATION (0x0040)
+#define THREAD_SET_THREAD_TOKEN (0x0080)
+#define THREAD_IMPERSONATE (0x0100)
+#define THREAD_DIRECT_IMPERSONATION (0x0200)
+#ifndef THREAD_ALL_ACCESS
+#define THREAD_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3ff)
+#endif
+
+#define JOB_OBJECT_ASSIGN_PROCESS (0x0001)
+#define JOB_OBJECT_SET_ATTRIBUTES (0x0002)
+#define JOB_OBJECT_QUERY (0x0004)
+#define JOB_OBJECT_TERMINATE (0x0008)
+#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES (0x0010)
+#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1f)
+
extern POBJECT_TYPE *PsJobType;
/* FUNCTION DEFS */
diff --git a/trunk/KProcessHacker/include/version.h b/trunk/KProcessHacker/include/version.h
index 6d4053a9f..01921dcb4 100644
--- a/trunk/KProcessHacker/include/version.h
+++ b/trunk/KProcessHacker/include/version.h
@@ -57,7 +57,7 @@ typedef struct _KV_SCANPROC
NTSTATUS KvInit();
PVOID KvVerifyPrologue(
- ULONG_PTR Offset
+ PVOID Address
);
PVOID KvScanProc(
@@ -85,6 +85,7 @@ EXT ACCESS_MASK ThreadAllAccess;
/* Structures
* Et: ETHREAD
* Ep: EPROCESS
+ * Kt: KTHREAD
* Ot: OBJECT_TYPE
* Oti: OBJECT_TYPE_INITIALIZER, offset measured from an OBJECT_TYPE
*/
@@ -96,6 +97,7 @@ EXT ULONG OffEpObjectTable;
EXT ULONG OffEpProtectedProcessOff;
EXT ULONG OffEpProtectedProcessBit;
EXT ULONG OffEpRundownProtect;
+EXT ULONG OffKtProcess;
EXT ULONG OffOhBody;
EXT ULONG OffOtiGenericMapping;
diff --git a/trunk/KProcessHacker/include/zw.h b/trunk/KProcessHacker/include/zw.h
index 6937f5c5a..bd07f4ff3 100644
--- a/trunk/KProcessHacker/include/zw.h
+++ b/trunk/KProcessHacker/include/zw.h
@@ -25,35 +25,6 @@
#include "types.h"
-#define PROCESS_TERMINATE (0x0001)
-#define PROCESS_CREATE_THREAD (0x0002)
-#define PROCESS_SET_SESSIONID (0x0004)
-#define PROCESS_VM_OPERATION (0x0008)
-#define PROCESS_VM_READ (0x0010)
-#define PROCESS_VM_WRITE (0x0020)
-#define PROCESS_DUP_HANDLE (0x0040)
-#define PROCESS_CREATE_PROCESS (0x0080)
-#define PROCESS_SET_QUOTA (0x0100)
-#define PROCESS_SET_INFORMATION (0x0200)
-#define PROCESS_QUERY_INFORMATION (0x0400)
-#define PROCESS_SUSPEND_RESUME (0x0800)
-#define PROCESS_QUERY_LIMITED_INFORMATION (0x1000)
-#if (NTDDI_VERSION >= NTDDI_LONGHORN)
-#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
- 0xFFFF)
-#else
-#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
- 0xFFF)
-#endif
-
-#define JOB_OBJECT_ASSIGN_PROCESS (0x0001)
-#define JOB_OBJECT_SET_ATTRIBUTES (0x0002)
-#define JOB_OBJECT_QUERY (0x0004)
-#define JOB_OBJECT_TERMINATE (0x0008)
-#define JOB_OBJECT_SET_SECURITY_ATTRIBUTES (0x0010)
-#define JOB_OBJECT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \
- 0x1F)
-
typedef struct _SYSTEM_MODULE_INFORMATION
{
ULONG Reserved[2];
diff --git a/trunk/KProcessHacker/kprocesshacker.c b/trunk/KProcessHacker/kprocesshacker.c
index 743bf9c20..ea32b1ad1 100644
--- a/trunk/KProcessHacker/kprocesshacker.c
+++ b/trunk/KProcessHacker/kprocesshacker.c
@@ -22,7 +22,9 @@
#include "include/kprocesshacker.h"
#include "include/debug.h"
+
#include "include/kph.h"
+#include "include/protect.h"
#include "include/ps.h"
#include "include/version.h"
@@ -33,6 +35,8 @@
#pragma alloc_text(PAGE, KphUnsupported)
#pragma pack(1)
+static BOOLEAN ProtectionInitialized = FALSE;
+
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING dosDeviceName;
@@ -41,6 +45,18 @@ VOID DriverUnload(PDRIVER_OBJECT DriverObject)
IoDeleteSymbolicLink(&dosDeviceName);
IoDeleteDevice(DriverObject->DeviceObject);
+ if (ProtectionInitialized)
+ {
+ LARGE_INTEGER waitLi;
+
+ KphProtectDeinit();
+ ProtectionInitialized = FALSE;
+
+ /* Wait for a bit before unloading to prevent BSODs. */
+ waitLi.QuadPart = KPH_REL_TIMEOUT_IN_SEC(5);
+ KeDelayExecutionThread(KernelMode, FALSE, &waitLi);
+ }
+
dprintf("Driver unloaded\n");
}
@@ -119,11 +135,26 @@ NTSTATUS KphDispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
+ if (ProtectionInitialized)
+ {
+ ULONG count = KphProtectRemoveByTag(PsGetCurrentProcessId());
+ dprintf("Removed %d protection entries\n", count);
+ }
+
dprintf("Client (PID %d) disconnected\n", PsGetCurrentProcessId());
return status;
}
+VOID InitProtection()
+{
+ if (!ProtectionInitialized)
+ {
+ KphProtectInit();
+ ProtectionInitialized = TRUE;
+ }
+}
+
/* from YAPM */
NTSTATUS GetObjectName(PFILE_OBJECT FileObject, PVOID Buffer, ULONG BufferLength, PULONG ReturnLength)
{
@@ -239,6 +270,12 @@ PCHAR GetIoControlName(ULONG ControlCode)
return "KphSetHandleGrantedAccess";
else if (ControlCode == KPH_ASSIGNIMPERSONATIONTOKEN)
return "KphAssignImpersonationToken";
+ else if (ControlCode == KPH_PROTECTADD)
+ return "Add Process Protection";
+ else if (ControlCode == KPH_PROTECTREMOVE)
+ return "Remove Process Protection";
+ else if (ControlCode == KPH_PROTECTQUERY)
+ return "Query Process Protection";
else
return "Unknown";
}
@@ -1239,6 +1276,158 @@ NTSTATUS KphDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
}
break;
+ /* Add Process Protection */
+ case KPH_PROTECTADD:
+ {
+ struct
+ {
+ HANDLE ProcessHandle;
+ ACCESS_MASK ProcessAllowMask;
+ ACCESS_MASK ThreadAllowMask;
+ } *args = dataBuffer;
+ PEPROCESS processObject;
+
+ if (inLength < sizeof(*args))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto IoControlEnd;
+ }
+
+ status = ObReferenceObjectByHandle(
+ args->ProcessHandle,
+ 0,
+ *PsProcessType,
+ KernelMode,
+ &processObject,
+ NULL
+ );
+ ObDereferenceObject(processObject);
+
+ if (!NT_SUCCESS(status))
+ goto IoControlEnd;
+
+ InitProtection();
+
+ /* Don't protect the same process twice. */
+ if (KphProtectFindEntry(processObject, NULL))
+ {
+ status = STATUS_NOT_SUPPORTED;
+ goto IoControlEnd;
+ }
+
+ if (!KphProtectAddEntry(
+ processObject,
+ PsGetCurrentProcessId(),
+ args->ProcessAllowMask,
+ args->ThreadAllowMask
+ ))
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto IoControlEnd;
+ }
+ }
+ break;
+
+ /* Remove Process Protection */
+ case KPH_PROTECTREMOVE:
+ {
+ struct
+ {
+ HANDLE ProcessHandle;
+ } *args = dataBuffer;
+ PEPROCESS processObject;
+
+ if (inLength < sizeof(*args))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto IoControlEnd;
+ }
+
+ status = ObReferenceObjectByHandle(
+ args->ProcessHandle,
+ 0,
+ *PsProcessType,
+ KernelMode,
+ &processObject,
+ NULL
+ );
+ ObDereferenceObject(processObject);
+
+ if (!NT_SUCCESS(status))
+ goto IoControlEnd;
+
+ InitProtection();
+
+ if (!KphProtectRemoveByProcess(processObject))
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto IoControlEnd;
+ }
+ }
+ break;
+
+ /* Query Process Protection */
+ case KPH_PROTECTQUERY:
+ {
+ struct
+ {
+ HANDLE ProcessHandle;
+ PACCESS_MASK ProcessAllowMask;
+ PACCESS_MASK ThreadAllowMask;
+ } *args = dataBuffer;
+ PEPROCESS processObject;
+ KPH_PROCESS_ENTRY processEntry;
+
+ if (inLength < sizeof(*args))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto IoControlEnd;
+ }
+
+ __try
+ {
+ ProbeForWrite(args->ProcessAllowMask, sizeof(ACCESS_MASK), 1);
+ ProbeForWrite(args->ThreadAllowMask, sizeof(ACCESS_MASK), 1);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ status = GetExceptionCode();
+ goto IoControlEnd;
+ }
+
+ status = ObReferenceObjectByHandle(
+ args->ProcessHandle,
+ 0,
+ *PsProcessType,
+ KernelMode,
+ &processObject,
+ NULL
+ );
+ ObDereferenceObject(processObject);
+
+ if (!NT_SUCCESS(status))
+ goto IoControlEnd;
+
+ InitProtection();
+
+ if (!KphProtectCopyEntry(processObject, &processEntry))
+ {
+ status = STATUS_UNSUCCESSFUL;
+ goto IoControlEnd;
+ }
+
+ __try
+ {
+ *(args->ProcessAllowMask) = processEntry.ProcessAllowMask;
+ *(args->ThreadAllowMask) = processEntry.ThreadAllowMask;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ status = GetExceptionCode();
+ }
+ }
+ break;
+
default:
{
dprintf("Unrecognized IOCTL code 0x%08x\n", controlCode);
diff --git a/trunk/KProcessHacker/protect.c b/trunk/KProcessHacker/protect.c
new file mode 100644
index 000000000..38080ed6e
--- /dev/null
+++ b/trunk/KProcessHacker/protect.c
@@ -0,0 +1,337 @@
+/*
+ * Process Hacker Driver -
+ * process protection
+ *
+ * Copyright (C) 2009 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include "include/protect.h"
+
+LIST_ENTRY ProtectedProcessListHead;
+KSPIN_LOCK ProtectedProcessListLock;
+NPAGED_LOOKASIDE_LIST ProtectedProcessLookasideList;
+
+KPH_HOOK ObOpenObjectByPointerHook = { 0 };
+
+BOOLEAN KphpIsCurrentProcessProtected();
+
+VOID KphpProtectRemoveEntry(
+ PKPH_PROCESS_ENTRY Entry
+ );
+
+KPH_DEFINE_HOOK_CALL(
+ NTSTATUS NTAPI KphOldObOpenObjectByPointer,
+ OBOPENOBJECTBYPOINTER_ARGS,
+ ObOpenObjectByPointerHook
+ );
+
+/* KphProtectInit
+ *
+ * Initializes process protection.
+ */
+NTSTATUS KphProtectInit()
+{
+ NTSTATUS status;
+
+ /* Initialize list structures. */
+ InitializeListHead(&ProtectedProcessListHead);
+ KeInitializeSpinLock(&ProtectedProcessListLock);
+ ExInitializeNPagedLookasideList(
+ &ProtectedProcessLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(KPH_PROCESS_ENTRY),
+ KPH_TAG,
+ 0
+ );
+
+ /* Hook various functions. */
+ ObOpenObjectByPointerHook.Function = ObOpenObjectByPointer;
+ ObOpenObjectByPointerHook.Target = KphNewObOpenObjectByPointer;
+ if (!NT_SUCCESS(status = KphHook(&ObOpenObjectByPointerHook)))
+ return status;
+
+ return STATUS_SUCCESS;
+}
+
+/* KphProtectDeinit
+ *
+ * Removes process protection and frees associated structures.
+ */
+NTSTATUS KphProtectDeinit()
+{
+ KIRQL oldIrql;
+
+ /* Unhook. */
+ KphUnhook(&ObOpenObjectByPointerHook);
+
+ KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql);
+
+ /* Free and remove all process entries from the list. */
+ while (!IsListEmpty(&ProtectedProcessListHead))
+ {
+ PKPH_PROCESS_ENTRY entry =
+ CONTAINING_RECORD(
+ RemoveHeadList(&ProtectedProcessListHead),
+ KPH_PROCESS_ENTRY,
+ ListEntry
+ );
+
+ dprintf("KphProtectDeinit: removing entry 0x%08x\n", entry);
+
+ ExFreeToNPagedLookasideList(
+ &ProtectedProcessLookasideList,
+ entry
+ );
+ }
+
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return STATUS_SUCCESS;
+}
+
+/* KphNewObOpenObjectByPointer
+ *
+ * New ObOpenObjectByPointer function.
+ */
+NTSTATUS NTAPI KphNewObOpenObjectByPointer(
+ OBOPENOBJECTBYPOINTER_ARGS
+ )
+{
+ if (
+ AccessMode != KernelMode && /* let kernel-mode callers through */
+ !KphpIsCurrentProcessProtected() /* let protected process callers through */
+ )
+ {
+ PEPROCESS processObject = (PEPROCESS)Object;
+ BOOLEAN isThread = ObjectType == *PsThreadType;
+ ACCESS_MASK access;
+ KPH_PROCESS_ENTRY processEntry;
+
+ *Handle = NULL;
+ access = DesiredAccess;
+
+ /* If we have an access state, get the desired access from it. */
+ if (PassedAccessState != NULL)
+ access = PassedAccessState->OriginalDesiredAccess;
+
+ /* If this is a thread, get its parent process. */
+ if (isThread)
+ processObject = *(PEPROCESS *)KVOFF(Object, OffKtProcess);
+
+ if (KphProtectCopyEntry(processObject, &processEntry))
+ {
+ ACCESS_MASK mask =
+ isThread ? processEntry.ThreadAllowMask : processEntry.ProcessAllowMask;
+
+ /* The process/thread is protected. Check if the requested access is allowed. */
+ if ((access & mask) != access)
+ {
+ dprintf(
+ "%d: Access denied: 0x%08x (%s)\n",
+ PsGetCurrentProcessId(),
+ access,
+ isThread ? "Thread" : "Process"
+ );
+ /* Access denied. */
+ return STATUS_ACCESS_DENIED;
+ }
+ }
+ }
+
+ return KphOldObOpenObjectByPointer(
+ Object,
+ HandleAttributes,
+ PassedAccessState,
+ DesiredAccess,
+ ObjectType,
+ AccessMode,
+ Handle
+ );
+}
+
+/* KphProtectAddEntry
+ *
+ * Protects the specified process.
+ */
+PKPH_PROCESS_ENTRY KphProtectAddEntry(
+ PEPROCESS Process,
+ HANDLE Tag,
+ ACCESS_MASK ProcessAllowMask,
+ ACCESS_MASK ThreadAllowMask
+ )
+{
+ KIRQL oldIrql;
+ PKPH_PROCESS_ENTRY entry =
+ ExAllocateFromNPagedLookasideList(&ProtectedProcessLookasideList);
+
+ if (entry == NULL)
+ return NULL;
+
+ entry->Process = Process;
+ entry->Tag = Tag;
+ entry->ProcessAllowMask = ProcessAllowMask;
+ entry->ThreadAllowMask = ThreadAllowMask;
+
+ KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql);
+ InsertHeadList(&ProtectedProcessListHead, &entry->ListEntry);
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return entry;
+}
+
+/* KphProtectCopyEntry
+ *
+ * Copies process protection data for the specified process.
+ */
+BOOLEAN KphProtectCopyEntry(
+ PEPROCESS Process,
+ PKPH_PROCESS_ENTRY ProcessEntry
+ )
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY entry = ProtectedProcessListHead.Flink;
+
+ KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql);
+
+ while (entry != &ProtectedProcessListHead)
+ {
+ PKPH_PROCESS_ENTRY processEntry =
+ CONTAINING_RECORD(entry, KPH_PROCESS_ENTRY, ListEntry);
+
+ if (processEntry->Process == Process)
+ {
+ memcpy(ProcessEntry, processEntry, sizeof(KPH_PROCESS_ENTRY));
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return TRUE;
+ }
+
+ entry = entry->Flink;
+ }
+
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return FALSE;
+}
+
+/* KphProtectFindEntry
+ *
+ * Finds process protection data.
+ */
+PKPH_PROCESS_ENTRY KphProtectFindEntry(
+ PEPROCESS Process,
+ HANDLE Tag
+ )
+{
+ KIRQL oldIrql;
+ PLIST_ENTRY entry = ProtectedProcessListHead.Flink;
+
+ KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql);
+
+ while (entry != &ProtectedProcessListHead)
+ {
+ PKPH_PROCESS_ENTRY processEntry =
+ CONTAINING_RECORD(entry, KPH_PROCESS_ENTRY, ListEntry);
+
+ if (
+ (Process != NULL && processEntry->Process == Process) ||
+ (Tag != NULL && processEntry->Tag == Tag)
+ )
+ {
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return processEntry;
+ }
+
+ entry = entry->Flink;
+ }
+
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+
+ return NULL;
+}
+
+/* KphProtectRemoveByProcess
+ *
+ * Removes protection from the specified process.
+ */
+BOOLEAN KphProtectRemoveByProcess(
+ PEPROCESS Process
+ )
+{
+ PKPH_PROCESS_ENTRY entry = KphProtectFindEntry(Process, NULL);
+
+ if (entry == NULL)
+ return FALSE;
+
+ KphpProtectRemoveEntry(entry);
+
+ return TRUE;
+}
+
+/* KphProtectRemoveByTag
+ *
+ * Removes protection from all processes with the specified tag.
+ */
+ULONG KphProtectRemoveByTag(
+ HANDLE Tag
+ )
+{
+ KIRQL oldIrql;
+ ULONG count = 0;
+ PKPH_PROCESS_ENTRY entry;
+
+ /* Keep removing entries until we can't find any more. */
+ while (entry = KphProtectFindEntry(NULL, Tag))
+ {
+ KphpProtectRemoveEntry(entry);
+ count++;
+ }
+
+ return count;
+}
+
+/* KphpIsCurrentProcessProtected
+ *
+ * Determines whether the current process is protected.
+ */
+BOOLEAN KphpIsCurrentProcessProtected()
+{
+ return KphProtectFindEntry(PsGetCurrentProcess(), NULL) != NULL;
+}
+
+/* KphpProtectRemoveEntry
+ *
+ * Removes and frees process protection data.
+ */
+VOID KphpProtectRemoveEntry(
+ PKPH_PROCESS_ENTRY Entry
+ )
+{
+ KIRQL oldIrql;
+
+ KeAcquireSpinLock(&ProtectedProcessListLock, &oldIrql);
+ RemoveEntryList(&Entry->ListEntry);
+ ExFreeToNPagedLookasideList(
+ &ProtectedProcessLookasideList,
+ Entry
+ );
+ KeReleaseSpinLock(&ProtectedProcessListLock, oldIrql);
+}
diff --git a/trunk/KProcessHacker/sources b/trunk/KProcessHacker/sources
index 6e6ab79dc..d46de85aa 100644
--- a/trunk/KProcessHacker/sources
+++ b/trunk/KProcessHacker/sources
@@ -9,6 +9,8 @@ SOURCES= \
kprocesshacker.c \
version.c \
kph.c \
+ hook.c \
+ protect.c \
mm.c \
ob.c \
ps.c \
diff --git a/trunk/KProcessHacker/version.c b/trunk/KProcessHacker/version.c
index 073c73fa0..79d341e75 100644
--- a/trunk/KProcessHacker/version.c
+++ b/trunk/KProcessHacker/version.c
@@ -118,6 +118,7 @@ NTSTATUS KvInit()
OffEpProtectedProcessOff = 0;
OffEpProtectedProcessBit = 0;
OffEpRundownProtect = 0x80;
+ OffKtProcess = 0x220; /* it's actually in the ETHREAD, but let's ignore that */
OffOtiGenericMapping = 0x60 + 0x8;
OffOhBody = 0x18;
@@ -182,6 +183,7 @@ NTSTATUS KvInit()
OffEpProtectedProcessOff = 0x224;
OffEpProtectedProcessBit = 0xb;
OffEpRundownProtect = 0x98;
+ OffKtProcess = 0x144;
OffOhBody = 0x18;
INIT_SCAN(
@@ -232,6 +234,7 @@ NTSTATUS KvInit()
OffEpProtectedProcessOff = 0x25c;
OffEpProtectedProcessBit = 0xb;
OffEpRundownProtect = 0xb0;
+ OffKtProcess = 0x154;
OffOtiGenericMapping = 0x28 + 0xc;
OffOhBody = 0x18;
@@ -266,13 +269,11 @@ NTSTATUS KvInit()
}
PVOID KvVerifyPrologue(
- ULONG_PTR Offset
+ PVOID Address
)
{
- PVOID address = (PVOID)((ULONG_PTR)__NtClose + Offset);
-
- if (memcmp(address, StandardPrologue, 5) == 0)
- return address;
+ if (memcmp(Address, StandardPrologue, 5) == 0)
+ return Address;
else
return NULL;
}
diff --git a/trunk/ProcessHacker.Native/KProcessHacker.cs b/trunk/ProcessHacker.Native/KProcessHacker.cs
index 40b12569a..b6b910d3f 100644
--- a/trunk/ProcessHacker.Native/KProcessHacker.cs
+++ b/trunk/ProcessHacker.Native/KProcessHacker.cs
@@ -76,7 +76,10 @@ namespace ProcessHacker.Native
KphTerminateThread,
GetFeatures,
KphSetHandleGrantedAccess,
- KphAssignImpersonationToken
+ KphAssignImpersonationToken,
+ ProtectAdd,
+ ProtectRemove,
+ ProtectQuery
}
[Flags]
@@ -113,9 +116,8 @@ namespace ProcessHacker.Native
shandle.Delete();
}
}
- catch (Exception)
- {
- }
+ catch
+ { }
try
{
@@ -546,6 +548,41 @@ namespace ProcessHacker.Native
bytesWritten = returnLength;
}
+ public void ProtectAdd(ProcessHandle processHandle, ProcessAccess ProcessAllowMask, ThreadAccess ThreadAllowMask)
+ {
+ byte* inData = stackalloc byte[12];
+
+ *(int*)inData = processHandle;
+ *(int*)(inData + 4) = (int)ProcessAllowMask;
+ *(int*)(inData + 8) = (int)ThreadAllowMask;
+
+ _fileHandle.IoControl(CtlCode(Control.ProtectAdd), inData, 12, null, 0);
+ }
+
+ public void ProtectQuery(ProcessHandle processHandle, out ProcessAccess ProcessAllowMask, out ThreadAccess ThreadAllowMask)
+ {
+ byte* inData = stackalloc byte[12];
+ ProcessAccess processAllowMask;
+ ThreadAccess threadAllowMask;
+
+ *(int*)inData = processHandle;
+ *(int*)(inData + 4) = (int)&processAllowMask;
+ *(int*)(inData + 8) = (int)&threadAllowMask;
+
+ _fileHandle.IoControl(CtlCode(Control.ProtectQuery), inData, 12, null, 0);
+
+ ProcessAllowMask = processAllowMask;
+ ThreadAllowMask = threadAllowMask;
+ }
+
+ public void ProtectRemove(ProcessHandle processHandle)
+ {
+ int processHandleInt = processHandle;
+
+ _fileHandle.IoControl(CtlCode(Control.ProtectRemove),
+ (byte*)&processHandleInt, 4, null, 0);
+ }
+
public byte[] Read(int address, int length)
{
byte[] buffer = new byte[length];
diff --git a/trunk/ProcessHacker/Components/ModuleList.cs b/trunk/ProcessHacker/Components/ModuleList.cs
index 16dae8d37..32b51e042 100644
--- a/trunk/ProcessHacker/Components/ModuleList.cs
+++ b/trunk/ProcessHacker/Components/ModuleList.cs
@@ -29,6 +29,7 @@ using ProcessHacker.Native.Api;
using ProcessHacker.Native.Objects;
using ProcessHacker.Native.Security;
using ProcessHacker.UI;
+using Microsoft.Win32;
namespace ProcessHacker.Components
{
@@ -409,41 +410,83 @@ namespace ProcessHacker.Components
private void unloadMenuItem_Click(object sender, EventArgs e)
{
- if (MessageBox.Show("Are you sure you want to unload this library?", "Process Hacker",
+ if (MessageBox.Show("Are you sure you want to unload this " +
+ (_pid != 4 ? "library" : "driver") + "?", "Process Hacker",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.No)
return;
- try
+ if (_pid == 4)
{
- IntPtr kernel32 = Win32.GetModuleHandle("kernel32.dll");
- IntPtr freeLibrary = Win32.GetProcAddress(kernel32, "FreeLibrary");
-
- if (freeLibrary == IntPtr.Zero)
- throw new Exception("Could not find the entry point of FreeLibrary in kernel32.dll!");
-
- using (ProcessHandle phandle = new ProcessHandle(_pid,
- Program.MinProcessQueryRights | Program.MinProcessReadMemoryRights |
- Program.MinProcessWriteMemoryRights | ProcessAccess.CreateThread))
+ try
{
- IntPtr baseAddress = ((ModuleItem)listModules.SelectedItems[0].Tag).BaseAddress;
+ string fileName = ((ModuleItem)listModules.SelectedItems[0].Tag).FileName;
+ RegistryKey servicesKey =
+ Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services", true);
+ string serviceName = Misc.MakeRandomString(8);
+ RegistryKey serviceKey = servicesKey.CreateSubKey(serviceName);
- phandle.SetModuleReferenceCount(baseAddress, 1);
+ serviceKey.SetValue("ErrorControl", 1, RegistryValueKind.DWord);
+ serviceKey.SetValue("ImagePath", "\\??\\" + fileName, RegistryValueKind.ExpandString);
+ serviceKey.SetValue("Start", 1, RegistryValueKind.DWord);
+ serviceKey.SetValue("Type", 1, RegistryValueKind.DWord);
+ serviceKey.Close();
+ servicesKey.Flush();
- var thread = phandle.CreateThread(freeLibrary, baseAddress, ThreadAccess.All);
-
- thread.Wait(1000);
-
- int exitCode = thread.GetExitCode();
-
- if (exitCode == 0)
+ try
{
- throw new Exception("Error unloading the library.");
+ Windows.UnloadDriver(serviceName);
+ }
+ finally
+ {
+ servicesKey.DeleteSubKeyTree(serviceName);
+ servicesKey.Close();
}
}
+ catch (System.Security.SecurityException ex)
+ {
+ MessageBox.Show("Could not unload the driver. Make sure Process Hacker " +
+ "is running with administrative privileges. Error:\n\n" +
+ ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
}
- catch (Exception ex)
+ else
{
- MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ try
+ {
+ IntPtr kernel32 = Win32.GetModuleHandle("kernel32.dll");
+ IntPtr freeLibrary = Win32.GetProcAddress(kernel32, "FreeLibrary");
+
+ if (freeLibrary == IntPtr.Zero)
+ throw new Exception("Could not find the entry point of FreeLibrary in kernel32.dll!");
+
+ using (ProcessHandle phandle = new ProcessHandle(_pid,
+ Program.MinProcessQueryRights | Program.MinProcessReadMemoryRights |
+ Program.MinProcessWriteMemoryRights | ProcessAccess.CreateThread))
+ {
+ IntPtr baseAddress = ((ModuleItem)listModules.SelectedItems[0].Tag).BaseAddress;
+
+ phandle.SetModuleReferenceCount(baseAddress, 1);
+
+ var thread = phandle.CreateThread(freeLibrary, baseAddress, ThreadAccess.All);
+
+ thread.Wait(1000);
+
+ int exitCode = thread.GetExitCode();
+
+ if (exitCode == 0)
+ {
+ throw new Exception("Error unloading the library.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message, "Process Hacker", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
}
}
}
diff --git a/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs b/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs
index 79cc3c551..7e7b84273 100644
--- a/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs
+++ b/trunk/ProcessHacker/Forms/HackerWindow.Designer.cs
@@ -41,6 +41,7 @@
this.menuItem5 = new System.Windows.Forms.MenuItem();
this.affinityProcessMenuItem = new System.Windows.Forms.MenuItem();
this.injectDllProcessMenuItem = new System.Windows.Forms.MenuItem();
+ this.protectionProcessMenuItem = new System.Windows.Forms.MenuItem();
this.setTokenProcessMenuItem = new System.Windows.Forms.MenuItem();
this.terminatorProcessMenuItem = new System.Windows.Forms.MenuItem();
this.priorityMenuItem = new System.Windows.Forms.MenuItem();
@@ -189,6 +190,7 @@
this.menuItem5,
this.affinityProcessMenuItem,
this.injectDllProcessMenuItem,
+ this.protectionProcessMenuItem,
this.setTokenProcessMenuItem,
this.terminatorProcessMenuItem,
this.priorityMenuItem,
@@ -264,22 +266,28 @@
this.injectDllProcessMenuItem.Text = "Inject DLL...";
this.injectDllProcessMenuItem.Click += new System.EventHandler(this.injectDllProcessMenuItem_Click);
//
+ // protectionProcessMenuItem
+ //
+ this.protectionProcessMenuItem.Index = 10;
+ this.protectionProcessMenuItem.Text = "Protection...";
+ this.protectionProcessMenuItem.Click += new System.EventHandler(this.protectionProcessMenuItem_Click);
+ //
// setTokenProcessMenuItem
//
- this.setTokenProcessMenuItem.Index = 10;
+ this.setTokenProcessMenuItem.Index = 11;
this.setTokenProcessMenuItem.Text = "Set Token...";
this.setTokenProcessMenuItem.Click += new System.EventHandler(this.setTokenProcessMenuItem_Click);
//
// terminatorProcessMenuItem
//
- this.terminatorProcessMenuItem.Index = 11;
+ this.terminatorProcessMenuItem.Index = 12;
this.terminatorProcessMenuItem.Text = "Terminator...";
this.terminatorProcessMenuItem.Click += new System.EventHandler(this.terminatorProcessMenuItem_Click);
//
// priorityMenuItem
//
this.vistaMenu.SetImage(this.priorityMenuItem, global::ProcessHacker.Properties.Resources.control_equalizer_blue);
- this.priorityMenuItem.Index = 12;
+ this.priorityMenuItem.Index = 13;
this.priorityMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.realTimeMenuItem,
this.highMenuItem,
@@ -333,7 +341,7 @@
//
// runAsProcessMenuItem
//
- this.runAsProcessMenuItem.Index = 13;
+ this.runAsProcessMenuItem.Index = 14;
this.runAsProcessMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.launchAsUserProcessMenuItem,
this.launchAsThisUserProcessMenuItem});
@@ -355,37 +363,37 @@
//
this.propertiesProcessMenuItem.DefaultItem = true;
this.vistaMenu.SetImage(this.propertiesProcessMenuItem, global::ProcessHacker.Properties.Resources.application_form_magnify);
- this.propertiesProcessMenuItem.Index = 14;
+ this.propertiesProcessMenuItem.Index = 15;
this.propertiesProcessMenuItem.Text = "&Properties...";
this.propertiesProcessMenuItem.Click += new System.EventHandler(this.propertiesProcessMenuItem_Click);
//
// menuItem7
//
- this.menuItem7.Index = 15;
+ this.menuItem7.Index = 16;
this.menuItem7.Text = "-";
//
// searchProcessMenuItem
//
- this.searchProcessMenuItem.Index = 16;
+ this.searchProcessMenuItem.Index = 17;
this.searchProcessMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlM;
this.searchProcessMenuItem.Text = "&Search Online...";
this.searchProcessMenuItem.Click += new System.EventHandler(this.searchProcessMenuItem_Click);
//
// reanalyzeProcessMenuItem
//
- this.reanalyzeProcessMenuItem.Index = 17;
+ this.reanalyzeProcessMenuItem.Index = 18;
this.reanalyzeProcessMenuItem.Text = "Re-analyze";
this.reanalyzeProcessMenuItem.Click += new System.EventHandler(this.reanalyzeProcessMenuItem_Click);
//
// copyProcessMenuItem
//
this.vistaMenu.SetImage(this.copyProcessMenuItem, global::ProcessHacker.Properties.Resources.page_copy);
- this.copyProcessMenuItem.Index = 18;
+ this.copyProcessMenuItem.Index = 19;
this.copyProcessMenuItem.Text = "&Copy";
//
// selectAllProcessMenuItem
//
- this.selectAllProcessMenuItem.Index = 19;
+ this.selectAllProcessMenuItem.Index = 20;
this.selectAllProcessMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlA;
this.selectAllProcessMenuItem.Text = "Select &All";
this.selectAllProcessMenuItem.Click += new System.EventHandler(this.selectAllProcessMenuItem_Click);
@@ -1343,6 +1351,7 @@
private System.Windows.Forms.MenuItem commitHistoryMenuItem;
private System.Windows.Forms.MenuItem physMemHistoryMenuItem;
private System.Windows.Forms.MenuItem closeNetworkMenuItem;
+ private System.Windows.Forms.MenuItem protectionProcessMenuItem;
}
}
diff --git a/trunk/ProcessHacker/Forms/HackerWindow.cs b/trunk/ProcessHacker/Forms/HackerWindow.cs
index 9100272de..25c5353d0 100644
--- a/trunk/ProcessHacker/Forms/HackerWindow.cs
+++ b/trunk/ProcessHacker/Forms/HackerWindow.cs
@@ -1163,6 +1163,11 @@ namespace ProcessHacker
}
}
+ private void protectionProcessMenuItem_Click(object sender, EventArgs e)
+ {
+ (new ProtectProcessWindow(processSelectedPID)).ShowDialog();
+ }
+
private void setTokenProcessMenuItem_Click(object sender, EventArgs e)
{
ProcessPickerWindow picker = new ProcessPickerWindow();
@@ -2318,7 +2323,7 @@ namespace ProcessHacker
treeProcesses.RefreshItems();
}
- private void LoadFixMenuItems()
+ public void LoadFixMenuItems()
{
if (!System.IO.File.Exists(Application.StartupPath + "\\Assistant.exe"))
{
@@ -2332,6 +2337,9 @@ namespace ProcessHacker
if (KProcessHacker.Instance == null || !OSVersion.HasSetAccessToken)
setTokenProcessMenuItem.Visible = false;
+ if (KProcessHacker.Instance == null || !Properties.Settings.Default.EnableExperimentalFeatures)
+ protectionProcessMenuItem.Visible = false;
+
if (!OSVersion.HasUac)
virtualizationProcessMenuItem.Visible = false;
diff --git a/trunk/ProcessHacker/Forms/OptionsWindow.Designer.cs b/trunk/ProcessHacker/Forms/OptionsWindow.Designer.cs
index 97017ff1b..909c273b5 100644
--- a/trunk/ProcessHacker/Forms/OptionsWindow.Designer.cs
+++ b/trunk/ProcessHacker/Forms/OptionsWindow.Designer.cs
@@ -50,6 +50,7 @@
this.label23 = new System.Windows.Forms.Label();
this.textIconMenuProcesses = new System.Windows.Forms.NumericUpDown();
this.tabAdvanced = new System.Windows.Forms.TabPage();
+ this.checkHidePhConnections = new System.Windows.Forms.CheckBox();
this.textMaxSamples = new System.Windows.Forms.NumericUpDown();
this.label6 = new System.Windows.Forms.Label();
this.buttonChangeReplaceTaskManager = new System.Windows.Forms.Button();
@@ -95,7 +96,7 @@
this.toolTipProvider = new System.Windows.Forms.ToolTip(this.components);
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonApply = new System.Windows.Forms.Button();
- this.checkHidePhConnections = new System.Windows.Forms.CheckBox();
+ this.checkEnableExperimentalFeatures = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.textUpdateInterval)).BeginInit();
this.tabControl.SuspendLayout();
this.tabGeneral.SuspendLayout();
@@ -177,7 +178,7 @@
//
this.checkWarnDangerous.AutoSize = true;
this.checkWarnDangerous.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.checkWarnDangerous.Location = new System.Drawing.Point(6, 78);
+ this.checkWarnDangerous.Location = new System.Drawing.Point(6, 102);
this.checkWarnDangerous.Name = "checkWarnDangerous";
this.checkWarnDangerous.Size = new System.Drawing.Size(228, 18);
this.checkWarnDangerous.TabIndex = 4;
@@ -383,6 +384,7 @@
//
// tabAdvanced
//
+ this.tabAdvanced.Controls.Add(this.checkEnableExperimentalFeatures);
this.tabAdvanced.Controls.Add(this.checkHidePhConnections);
this.tabAdvanced.Controls.Add(this.textMaxSamples);
this.tabAdvanced.Controls.Add(this.label6);
@@ -400,6 +402,19 @@
this.tabAdvanced.Text = "Advanced";
this.tabAdvanced.UseVisualStyleBackColor = true;
//
+ // checkHidePhConnections
+ //
+ this.checkHidePhConnections.AutoSize = true;
+ this.checkHidePhConnections.FlatStyle = System.Windows.Forms.FlatStyle.System;
+ this.checkHidePhConnections.Location = new System.Drawing.Point(6, 150);
+ this.checkHidePhConnections.Name = "checkHidePhConnections";
+ this.checkHidePhConnections.Size = new System.Drawing.Size(235, 18);
+ this.checkHidePhConnections.TabIndex = 21;
+ this.checkHidePhConnections.Text = "Hide Process Hacker network connections";
+ this.toolTipProvider.SetToolTip(this.checkHidePhConnections, "Hides network connections made by Process Hacker. This may be useful when Process" +
+ " Hacker is resolving addresses.");
+ this.checkHidePhConnections.UseVisualStyleBackColor = true;
+ //
// textMaxSamples
//
this.textMaxSamples.Increment = new decimal(new int[] {
@@ -407,7 +422,7 @@
0,
0,
0});
- this.textMaxSamples.Location = new System.Drawing.Point(118, 154);
+ this.textMaxSamples.Location = new System.Drawing.Point(118, 178);
this.textMaxSamples.Maximum = new decimal(new int[] {
10000,
0,
@@ -430,7 +445,7 @@
// label6
//
this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(6, 156);
+ this.label6.Location = new System.Drawing.Point(6, 180);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(106, 13);
this.label6.TabIndex = 19;
@@ -440,7 +455,7 @@
// buttonChangeReplaceTaskManager
//
this.buttonChangeReplaceTaskManager.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.buttonChangeReplaceTaskManager.Location = new System.Drawing.Point(257, 51);
+ this.buttonChangeReplaceTaskManager.Location = new System.Drawing.Point(257, 75);
this.buttonChangeReplaceTaskManager.Name = "buttonChangeReplaceTaskManager";
this.buttonChangeReplaceTaskManager.Size = new System.Drawing.Size(89, 23);
this.buttonChangeReplaceTaskManager.TabIndex = 18;
@@ -452,7 +467,7 @@
//
this.checkReplaceTaskManager.AutoSize = true;
this.checkReplaceTaskManager.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.checkReplaceTaskManager.Location = new System.Drawing.Point(6, 54);
+ this.checkReplaceTaskManager.Location = new System.Drawing.Point(6, 78);
this.checkReplaceTaskManager.Name = "checkReplaceTaskManager";
this.checkReplaceTaskManager.Size = new System.Drawing.Size(245, 18);
this.checkReplaceTaskManager.TabIndex = 17;
@@ -477,7 +492,7 @@
//
this.checkHideHandlesWithNoName.AutoSize = true;
this.checkHideHandlesWithNoName.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.checkHideHandlesWithNoName.Location = new System.Drawing.Point(6, 102);
+ this.checkHideHandlesWithNoName.Location = new System.Drawing.Point(6, 126);
this.checkHideHandlesWithNoName.Name = "checkHideHandlesWithNoName";
this.checkHideHandlesWithNoName.Size = new System.Drawing.Size(160, 18);
this.checkHideHandlesWithNoName.TabIndex = 13;
@@ -489,7 +504,7 @@
//
this.checkVerifySignatures.AutoSize = true;
this.checkVerifySignatures.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.checkVerifySignatures.Location = new System.Drawing.Point(6, 30);
+ this.checkVerifySignatures.Location = new System.Drawing.Point(6, 54);
this.checkVerifySignatures.Name = "checkVerifySignatures";
this.checkVerifySignatures.Size = new System.Drawing.Size(254, 18);
this.checkVerifySignatures.TabIndex = 4;
@@ -932,18 +947,16 @@
this.buttonApply.UseVisualStyleBackColor = true;
this.buttonApply.Click += new System.EventHandler(this.buttonApply_Click);
//
- // checkHidePhConnections
+ // checkEnableExperimentalFeatures
//
- this.checkHidePhConnections.AutoSize = true;
- this.checkHidePhConnections.FlatStyle = System.Windows.Forms.FlatStyle.System;
- this.checkHidePhConnections.Location = new System.Drawing.Point(6, 126);
- this.checkHidePhConnections.Name = "checkHidePhConnections";
- this.checkHidePhConnections.Size = new System.Drawing.Size(235, 18);
- this.checkHidePhConnections.TabIndex = 21;
- this.checkHidePhConnections.Text = "Hide Process Hacker network connections";
- this.toolTipProvider.SetToolTip(this.checkHidePhConnections, "Hides network connections made by Process Hacker. This may be useful when Process" +
- " Hacker is resolving addresses.");
- this.checkHidePhConnections.UseVisualStyleBackColor = true;
+ this.checkEnableExperimentalFeatures.AutoSize = true;
+ this.checkEnableExperimentalFeatures.FlatStyle = System.Windows.Forms.FlatStyle.System;
+ this.checkEnableExperimentalFeatures.Location = new System.Drawing.Point(6, 30);
+ this.checkEnableExperimentalFeatures.Name = "checkEnableExperimentalFeatures";
+ this.checkEnableExperimentalFeatures.Size = new System.Drawing.Size(168, 18);
+ this.checkEnableExperimentalFeatures.TabIndex = 22;
+ this.checkEnableExperimentalFeatures.Text = "Enable experimental features";
+ this.checkEnableExperimentalFeatures.UseVisualStyleBackColor = true;
//
// OptionsWindow
//
@@ -1054,5 +1067,6 @@
private System.Windows.Forms.CheckBox checkUndecorate;
private System.Windows.Forms.Button buttonApply;
private System.Windows.Forms.CheckBox checkHidePhConnections;
+ private System.Windows.Forms.CheckBox checkEnableExperimentalFeatures;
}
}
\ No newline at end of file
diff --git a/trunk/ProcessHacker/Forms/OptionsWindow.cs b/trunk/ProcessHacker/Forms/OptionsWindow.cs
index 0932a538c..e54d78c18 100644
--- a/trunk/ProcessHacker/Forms/OptionsWindow.cs
+++ b/trunk/ProcessHacker/Forms/OptionsWindow.cs
@@ -235,6 +235,7 @@ namespace ProcessHacker
checkVerifySignatures.Checked = Properties.Settings.Default.VerifySignatures;
checkHideHandlesWithNoName.Checked = Properties.Settings.Default.HideHandlesWithNoName;
checkEnableKPH.Checked = Properties.Settings.Default.EnableKPH;
+ checkEnableExperimentalFeatures.Checked = Properties.Settings.Default.EnableExperimentalFeatures;
checkStartHidden.Checked = Properties.Settings.Default.StartHidden;
checkHidePhConnections.Checked = Properties.Settings.Default.HideProcessHackerNetworkConnections;
@@ -341,6 +342,7 @@ namespace ProcessHacker
Properties.Settings.Default.HideHandlesWithNoName = checkHideHandlesWithNoName.Checked;
Properties.Settings.Default.StartHidden = checkStartHidden.Checked;
Properties.Settings.Default.EnableKPH = checkEnableKPH.Checked;
+ Properties.Settings.Default.EnableExperimentalFeatures = checkEnableExperimentalFeatures.Checked;
Properties.Settings.Default.ImposterNames = textImposterNames.Text.ToLower();
Properties.Settings.Default.HideProcessHackerNetworkConnections = checkHidePhConnections.Checked;
@@ -414,6 +416,7 @@ namespace ProcessHacker
Program.ImposterNames.Add(s.Trim());
Program.HackerWindow.ApplyIconVisibilities();
+ Program.HackerWindow.LoadFixMenuItems();
Program.ProcessProvider.Interval = Properties.Settings.Default.RefreshInterval;
Program.HackerWindow.ServiceProvider.Interval = Properties.Settings.Default.RefreshInterval;
Program.HackerWindow.NetworkProvider.Interval = Properties.Settings.Default.RefreshInterval;
diff --git a/trunk/ProcessHacker/Forms/ProcessWindow.Designer.cs b/trunk/ProcessHacker/Forms/ProcessWindow.Designer.cs
index d45b8b684..2dac8a2ac 100644
--- a/trunk/ProcessHacker/Forms/ProcessWindow.Designer.cs
+++ b/trunk/ProcessHacker/Forms/ProcessWindow.Designer.cs
@@ -563,7 +563,7 @@
this.tabStatistics.Location = new System.Drawing.Point(4, 42);
this.tabStatistics.Name = "tabStatistics";
this.tabStatistics.Padding = new System.Windows.Forms.Padding(3);
- this.tabStatistics.Size = new System.Drawing.Size(454, 383);
+ this.tabStatistics.Size = new System.Drawing.Size(481, 409);
this.tabStatistics.TabIndex = 9;
this.tabStatistics.Text = "Statistics";
this.tabStatistics.UseVisualStyleBackColor = true;
@@ -575,7 +575,7 @@
this.tabPerformance.Location = new System.Drawing.Point(4, 42);
this.tabPerformance.Name = "tabPerformance";
this.tabPerformance.Padding = new System.Windows.Forms.Padding(3);
- this.tabPerformance.Size = new System.Drawing.Size(454, 383);
+ this.tabPerformance.Size = new System.Drawing.Size(481, 409);
this.tabPerformance.TabIndex = 8;
this.tabPerformance.Text = "Performance";
this.tabPerformance.UseVisualStyleBackColor = true;
@@ -594,7 +594,7 @@
this.tablePerformance.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tablePerformance.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tablePerformance.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
- this.tablePerformance.Size = new System.Drawing.Size(448, 377);
+ this.tablePerformance.Size = new System.Drawing.Size(475, 403);
this.tablePerformance.TabIndex = 1;
//
// groupCPUUsage
@@ -603,7 +603,7 @@
this.groupCPUUsage.Dock = System.Windows.Forms.DockStyle.Fill;
this.groupCPUUsage.Location = new System.Drawing.Point(3, 3);
this.groupCPUUsage.Name = "groupCPUUsage";
- this.groupCPUUsage.Size = new System.Drawing.Size(442, 119);
+ this.groupCPUUsage.Size = new System.Drawing.Size(469, 128);
this.groupCPUUsage.TabIndex = 0;
this.groupCPUUsage.TabStop = false;
this.groupCPUUsage.Text = "CPU Usage (Kernel, User)";
@@ -626,7 +626,7 @@
this.plotterCPUUsage.Name = "plotterCPUUsage";
this.plotterCPUUsage.OverlaySecondLine = false;
this.plotterCPUUsage.ShowGrid = true;
- this.plotterCPUUsage.Size = new System.Drawing.Size(436, 100);
+ this.plotterCPUUsage.Size = new System.Drawing.Size(463, 109);
this.plotterCPUUsage.TabIndex = 0;
this.plotterCPUUsage.TextBoxColor = System.Drawing.Color.FromArgb(((int)(((byte)(127)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.plotterCPUUsage.TextColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(255)))), ((int)(((byte)(0)))));
@@ -640,9 +640,9 @@
//
this.groupBox3.Controls.Add(this.plotterIO);
this.groupBox3.Dock = System.Windows.Forms.DockStyle.Fill;
- this.groupBox3.Location = new System.Drawing.Point(3, 253);
+ this.groupBox3.Location = new System.Drawing.Point(3, 271);
this.groupBox3.Name = "groupBox3";
- this.groupBox3.Size = new System.Drawing.Size(442, 121);
+ this.groupBox3.Size = new System.Drawing.Size(469, 129);
this.groupBox3.TabIndex = 0;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "I/O (R+O, W)";
@@ -665,7 +665,7 @@
this.plotterIO.Name = "plotterIO";
this.plotterIO.OverlaySecondLine = true;
this.plotterIO.ShowGrid = true;
- this.plotterIO.Size = new System.Drawing.Size(436, 102);
+ this.plotterIO.Size = new System.Drawing.Size(463, 110);
this.plotterIO.TabIndex = 0;
this.plotterIO.TextBoxColor = System.Drawing.Color.FromArgb(((int)(((byte)(127)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.plotterIO.TextColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(255)))), ((int)(((byte)(0)))));
@@ -679,9 +679,9 @@
//
this.groupBox2.Controls.Add(this.plotterMemory);
this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
- this.groupBox2.Location = new System.Drawing.Point(3, 128);
+ this.groupBox2.Location = new System.Drawing.Point(3, 137);
this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(442, 119);
+ this.groupBox2.Size = new System.Drawing.Size(469, 128);
this.groupBox2.TabIndex = 0;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Memory (Private Pages, Working Set)";
@@ -704,7 +704,7 @@
this.plotterMemory.Name = "plotterMemory";
this.plotterMemory.OverlaySecondLine = true;
this.plotterMemory.ShowGrid = true;
- this.plotterMemory.Size = new System.Drawing.Size(436, 100);
+ this.plotterMemory.Size = new System.Drawing.Size(463, 109);
this.plotterMemory.TabIndex = 0;
this.plotterMemory.TextBoxColor = System.Drawing.Color.FromArgb(((int)(((byte)(127)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))), ((int)(((byte)(0)))));
this.plotterMemory.TextColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(255)))), ((int)(((byte)(0)))));
@@ -720,7 +720,7 @@
this.tabThreads.ImageKey = "hourglass";
this.tabThreads.Location = new System.Drawing.Point(4, 42);
this.tabThreads.Name = "tabThreads";
- this.tabThreads.Size = new System.Drawing.Size(454, 383);
+ this.tabThreads.Size = new System.Drawing.Size(481, 409);
this.tabThreads.TabIndex = 3;
this.tabThreads.Text = "Threads";
this.tabThreads.UseVisualStyleBackColor = true;
@@ -733,7 +733,7 @@
this.listThreads.Location = new System.Drawing.Point(0, 0);
this.listThreads.Name = "listThreads";
this.listThreads.Provider = null;
- this.listThreads.Size = new System.Drawing.Size(454, 383);
+ this.listThreads.Size = new System.Drawing.Size(481, 409);
this.listThreads.TabIndex = 0;
//
// tabToken
@@ -742,7 +742,7 @@
this.tabToken.Location = new System.Drawing.Point(4, 42);
this.tabToken.Name = "tabToken";
this.tabToken.Padding = new System.Windows.Forms.Padding(3);
- this.tabToken.Size = new System.Drawing.Size(454, 383);
+ this.tabToken.Size = new System.Drawing.Size(481, 409);
this.tabToken.TabIndex = 1;
this.tabToken.Text = "Token";
this.tabToken.UseVisualStyleBackColor = true;
@@ -753,7 +753,7 @@
this.tabModules.ImageKey = "page_white_wrench";
this.tabModules.Location = new System.Drawing.Point(4, 42);
this.tabModules.Name = "tabModules";
- this.tabModules.Size = new System.Drawing.Size(454, 383);
+ this.tabModules.Size = new System.Drawing.Size(481, 409);
this.tabModules.TabIndex = 6;
this.tabModules.Text = "Modules";
this.tabModules.UseVisualStyleBackColor = true;
@@ -765,7 +765,7 @@
this.listModules.Location = new System.Drawing.Point(0, 0);
this.listModules.Name = "listModules";
this.listModules.Provider = null;
- this.listModules.Size = new System.Drawing.Size(454, 383);
+ this.listModules.Size = new System.Drawing.Size(481, 409);
this.listModules.TabIndex = 0;
//
// tabMemory
@@ -778,7 +778,7 @@
this.tabMemory.Location = new System.Drawing.Point(4, 42);
this.tabMemory.Name = "tabMemory";
this.tabMemory.Padding = new System.Windows.Forms.Padding(3);
- this.tabMemory.Size = new System.Drawing.Size(454, 383);
+ this.tabMemory.Size = new System.Drawing.Size(481, 409);
this.tabMemory.TabIndex = 4;
this.tabMemory.Text = "Memory";
this.tabMemory.UseVisualStyleBackColor = true;
@@ -874,7 +874,7 @@
this.listMemory.Location = new System.Drawing.Point(6, 59);
this.listMemory.Name = "listMemory";
this.listMemory.Provider = null;
- this.listMemory.Size = new System.Drawing.Size(442, 318);
+ this.listMemory.Size = new System.Drawing.Size(469, 344);
this.listMemory.TabIndex = 0;
//
// tabEnvironment
@@ -884,7 +884,7 @@
this.tabEnvironment.Location = new System.Drawing.Point(4, 42);
this.tabEnvironment.Name = "tabEnvironment";
this.tabEnvironment.Padding = new System.Windows.Forms.Padding(3);
- this.tabEnvironment.Size = new System.Drawing.Size(454, 383);
+ this.tabEnvironment.Size = new System.Drawing.Size(481, 409);
this.tabEnvironment.TabIndex = 10;
this.tabEnvironment.Text = "Environment";
this.tabEnvironment.UseVisualStyleBackColor = true;
@@ -900,7 +900,7 @@
this.listEnvironment.Location = new System.Drawing.Point(3, 3);
this.listEnvironment.Name = "listEnvironment";
this.listEnvironment.ShowItemToolTips = true;
- this.listEnvironment.Size = new System.Drawing.Size(448, 377);
+ this.listEnvironment.Size = new System.Drawing.Size(475, 403);
this.listEnvironment.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.listEnvironment.TabIndex = 0;
this.listEnvironment.UseCompatibleStateImageBehavior = false;
@@ -924,7 +924,7 @@
this.tabHandles.Location = new System.Drawing.Point(4, 42);
this.tabHandles.Name = "tabHandles";
this.tabHandles.Padding = new System.Windows.Forms.Padding(3);
- this.tabHandles.Size = new System.Drawing.Size(454, 383);
+ this.tabHandles.Size = new System.Drawing.Size(481, 409);
this.tabHandles.TabIndex = 5;
this.tabHandles.Text = "Handles";
this.tabHandles.UseVisualStyleBackColor = true;
@@ -950,7 +950,7 @@
this.listHandles.Location = new System.Drawing.Point(6, 30);
this.listHandles.Name = "listHandles";
this.listHandles.Provider = null;
- this.listHandles.Size = new System.Drawing.Size(442, 347);
+ this.listHandles.Size = new System.Drawing.Size(469, 373);
this.listHandles.TabIndex = 0;
//
// tabJob
@@ -958,7 +958,7 @@
this.tabJob.ImageKey = "wrench";
this.tabJob.Location = new System.Drawing.Point(4, 42);
this.tabJob.Name = "tabJob";
- this.tabJob.Size = new System.Drawing.Size(454, 383);
+ this.tabJob.Size = new System.Drawing.Size(481, 409);
this.tabJob.TabIndex = 11;
this.tabJob.Text = "Job";
this.tabJob.UseVisualStyleBackColor = true;
@@ -968,7 +968,7 @@
this.tabServices.ImageKey = "cog";
this.tabServices.Location = new System.Drawing.Point(4, 42);
this.tabServices.Name = "tabServices";
- this.tabServices.Size = new System.Drawing.Size(454, 383);
+ this.tabServices.Size = new System.Drawing.Size(481, 409);
this.tabServices.TabIndex = 7;
this.tabServices.Text = "Services";
this.tabServices.UseVisualStyleBackColor = true;
diff --git a/trunk/ProcessHacker/Forms/ProcessWindow.resx b/trunk/ProcessHacker/Forms/ProcessWindow.resx
index 1992d4d49..c5131c83d 100644
--- a/trunk/ProcessHacker/Forms/ProcessWindow.resx
+++ b/trunk/ProcessHacker/Forms/ProcessWindow.resx
@@ -123,8 +123,8 @@
577, 17
-
- 577, 17
+
+ 338, 17
235, 17
@@ -133,223 +133,219 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
- ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA2
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAy
MQAAAk1TRnQBSQFMAgEBCwEAAQwBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABMAMAAQEBAAEgBgABMFYAAxUBHQMjATQDJAE2AyQBNgMkATYDJAE2AyQBNgMkATYDJAE2AyQBNgMk
- ATYDJAE2AyMBMwMVAR0IAAJeAVoC1QGDAT8B/wHRAWsBOQH/A1QBr2wAAYcBAAGAAf8BgwEAASkB/wEq
- AQABKAH/AScBAAEnAf8BJAEAASYB/wHGAgAB/wHGAgAB/wHEAgAB/wHAAgAB/wHAAgAB/wG/AgAB/wEn
- AgAB/wElAgAB/wEiAgAB/wEgAgAB/wEeAgAB/wQAAyMBNAN0AfUDvAH9A/wB/wP8Af8D/AH/A/wB/wP8
- Af8D/AH/A/wB/wP8Af8DvAH9A3AB8wMjATMEAANcAcwB3wGkAYEB/wHqAcIBqwH/AeoBwAGoAf8B3AGZ
- AV8B/wNUAa9qAAHzAf8BmQGbAf4B/wGWAZgB/gH/AZMBlQH+Af8BkQGTAf4B/wHJAgAB/wHgAZMBCAH/
- Ad8BjwEEAf8B3wGNAQAB/wHeAYoBAAH/AcACAAH/AaIByQGeAf8BnQHGAZkB/wGYAcMBlQH/AZQBwAGR
- Af8BAAEYAQAB/wMAAQEDJAE2A88B/gP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8
- Af8DvAH9AyQBNgQAAdsBlwFdAf8B7QHIAbMB/wHnAbgBmwH/AeYBtAGYAf8B6gHDAasB/wHeAZwBYQH/
- A1QBr2YAAfUB/wGeAaAB/gH/AQYBCQH+Af8BAQEEAf4B/wGVAZcB/gH/Ac0CAAH/AeEBlwEOAf8B2gGA
- AQAB/wHZASgBAAH/Ad8BjwEDAf8BxgIAAf8BqAHNAaQB/wEiAbABHAH/ARsBqwEVAf8BmgHEAZYB/wEA
- ASEBAAH/AwABAQMkATYD/AH/A/wB/wPdAf8D2wH/A9kB/wPXAf8D1QH/A9QB/wPUAf8D1AH/A/sB/wP8
- Af8DJAE2AwABAQHdAZ8BZwH/Ae0BzAG3Af8B6AG9AaMB/wHkAbEBkgH/AeYBtgGaAf8B6gHDAawB/wHe
- AZwBYgH/AlQBUwGsYgAB9gH/AaIBpAH+Af8BDQERAf4B/wEIAQwB/gH/AZkBmwH+Af8BzwIAAf8B4wGc
- ARcB/wHcAYYBAAH/AdsBgwEAAf8B4AGUAQkB/wHGAgAB/wGvAdEBqwH/AYABtwElAf8BJAGyAR4B/wGg
+ ATYDJAE2AyMBMwMVAR0IAAJeAVoC1QGDATwB/wHRAWgBNgH/A1QBr2wAAYcBAAGAAf8BgwEAASYB/wEn
+ AQABJQH/ASQBAAEkAf8BIQEAASMB/wHGAgAB/wHGAgAB/wHEAgAB/wHAAgAB/wHAAgAB/wG/AgAB/wEk
+ AgAB/wEiAgAB/wEfAgAB/wEdAgAB/wEbAgAB/wQAAyMBNANuAfUDuQH9A/wB/wP8Af8D/AH/A/wB/wP8
+ Af8D/AH/A/wB/wP8Af8DuQH9A20B8wMjATMEAANcAcwB3wGkAYEB/wHqAcIBqwH/AeoBwAGoAf8B3AGZ
+ AVwB/wNUAa9qAAHzAf8BmQGbAf4B/wGWAZgB/gH/AZMBlQH+Af8BkQGTAf4B/wHJAgAB/wHgAZMBBQH/
+ Ad8BjwEBAf8B3wGNAQAB/wHeAYoBAAH/AcACAAH/AaIByQGeAf8BnQHGAZkB/wGYAcMBlQH/AZQBwAGR
+ Af8BAAEVAQAB/wMAAQEDJAE2A8kB/gP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8
+ Af8DuQH9AyQBNgQAAdsBlwFaAf8B7QHIAbMB/wHnAbgBmwH/AeYBtAGYAf8B6gHDAasB/wHeAZwBXgH/
+ A1QBr2YAAfUB/wGeAaAB/gH/AQMBBgH+Af8BAAEBAf4B/wGVAZcB/gH/Ac0CAAH/AeEBlwELAf8B2gGA
+ AQAB/wHZASUBAAH/Ad8BjwEAAf8BxgIAAf8BqAHNAaQB/wEfAbABGQH/ARgBqwESAf8BmgHEAZYB/wEA
+ AR4BAAH/AwABAQMkATYD/AH/A/wB/wPdAf8D2wH/A9kB/wPXAf8D1QH/A9QB/wPUAf8D1AH/A/sB/wP8
+ Af8DJAE2AwABAQHdAZ8BZAH/Ae0BzAG3Af8B6AG9AaMB/wHkAbEBkgH/AeYBtgGaAf8B6gHDAawB/wHe
+ AZwBXwH/AlQBUwGsYgAB9gH/AaIBpAH+Af8BCgEOAf4B/wEFAQkB/gH/AZkBmwH+Af8BzwIAAf8B4wGc
+ ARQB/wHcAYYBAAH/AdsBgwEAAf8B4AGUAQYB/wHGAgAB/wGvAdEBqwH/AYABtwEiAf8BIQGyARsB/wGg
AcgBnAH/AQABgAEAAf8DAAEBAyQBNgP8Af8D/AH/A/wB/wP8Af8D+wH/A/sB/wP6Af8D+gH/A/oB/wP6
Af8D+gH/A/wB/wMkATYDAAEBA0wBkgHmAbMBlAH/Ae4BzAG4Af8B6QG+AaUB/wHlAbMBlAH/AeYBtwGb
- Af8B6gHEAa0B/wHeAZ4BZgH/AlQBUwGsXAACBgH4Af8BqAGqAf4B/wEWARoB/gH/ARABFAH+Af8BngGg
- Af4B/wHRAQsBAAH/AeUBogEfAf8B3gGMAQAB/wHdAYkBAAH/AeIBmQERAf8ByQIAAf8BtQHVAbAB/wGK
- Ab0BgwH/AYMBuAEoAf8BpwHNAaMB/wEAAYsBAAH/AwABAQMkATYD/AH/A/wB/wPWAf8D0wH/A88B/wPN
+ Af8B6gHEAa0B/wHeAZ4BYwH/AlQBUwGsXAACAwH4Af8BqAGqAf4B/wETARcB/gH/AQ0BEQH+Af8BngGg
+ Af4B/wHRAQgBAAH/AeUBogEcAf8B3gGMAQAB/wHdAYkBAAH/AeIBmQEOAf8ByQIAAf8BtQHVAbAB/wGK
+ Ab0BgwH/AYMBuAElAf8BpwHNAaMB/wEAAYsBAAH/AwABAQMkATYD/AH/A/wB/wPWAf8D0wH/A88B/wPN
Af8DywH/A8gB/wPIAf8DxgH/A/gB/wP8Af8DJAE2AwABAQQAA0wBkgHmAbQBmAH/Ae4BzQG6Af8B6QG/
- AaUB/wHlAbQBlgH/AecBuQGdAf8B6wHGAa4B/wHeAZ8BZwH/A1MBqlgAAQ4BDwH6Af8BrAGvAf4B/wEd
- ASEB/gH/ARgBHAH+Af8BogGkAf4B/wHWARQBAAH/AecBpwEmAf8B4AGSAQcB/wHfAY8BAQH/AeQBngEZ
+ AaUB/wHlAbQBlgH/AecBuQGdAf8B6wHGAa4B/wHeAZ8BZAH/A1MBqlgAAQsBDAH6Af8BrAGvAf4B/wEa
+ AR4B/gH/ARUBGQH+Af8BogGkAf4B/wHWAREBAAH/AecBpwEjAf8B4AGSAQQB/wHfAY8BAAH/AeQBngEW
Af8BzQIAAf8BugHZAbUB/wG3AdYBsQH/AbMB0wGuAf8BrgHRAakB/wEAAZYBAAH/AwABAQMkATYD/AH/
A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/sB/wP5Af8D+QH/A/gB/wP8Af8DJAE2AwABAQgAA0wBkgHm
- AbcBmQH/Ae4BzgG7Af8B6QHAAacB/wHoAb0BowH/AewByAGzAf8B3wGkAYEB/wNcAclYAAEVARcB/AH/
- AbABswH+Af8BJAEpAf4B/wEgASQB/gH/AagBqgH+Af8B2AEfAQAB/wHoAa0BgwH/AeIBmAEQAf8B4QGV
- AQsB/wHlAaMBIQH/Ac8BAgEAAf8BCwG8ARcB/wEHAbYBEgH/AQIBsAEMAf8BAAGoAQcB/wEAAaEBAAH/
- AwABAQMkATYD/AH/A/wB/wPOAf8DygH/A8YB/wPDAf8DwAH/A70B/wO8Af8DugH/A/YB/wP8Af8DJAE2
- AwABAQwAA0wBkgHmAbcBnAH/Ae8BzwG8Af8B7gHOAboB/wHiAa4BjAH/AdIBmwFpAf8DbQH3AxkBI1QA
- ARsBHgH9Af8BtAG3Af4B/wGBAYUB/gH/AScBgQH+Af8BrAGvAf4B/wHZASYBAAH/AeoBsgGKAf8B5AGf
- ARkB/wHjAZwBFQH/AecBqAEoAf8B0QENAQAB/xcAAQEDJAE2A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/
- A/sB/wP4Af8D9gH/A/MB/wPyAf8D/AH/AyQBNgMAAQEQAANMAZIB5wG5AZwB/wHmAbYBmAH/AdgBqQGM
- Af8D0gH/A7UB/wN/Af4DYgH7A18B+wNgAdYDQAFwRAABHwEjAf4B/wG4AbsB/gH/AbYBuQH+Af8BswG2
- Af4B/wGwAbMB/gH/Ad8BhAEAAf8B7AG3AZIB/wHmAaUBIwH/AeYBogEeAf8B6QGtAYUB/wHWARYBAAH/
- FwABAQMkATYD/AH/A/wB/wPHAf8DwgH/A74B/wO4Af8DtAH/A7EB/wOuAf8DrAH/A+0B/wP8Af8DJAE2
- AwABARQAA0wBkgNcAc8DgAH7A8cB/wPMAf8DxwH/A8YB/wPDAf8DwAH/A2QB9QNAAXBAAAEfASMB/gH/
- AR8BIwH+Af8BHQEhAf4B/wEZARwB/QH/ARUBFwH8Af8B4QGNAQAB/wHtAbsBmQH/AekBrAGBAf8B5wGo
- AScB/wHqAbMBjQH/AdgBHwEAAf8XAAEBAyQBNgP8Af8D+wH/A/wB/wP8Af8D+wH/A/gB/wP1Af8D8QH/
- A+wB/wPqAf8D5gH/A/wB/wMkATYDAAEBHAADLgFIA38B/gPUAf8DyAH/A7wB/wO6Af8DwgH/A8QB/wNg
- AdZUAAHiAZIBBwH/Ae4BwQGgAf8B6gGxAYkB/wHpAa4BhQH/Ae0BtwGUAf8B2wEnAQAB/xcAAQEDJAE2
- A/wB/wP5Af8DwAH/A7oB/wO0Af8DrwH/A6oB/wOlAf8D/AH/A/wB/wP8Af8D/AH/AyQBNgMAAQEgAAN1
- AfwD3QH/A8UB/wNYAcEDWwHDA6wB/wPXAf8DYgH7VAAB5gGbARIB/wHwAcUBpgH/AewBtgGRAf8B6wGz
- AYwB/wHuAbwBmwH/Ad8BhQEAAf8XAAEBAyQBNgP8Af8D9wH/A/kB/wP3Af8D9wH/A/MB/wPwAf8D6gH/
- A/wB/wP2Af8D9AH/A00BkQMXASAkAAOFAfsD5AH/A88B/wNZAcIEAAOOAf8DjAH/A2oB+1QAAegBoAEb
- Af8B8gHIAawB/wHwAcYBqAH/AfABxQGmAf8B7wHCAaIB/wHhAY4BAAH/GAADJAE2A7wB/QP0Af8D9QH/
- A/UB/wP1Af8D8QH/A+8B/wPpAf8D/AH/A+cB/wNNAZEDFwEgAwEBAiQAA2AB1gPiAf8D5wH/A7kB/wOT
- Af9gAAHqAaYBIgH/AegBpAEfAf8B6AGgARkB/wHmAZ0BFgH/AeQBmQEQAf8B4gGVAQkB/xgAAyMBMwNm
- AfADvAH9A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/gB/wNNAZEDFwEgAwEBAigAA0ABcANrAfUD5AH/
- A+4B/wOWAf+QAAMUARwDIwEzAyQBNgMkATYDJAE2AyQBNgMkATYDJAE2AyQBNgMkATYDFwEgAwEBAjAA
- A0ABcANgAdYDhwH7A4YB+2QAAwoBDQEiAiEBMQMgAS8DBQEHGAADEQEXAasCAAH/AWIBWQFIAfYDKQE/
- NAADBgEIAUACPwFuA1YBswFeAlgB3QFSAl0B9AFAAYQBpgH9AgABswH/AgABqAH/AkABnAH9AlIBXQH0
- AVoCWAHdA1YBswFAAj8BbgMGAQhQAAMYASEDUAGdAV0CVAHwA6EB/wOrAf8DpwH/A5UB/wFkAlwB5wNK
- AYoDEAEWDAABugIAAf8BwAGJAQAB/wG/AYkBAAH/Aa8CAAH/AyoBQTAAAVsCWQHEAYcBtwHgAf8BlQHG
- AeYB/wGbAc0B6QH/AZwBzQHpAf8BmQHHAecB/wGVAcEB5AH/AY4BuAHgAf8BiQGwAd0B/wGBAacB1wH/
- AQABmwHPAf8BAAGMAcIB/wIAAa4B/wFbAlkBxBAAAwkBDAJGAUcBgQJZAVwByQIAAegB/wMfAS0oAAMv
- AUoBZQJdAfQDzgH/A+0B/wP0Af8D9QH/A/QB/wPvAf8D4gH/A7oB/wFkAlwB5wMkATUIAAHDAYgBAAH/
- Ac8BogEAAf8BzQGiAYEB/wHAAYwBAAH/AbACAAH/AU4CTQGVAzEBTgMmATkDFgEeAwMBBBwAAVsCWQHE
- AZgBuQHUAf8BxQHHAcQB/wHsAdgBxwH/AfYB6wHjAf8B+gH1AfEB/wHzAecB3gH/Ad8BvwGmAf8B0AGk
- AYEB/wHLAZoBAAH/AcgBlwEAAf8BowGTAYwB/wIAAZwB/wFbAlkBxAwAAy0BRQJaAWAB3gIAAesB/wEF
- AQYB5wH/AgAB6QH/Ax8BLQFdAlkB0gFcAlkByQFHAkYBgQMJAQwYAAFcAlUB6gPeAf8D8wH/A9sB/wPS
- Af8D2wH/A9YB/wPAAf8DyQH/A+YB/wPEAf8BXAJVAeoIAANAAXEBzAGZAQAB/wHQAaMBgQH/Ac8BpAGD
- Af8BygGeAQAB/wG8AYUBAAH/Aa8CAAH/AacCAAH/AZ4CAAH/AVsCWAHGAwcBCRgAAx0BKgHmAcMBpQH/
- Ae8B1gHAAf8B+wHyAeoB/wH+AfwB+gL/Af4B/QH/Af4B/QH8Af8B/AH2AfAB/wH4AegB2QH/AfYB4wHR
- Af8B9gHiAc4B/wHmAcgBrQH/Ac4BoAEAAf8DHQEqCAADNAFUAgAB8wH/ARYBGAHuAf8BlAGZAesB/wGN
- AZEB6QH/AgAB7AH/Ax8BLQFdAlkB0gHWAY4BAAH/AbgCAAH/AWACWgHeAy4BSBQAAVwCVQHqA/AB/wPe
- Af8D1AH/A9IB/wPbAf8D1gH/A78B/wOwAf8DswH/A94B/wFcAlUB6gwAA0EBcgHOAZ0BAAH/AdUBrAGM
- Af8BywGbAQAB/wHMAaABAAH/AcgBmwEAAf8BxQGVAQAB/wHAAY8BAAH/AawCAAH/A0IBdhwAAVgCVgG5
- Ae0B0wG7Af8B+gHwAeUB/wH9AfkB9QH/Af4B/AH6Af8B/gH9AfwB/wH9AfkB9AH/AfYB4wHPAf8B9wHl
- AdMB/wH2AeMB0QH/Ad0BuQGaAf8BVwJWAbgIAAMQARUDXwHzAZUBmQHyAf8BpQGqAe4B/wEUAYEB5gH/
- AZcBmgHrAf8CAAHvAf8DHwEtAV0BWwFZAdIB2wGZAQkB/wHmAaQBGAH/AcsBgAEAAf8BpgIAAf8DNAFU
- EAABXAJVAeoD8gH/A+IB/wPYAf8D1QH/A9wB/wPYAf8DwAH/A7MB/wO3Af8D4AH/AVwCVQHqEAABVgJV
- AbEB0wGoAYYB/wHWAawBjgH/AckBmAEAAf8BxAGQAQAB/wG/AYoBAAH/AcIBjwEAAf8BvwGLAQAB/wFf
- AV0BRgH7Ax0BKRwAAVUCUwGwA38B/gH3AeoB3gH/Af4B+gH3Af8B/gH8AfkB/wH9AfcB8gH/AfoB7QHi
- Af8B6wHQAbcB/wJ/AX4B/gNUAa4MAAMNAREDTgGZAmIBagH5AYQBhQH0Af8BowGoAe8B/wGgAaUB7QH/
- AgAB8QH/Ax8BLQJdAVkB0gHeAaEBEgH/Ad4BiQEAAf8B5gGmARgB/wHQAYcBAAH/AV8CTAHzAxABFQwA
- AVwCVQHqA/MB/wPnAf8D3QH/A9kB/wPgAf8D2wH/A8QB/wO4Af8DuwH/A+EB/wFcAlUB6hAAAzEBTgHU
- AaMBAAH/AdwBtQGYAf8B0AGhAQAB/wHMAZoBAAH/Ac8BpAGDAf8ByAGaAQAB/wEAAYwBAAH/AQABuAEA
- Af8BXwFOATAB+wNUAa8DBwEJGAADJwE6AWECWwHhAfMB4gHSAf8B/AH0Ae0B/wH7AfEB5wH/AekBzAG1
- Af8BYQJcAdwDJgE4EAADQgFzAzwBZgMUARsDSgGNAl0BXwHzARUBFwHzAf8CAAH0Af8DHwEtAl0BWQHS
- AeEBqAGBAf8B4AGSAQAB/wHZARIBAAH/AecBqAGEAf8BvgEJAQAB/wNIAYQMAAFcAlUB6gP0Af8D6gH/
- A+EB/wPdAf8D4wH/A94B/wPJAf8DvQH/A78B/wPiAf8BXAJVAeoQAAMmATkB2wGrAYkB/wHhAb0BogH/
- AdYBqgGHAf8B2QGzAZQB/wHOAZ8BAAH/AV8CXQH7AQABvAEAAf8BkwIAAf8BsAIAAf8BpAIAAf8BYQJe
- AdoDAwEEHAADWQHHAfQB4wHQAf8B8wHfAc0B/wFbAlkBwxgAAVkBXAFZAc8BkAG/AZMB/wFVAVwBVQHq
- A0EBcgMVAR0DRAF7A10B7QMfAS0CXQFZAdIB5AGwAYsB/wHjAZwBBgH/Ad0BhQEAAf8B4gGWAQAB/wHa
- AZcBBgH/AVwCWQHPDAABXAJVAeoD9QH/A+4B/wPmAf8D4gH/A+YB/wPhAf8DzQH/A8IB/wPCAf8D4wH/
- AVwCVQHqEAADFgEeAeABsQGPAf8B5gHEAasB/wHiAb8BpAH/AdgBrQGOAf8DTQH6A0MBdwMrAfwBuwGE
- AQAB/wHAAY8BAAH/AbwBigEAAf8BnAIAAf8DFgEeHAABWwJZAcMB9AHhAc4B/wHzAd8BzAH/AVkCVwHC
- GAABWgJdAfABygHoAcgB/wGvAdkBqwH/AZIBvwGUAf8DXQHtAUUBRgFFAX4DDwEUAxIBGAJdAVkB0gHn
- AbcBkwH/AecBpgEQAf8B4AGQAQAB/wHeAY4BAAH/AeYBrQGIAf8BXwFUAUwB8wwAAVwCVQHqA/YB/wPr
- Af8D3gH/A9YB/wPVAf8D0QH/A8MB/wO8Af8DwAH/A+UB/wFcAlUB6hAAAwMBBAFhAl4B2gHkAbsBnwH/
- AeQBuwGfAf8DKwH8AQABwQEAAf8DKwH8AccBlgEAAf8BywGeAQAB/wG8AYUBAAH/AcMBkgEAAf8BpgIA
- Af8DJgE5FAADJgE4AV4CWAHdAfMB3QHJAf8B+gHuAeIB/wH5AesB3gH/Ae0B0AG2Af8BXwJaAdsDJgE4
- EAABYAJqAfkBtgHgAbEB/wEUAcwBCAH/AZIB0gGJAf8BrQHZAakB/wGJAbgBiwH/A1ABnQM1AVYCYgFJ
- AfYB7wHIAakB/wHmAaYBDAH/AeIBmwEAAf8B4gGYAQAB/wHnAbMBjwH/AV0BXAFOAfAMAAFcAlUB6gP3
- Af8D5wH/A+8B/wP2Af8D+wH/A/oB/wPwAf8D3gH/A8MB/wPmAf8BXAJVAeoUAAMHAQkDVAGvAWoCZgH5
- AQABxQGCAf8BtQGwAYEB/wHYAbABkgH/AdcBrgGPAf8ByQGXAQAB/wHDAY8BAAH/AcgBmwEAAf8BsQIA
- Af8DMQFOEAADVAGvA38B/gH5AewB4AH/Af0B+AH0Af8B+wHwAeYB/wH4AecB1wH/AfkB6wHeAf8B8gHa
- AcUB/wN/Af4DVAGuDAADXAHPAboB3wG4Af8BEwHMAQYB/wEAAcYBAAH/AQsByAEAAf8BqAHaAaMB/wEB
- AagBBgH/AygBPANbAcMB5gG1AY4B/wHwAcwBrAH/AeUBpgEKAf8B6QGxAYQB/wHjAa8BiAH/AlwBWQHP
- DAABXAJVAeoD+AH/A/4Z/wP7Af8D6gH/AVwCVQHqHAADGwEmAagBpgGEAf0B4gG+AaMB/wHfAbcBmgH/
- AdUBqAGGAf8B0AGhAQAB/wHLAZoBAAH/Ac4BogGBAf8BvwGLAQAB/wFOAk0BlQwAAVcCVgG4AfkB4wHN
- Af8B+wHzAewB/wH+AfoB9wH/Af4B+wH4Af8B/AH1Ae0B/wH3AeYB1QH/AfYB4QHMAf8B+QHsAd8B/wH5
- AesB3QH/AesBzgG0Af8BVwJWAbgIAANIAYQBswHaAbUB/wGiAdgBmgH/AQYBygEAAf8BAAHGAQAB/wGA
- AcwBDgH/AaMBzgGjAf8BWQFcAVkBzwMiATIBLgIrAfwB8gHRAbIB/wHrAbkBjQH/AfAByQGqAf8B2AGc
- AQkB/wNIAYQMAAFZAlcBvwPhAf8D/hn/A/sB/wPPAf8BUgJRAaEgAANCAXYB5AG6AZ0B/wHmAcQBqwH/
- AeIBvgGkAf8B3gG5AZwB/wHZAbIBkwH/AdEBowEAAf8B0QGmAYUB/wG7AgAB/wMpAT8EAAMdASoBwAHF
- Ac0B/wGaAbcB3AH/AQABpgHVAf8BAAGVAcoB/wEAAYcBvgH/AgABswH/AgABqAH/AgABnwH/AgABmAH/
- AgABmgH/AQABgwGnAf8BiAGUAZoB/wMdASoEAAMNARIDXwHzAb4B4QG+Af8BlAHUAYkB/wEHAcoBAAH/
- AQcByQEAAf8BngHWAZcB/wGTAcEBlgH/Az0BaQNOAZYB5wG0AY4B/wHzAdMBtQH/AekBuwGYAf8CXwFM
- AfMDDQESDAADHQEqAVwCWAHRA9AB/wPoAf8D8wH/A/0B/wP8Af8D7QH/A+AB/wPCAf8BWwJZAcMDFAEb
- IAADBwEJAVsCWAHGAeMBtAGTAf8B3wGxAY4B/wHaAasBiQH/AdoBrQGMAf8B3AG1AZgB/wHXAa8BkAH/
- AcwBmwEAAf8DTQH6BAABXAJYAdEBhwG3AeAB/wGVAcYB5gH/AZsBzQHpAf8BnAHNAekB/wGZAccB5wH/
- AZUBwQHkAf8BjgG4AeAB/wGJAbAB3QH/AYEBpwHXAf8BAAGbAc8B/wEAAYwBwgH/AgABrgH/AVwCWAHR
- CAADMgFRAaAB1QGoAf8BugHgAbsB/wGnAdoBoAH/ARYBzgEJAf8BGAHNAQwB/wGwAdkBrQH/A10B7QMZ
- ASMDXQHtAesBwgGeAf8B3QGiAQwB/wMyAVEUAAMFAQcBNQI0AVUDVAGuAWACWwHWAV8CXQH7AWoCZgH5
- AVwCWgHNA1IBqQMtAUYDAgEDKAADAwEEAxYBHgMmATkDMQROAZQB2AGnAYIB/wHXAawBiwH/AdMBpwGE
- Af8BYgFcAUkB9gQAAVsCWQHEAYcBtwHgAf8BlQHGAeYB/wGdAc8B6gH/AaEB0wHsAf8BoAHRAesB/wGb
- AcoB6AH/AZYBwgHlAf8BjwG6AeIB/wGHAbEB3QH/AQABowHUAf8BAAGQAcQB/wIAAa4B/wFbAlkBxAwA
- AykBPwNgAd4BtAHcAbcB/wG8AeABugH/AbkB4QG1Af8BzgHqAcsB/wGkAc4BpgH/AU0CTgGWAz0BaQNg
- Ad4DKQE/fAADKQE+AV8CXQH7AWICXAH2Ay4BSAQAAwYBCAFAAj8BbgNWAbMBXgJYAd0BZQJdAfQBQAGd
- AaYB/QEAAZkB0QH/AQABkAHIAf8BQAGEAaYB/QFSAl0B9AFaAlgB3QNWAbMBQAI/AW4DBgEIEAADCQEM
- A0YBfgNbAcYDKwH8AysB/ANbAcYDRQF9AwIBAwMHAQoRAAGdAdkB/wEAAZkB2AH/AQABlAHXAf8BAAGQ
- AdYB/wEAAYwB1QH/AQABiAHUAf8BAAGEAdMB/wEAAYEB0gH/AgAB0QH/AgAB0QH/AgAB0AH/AgABzwH/
- AgABzwH/AgABzgH/YAADOwFjAVkCVwG/AVgCVwG/AzsBYyAAAxUBHQMjATQDJAE2AyQBNgMkATYDJAE2
- AyQBNgMkATYDJAE2AyQBNgMkATYDJAE2AyMBMwMVAR0BAAGjAdoB/wG8AesB+gH/AbwB6wH8Af8BvwHu
- Af4B/wHGAfQC/wHOAfgC/wHTAfoC/wHQAfgC/wHHAfIC/wG6AekB/AH/AbMB5AH5Af8BsAHiAfgB/wGw
- AeIB+AH/AgABzwH/VAADHQEpAwoBDgMBAQIBXAJVAeoDvQH/A7IB/wFcAlUB6gMBAQIDCgEOAx0BKRQA
- AyMBNANZAfUBqAKmAf0D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wGoAqYB/QFfAl0B8wMj
- ATMBAAGoAdsB/wG/AewB+wH/AQABzwH1Af8BAAGwAewB/wMAAf8CAAGJAf8BAAGJAb4B/wEAAZoByAH/
- AQABrgHnAf8BAAGlAeYB/wEAAZoB4QH/AQABuAHuAf8BsQHjAfgB/wIAAdAB/wgAA1IBqQHDAY4BAAH/
- AcABiwEAAf8BvgGIAQAB/wG7AYUBAAH/AbkBgwEAAf8BtAIAAf8BsgIAAf8BsQIAAf8BrgIAAf8BrQIA
- Af8BqwIAAf8BqQIAAf8BqQIAAf8DUgGpDAABUAJPAZsDQAH9AWQCXAHnAxIBGQFkAlwB5wPLAf8DxwH/
- AWMCXAHnAxIBGQNcAecDQAH9AVACTwGbCAADNwFbAV0BVAFOAfABYgFcAUgB9gHlAbcBmgH/AfsC+gH/
- A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/AagCpgH9AyQBNgEAAa0B3AH/AcEB7gH7
- Af8BAAHTAfcB/wEAAdsB/AH/AgABhQH/AZQBxwH5Af8BkQHJAfkB/wEAAYUByQH/AgABrgH/AQABvQHs
- Af8BAAG+Ae8B/wEAAboB7gH/AbMB4wH5Af8CAAHRAf8IAAHIAZIBADX/AakCAAH/CAADRAF7A7wB/wPe
- Af8DpgH/AWUCXQH0A38B/gPEAf8DwgH/AW4CbQH+AWUCXQH0A6YB/wPSAf8DgQH/A0QBewQAAWICWAHv
- AeYBuAGcAf8B6QG/AaUB/wHcAZsBAAH/AeUBuAGdAf8D/AH/A/wB/wP8Af8D+wH/A/sB/wP7Af8D+wH/
- A/sB/wP7Af8D/AH/AyQBNgEAAbIB3QH/AcMB7wH7Af8BAAHWAfgB/wEAAbYB7AH/AQABiQGqAf8B4AHy
- Av8BAAGaAdgB/wIAAb4B/wEAAZgBxQH/AQABhgHFAf8BAAGbAd4B/wEAAb4B7wH/AbQB5QH5Af8CAAHS
- Af8IAAHKAZQBAAv/Af4D/wH9Af8C/gH9Af8C/gH8Af8C/gH8Af8C/gH8Af8C/gH8Af8C/gH6Af8C/gH6
- Af8C/AH5Bf8BqgIAAf8IAANFAX0DfwH+A9UB/wPFAf8DywH/A9EB/wPJAf8DxwH/A8wB/wPFAf8DvQH/
- A8sB/wFvAm4B/gNFAX0EAAFtAmcB9wHrAcQBrQH/AewByAGyAf8B6gHBAakB/wHeAZ4BAAH/AecBuwGh
- Af8D/AH/A/sB/wP7Af8D+gH/A/oB/wP6Af8D+gH/A/oB/wP8Af8DJAE2AQABtwHeAf8BxgHwAfwB/wEA
- AdkB+AH/AQAB4gH9Af8BAAG3AdkB/wEAAbYB1QH/AZABtwHRAf8BAAHJAeQB/wEAAd8B9QH/AQAB0AHt
- Af8BAAGYAdwB/wEAAboB7QH/AbYB5wH5Af8BAAGDAdMB/wgAAcwBlwEAB/8B/AP/Af0B/wL+AfwB/wL+
- AfwB/wL+AfsB/wL9AfoB/wL9AfoB/wL9AfoB/wL9AfoB/wL8AfcB/wL7AfYF/wGsAgAB/wwAA0gBhQPF
- Af8DwQH/A8UB/wPHAf8DqgH/A6cB/wPBAf8DvgH/A7UB/wOqAf8DSAGFCAADQgF1AWoCZgH5AewBxwGw
- Af8B7QHKAbUB/wHrAcMBqwH/Ad4BoQEAAf8B5wG6AZ8B/wP7Af8D+wH/A/sB/wP6Af8D+gH/A/gB/wP4
- Af8D/AH/AyQBNgEAAbsB3wH/AccB8QH8Af8BAAHcAfkB/wEAAbsB7QH/AQABvQHvAf8BAAHGAecB/wEA
- AbgB1gH/AcIB9gH9Af8BAAHfAfcB/wEAAeIB+AH/AQAB0wHwAf8BAAGXAdwB/wGoAdwB9QH/AQABiAHU
- Af8IAAHRAZwBAAX/Av4B/AH/Av4B/AH/Av4B/AH/Av0B+wH/Av0B+wH/Av0B+gH/Av0B+AH/AvsB+QH/
- AfsB+gH3Af8B+wH6AfYB/wH7AfgB9AX/AbACAAH/BAABXAJaAc0BXwJYAeMBYQJWAe4DzwH/A8YB/wPM
- Af8BWwJYAcYDLAFEAywBRAFbAlgBxgPBAf8DvAH/A7kB/wFhAlYB7gFbAlgB4wNaAc0EAANDAXgDfwH+
- Ae0ByAGzAf8B7QHNAbgB/wHpAb4BowH/AdYBjgEAAf8D/AH/A/wB/wP8Af8D+wH/A/kB/wP5Af8D+AH/
- A/wB/wMkATYBAAG/AeAB/wHIAfMB/AH/AQAB3wH5Af8BiQHmAf0B/wGVAecC/wGaAeUC/wEAAcoB5wH/
- AQABywHnAf8BxwH3Af0B/wEAAdwB9QH/AQAB4QH3Af8BAAHUAfEB/wEAAZkB3gH/AQABjQHWAf8IAAHU
- AZ4BAAX/Av4B/AH/Av0B+wH/Av0B/AH/Av0B+wH/Av0B+QH/AvwB+AH/AfsB+QH3Af8B+wH5AfUB/wH7
- AfgB9AH/AfsB9wHyAf8B+wH1AfIF/wGyAgAB/wQAAagCpgH9A+IB/wPSAf8DxgH/A80B/wOxAf8DLAFE
- CAADLAFEA6gB/wPCAf8DtwH/A8AB/wPSAf8DQAH9BwABAQNMAZIB4AGpAYgB/wHrAccBsAH/Ad0BoQEA
- Af8BvAGlAZUB/wOsAf8D0AH/A9QB/wPvAf8D+QH/A/YB/wP2Af8D/AH/AyQBNgEAAcIB4QH/AckB8wH8
- Af8BywHzAf0B/wHUAfYB/gH/AdcB9gL/AdgB9AL/AeAB+AL/AakB4wH1Af8BAAHTAe4B/wHHAfcB/QH/
- AQAB3AH1Af8BAAHiAfcB/wEAAdYB8gH/AQABmAHeAf8DIQEwBAAB1QGgAQAF/wL9AfwB/wL9AfsB/wL9
- AfoB/wL8AfkB/wH8AfsB9wH/AfsB+QH1Af8B+wH4AfQB/wH7AfcB8wH/AfsB9QHyAf8B+gHzAe8B/wH4
- AfIB7AX/AbUCAAH/BAABqAKmAf0D6QH/A9YB/wPJAf8DzgH/A6UB/wMsAUQIAAMsAUQDrAH/A8QB/wO6
- Af8DxgH/A90B/wNAAf0HAAEBAyQBNgHwAdYBxgH/Ad4BrQGQAf8BxAGvAaMB/wPVAf8DuwH/A6YB/wOg
- Af8DkAH/A8kB/wPzAf8D8gH/A/wB/wMkATYBAAHDAeEB/wGIAaABqAH/A5EB/wOOAf8BAAG5AdwB/wEA
- AbgB3wH/AQABtQHeAf8BAAGxAd0B/wEAAbAB3gH/AQAB1AHuAf8BxAH2Af0B/wEAAd0B9gH/AQABygHt
- Af8BAAGjAdcB/wFgAlkB7AMbASYB2AGiAQAF/wL9AfoB/wL8AfoB/wH8AfsB+QH/AfsB+gH2Af8B+wH4
- AfUB/wH7AfcB9AH/AfsB9gHxAf8B+AH0Ae4B/wH3AfIB6wH/AfcB8AHqAf8B9gHsAegF/wG3AYEBAAH/
- BAABXAJaAc0BXwJYAeMBYQJWAe4D2AH/A80B/wO8Af8BWwJYAcYDLAFEAywBRAFbAlgBxgPDAf8DwgH/
- A80B/wFhAlYB7gFfAlgB4wFcAloBzQcAAQEDJAE2A/wB/wP7Af8DrAH/A8sB/wPSAf8DyQH/A9IB/wPG
- Af8DjwH/A+8B/wPtAf8D/AH/AyQBNgQAAVsCWQHDA8YB/wOUAf8DBgEIEAADNwFaAQAB0wHrAf8BsgHj
- AfkB/wGLAcAB5wH/Aa4B0wH2Af8BxAHgAfwB/wNnAfcB2QGjAQAF/wH8AfsB+QH/AfwB+wH4Af8B+wH5
- AfcB/wH7AfcB9AH/AfoB9wHyAf8B+QH1AfAB/wH3AfMB7QH/AfYB7wHqAf8B9QHrAecB/wHzAeoB5AH/
- AfIB5wHeBf8BugGFAQAB/wwAA0gBhQPUAf8DzAH/A8kB/wO6Af8DnAH/A6EB/wPCAf8DxgH/A8EB/wO3
- Af8DSAGFDwABAQMkATYD/AH/A/sB/wPbAf8DsgH/A9YB/wOgAf8DkgH/A8AB/wOKAf8D6gH/A+YB/wP8
- Af8DJAE2BAADVAGuA8QB/wOhAf8DHQEpEAADHQEpAQABmQGpAf8BAAG+AecB/wG0AdIB8AH/AeUB8wL/
- AawB0gHvAf8BXwJXAegB2wGkAQA1/wG9AYcBAAH/CAADRQF9A38B/gPcAf8D1AH/A9kB/wPbAf8D1gH/
- A9QB/wPZAf8D0gH/A8sB/wPIAf8BegJ5Af4DRQF9CwABAQMkATYD/AH/A/kB/wPaAf8DtQH/A+YB/wOa
- Af8DsAH/A68B/wO9Af8D/AH/A/wB/wP8Af8DJAE2BAADQgF1A7oB/wO/Af8BXgJYAd0DFgEfAwQBBQME
- AQUDFgEfAWUCXgHlA6gB/wEAAaQBswH/AQABpQHYAf8BhQGxAdsB/wEAAZ0B0AH/AzgBXgHcAacBAAH/
- AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/AdwBpwEAAf8B3AGn
- AQAB/wHcAacBAAH/AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/AdwBpwEAAf8BwAGLAQAB/wgAA0QBewPc
- Af8D7QH/A9sB/wFlAl0B9AN/Af4D1gH/A9QB/wN/Af4BZQJdAfQDywH/A+cB/wO3Af8DRAF7CwABAQMk
- ATYD/AH/A/cB/wPvAf8DpgH/A+EB/wPSAf8DtAH/A+oB/wP8Af8D9gH/A/QB/wFNAkwBkQMXASAEAAMJ
- AQwBXwJaAdsDxAH/A74B/wOhAf8DlgH/A5MB/wOXAf8DrgH/A64B/wFfAloB2wMHAQkMAAGoAaYBgwH9
- AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5
- AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8BqAGOAUAB/QwAAVACTwGb
- AagCpgH9AWQCXAHnAxIBGQFkAlwB5wPeAf8D3QH/AWQCXAHnAxIBGQFkAlwB5wGnAqUB/QFQAk8BmxAA
- AyQBNgGoAqYB/QP0Af8D9QH/A9QB/wOlAf8DnQH/A74B/wPpAf8D/AH/A+cB/wFNAkwBkQMXASADAQEC
- CAADIQEwAWACWgHeA7wB/wPKAf8DzAH/A8oB/wPCAf8DrQH/AWACWgHeAyEBMBAAAz4BawFlAl0B9AHc
- AacBAAH/AdwBpgEAAf8B2gGkAQAB/wHYAaIBAAH/AdUBoAEAAf8B1AGeAQAB/wHSAZ0BAAH/Ac8BmgEA
- Af8BzgGZAQAB/wHLAZYBAAH/AckBlAEAAf8BZQJdAfQDPgFrEAADHQEpAwoBDgMBAQIBXAJVAeoD5QH/
- A+QB/wFcAlUB6gMBAQIDCgEOAx0BKRQAAyMBMwFdAlQB8AGoAqYB/QP8Af8D/AH/A/wB/wP8Af8D/AH/
- A/wB/wP4Af8BTQJMAZEDFwEgAwEBAhAAAwkBDAFHAkYBgQFXAlUBugFcAlkBzAFcAlkBzAFXAlUBugFH
- AkYBgQMJAQxsAAM7AWMBWQJXAb8BWQJXAb8DOwFjIAADFAEcAyMBMwMkATYDJAE2AyQBNgMkATYDJAE2
- AyQBNgMkATYDJAE2AxcBIAMBAQIIAAFCAU0BPgcAAT4DAAEoAwABQAMAATADAAEBAQABAQUAAYABARYA
- A/8BAAL/AYABAQGHAf8EAAGAAQEBAwH/BQACAQH/BwAB/wcAAX8GAAGAAT8GAAHAAT8GAAHgAR8DAAEf
- AgAB8AEBAwABHwIAAfgEAAEfAgAB/gMAAfgBHwIAAf8DAAH4AR8BAAEBAf8BCAIAAfgBHwGAAQEB/wEH
- AgAB+AEfAYABAwH/AQcCAAL/AYABBwH/AYcCAAH8AT8BDwH/AYABAQL/AeACBwH/AYABAQHgAf8BwAED
- AQABPwGAAQEBwAEPAcABAwEAAR8BgAEBAYABBwHAAQMBgAEfAcABAwEAAQMBwAEDAcABDwHgAQcBAAEB
- AcABAwHAAQMB8AEPAQABAQHAAQMBwAEBAfwBPwEAAQEBwAEDAcABAQH8AT8BAAEBAcABAwHAAQEB8AEP
- AQABAQHAAQMB4AEBAeABBwEAAQEBwAEDAfgBAQHAAQMBAAEBAcABAwH8AQABgAEBAQABAQHAAQMB/AEA
- AYABAQGAAQMB4AEHAf4BAAGAAQEBwAEHA/8B8AGAAQEB4AEPAQABAwL/AfwBPwHAAgABAwL/AeABBwHA
- AgABAwEAAQEBwAEDAwABAwEAAQEBgAEBAwABAwEAAQEBgAEBAwABAwEAAQEBwAEDAwABAwEAAQECAAGA
- AgABAwEAAgECgAIAAQEBAAIBAoAEAAEBAgABgAEAAYcBgAEAAQEBwAEDAYABAAGHAYABAAEBAYABAQGA
- AQABgAIAAQEBgAEBAYABAAGAAQcBAAEBAcABAwHAAQABwAEPAQABAQHgAQcBwAEBAeABHwL/AfwBPwHA
- AQML
+ AbcBmQH/Ae4BzgG7Af8B6QHAAacB/wHoAb0BowH/AewByAGzAf8B3wGkAYEB/wNcAclYAAESARQB/AH/
+ AbABswH+Af8BIQEmAf4B/wEdASEB/gH/AagBqgH+Af8B2AEcAQAB/wHoAa0BgwH/AeIBmAENAf8B4QGV
+ AQgB/wHlAaMBHgH/Ac8CAAH/AQgBvAEUAf8BBAG2AQ8B/wEAAbABCQH/AQABqAEEAf8BAAGhAQAB/wMA
+ AQEDJAE2A/wB/wP8Af8DzgH/A8oB/wPGAf8DwwH/A8AB/wO9Af8DvAH/A7oB/wP2Af8D/AH/AyQBNgMA
+ AQEMAANMAZIB5gG3AZwB/wHvAc8BvAH/Ae4BzgG6Af8B4gGuAYwB/wHSAZsBZgH/A20B9wMZASNUAAEY
+ ARsB/QH/AbQBtwH+Af8BgQGFAf4B/wEkAYEB/gH/AawBrwH+Af8B2QEjAQAB/wHqAbIBigH/AeQBnwEW
+ Af8B4wGcARIB/wHnAagBJQH/AdEBCgEAAf8XAAEBAyQBNgP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP7
+ Af8D+AH/A/YB/wPzAf8D8gH/A/wB/wMkATYDAAEBEAADTAGSAecBuQGcAf8B5gG2AZgB/wHYAakBjAH/
+ A9IB/wO1Af8DfwH+A18B+wNfAfsDYAHWA0ABcEQAARwBIAH+Af8BuAG7Af4B/wG2AbkB/gH/AbMBtgH+
+ Af8BsAGzAf4B/wHfAYQBAAH/AewBtwGSAf8B5gGlASAB/wHmAaIBGwH/AekBrQGFAf8B1gETAQAB/xcA
+ AQEDJAE2A/wB/wP8Af8DxwH/A8IB/wO+Af8DuAH/A7QB/wOxAf8DrgH/A6wB/wPtAf8D/AH/AyQBNgMA
+ AQEUAANMAZIDXAHPA3kB+wPHAf8DzAH/A8cB/wPGAf8DwwH/A8AB/wNeAfUDQAFwQAABHAEgAf4B/wEc
+ ASAB/gH/ARoBHgH+Af8BFgEZAf0B/wESARQB/AH/AeEBjQEAAf8B7QG7AZkB/wHpAawBgQH/AecBqAEk
+ Af8B6gGzAY0B/wHYARwBAAH/FwABAQMkATYD/AH/A/sB/wP8Af8D/AH/A/sB/wP4Af8D9QH/A/EB/wPs
+ Af8D6gH/A+YB/wP8Af8DJAE2AwABARwAAy4BSAN/Af4D1AH/A8gB/wO8Af8DugH/A8IB/wPEAf8DYAHW
+ VAAB4gGSAQQB/wHuAcEBoAH/AeoBsQGJAf8B6QGuAYUB/wHtAbcBlAH/AdsBJAEAAf8XAAEBAyQBNgP8
+ Af8D+QH/A8AB/wO6Af8DtAH/A68B/wOqAf8DpQH/A/wB/wP8Af8D/AH/A/wB/wMkATYDAAEBIAADcgH8
+ A90B/wPFAf8DWAHBA1sBwwOsAf8D1wH/A18B+1QAAeYBmwEPAf8B8AHFAaYB/wHsAbYBkQH/AesBswGM
+ Af8B7gG8AZsB/wHfAYUBAAH/FwABAQMkATYD/AH/A/cB/wP5Af8D9wH/A/cB/wPzAf8D8AH/A+oB/wP8
+ Af8D9gH/A/QB/wNNAZEDFwEgJAADggH7A+QB/wPPAf8DWQHCBAADjgH/A4wB/wNiAftUAAHoAaABGAH/
+ AfIByAGsAf8B8AHGAagB/wHwAcUBpgH/Ae8BwgGiAf8B4QGOAQAB/xgAAyQBNgO5Af0D9AH/A/UB/wP1
+ Af8D9QH/A/EB/wPvAf8D6QH/A/wB/wPnAf8DTQGRAxcBIAMBAQIkAANgAdYD4gH/A+cB/wO5Af8DkwH/
+ YAAB6gGmAR8B/wHoAaQBHAH/AegBoAEWAf8B5gGdARMB/wHkAZkBDQH/AeIBlQEGAf8YAAMjATMDYQHw
+ A7kB/QP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP4Af8DTQGRAxcBIAMBAQIoAANAAXADaAH1A+QB/wPu
+ Af8DlgH/kAADFAEcAyMBMwMkATYDJAE2AyQBNgMkATYDJAE2AyQBNgMkATYDJAE2AxcBIAMBAQIwAANA
+ AXADYAHWA4QB+wODAftkAAMKAQ0BIgIhATEDIAEvAwUBBxgAAxEBFwGrAgAB/wFiAVkBSAH2AykBPzQA
+ AwYBCAFAAj8BbgNWAbMBXgJYAd0BUgJdAfQBQAGEAaYB/QIAAbMB/wIAAagB/wJAAZwB/QJSAV0B9AFa
+ AlgB3QNWAbMBQAI/AW4DBgEIUAADGAEhA1ABnQFdAlQB8AOhAf8DqwH/A6cB/wOVAf8BZAJcAecDSgGK
+ AxABFgwAAboCAAH/AcABiQEAAf8BvwGJAQAB/wGvAgAB/wMqAUEwAAFbAlkBxAGHAbcB4AH/AZUBxgHm
+ Af8BmwHNAekB/wGcAc0B6QH/AZkBxwHnAf8BlQHBAeQB/wGOAbgB4AH/AYkBsAHdAf8BgQGnAdcB/wEA
+ AZsBzwH/AQABjAHCAf8CAAGuAf8BWwJZAcQQAAMJAQwCRgFHAYECWQFcAckCAAHoAf8DHwEtKAADLwFK
+ AWUCXQH0A84B/wPtAf8D9AH/A/UB/wP0Af8D7wH/A+IB/wO6Af8BZAJcAecDJAE1CAABwwGIAQAB/wHP
+ AaIBAAH/Ac0BogGBAf8BwAGMAQAB/wGwAgAB/wFOAk0BlQMxAU4DJgE5AxYBHgMDAQQcAAFbAlkBxAGY
+ AbkB1AH/AcUBxwHEAf8B7AHYAccB/wH2AesB4wH/AfoB9QHxAf8B8wHnAd4B/wHfAb8BpgH/AdABpAGB
+ Af8BywGaAQAB/wHIAZcBAAH/AaMBkwGMAf8CAAGcAf8BWwJZAcQMAAMtAUUCWgFgAd4CAAHrAf8BAgED
+ AecB/wIAAekB/wMfAS0BXQJZAdIBXAJZAckBRwJGAYEDCQEMGAABXAJVAeoD3gH/A/MB/wPbAf8D0gH/
+ A9sB/wPWAf8DwAH/A8kB/wPmAf8DxAH/AVwCVQHqCAADQAFxAcwBmQEAAf8B0AGjAYEB/wHPAaQBgwH/
+ AcoBngEAAf8BvAGFAQAB/wGvAgAB/wGnAgAB/wGeAgAB/wFbAlgBxgMHAQkYAAMdASoB5gHDAaUB/wHv
+ AdYBwAH/AfsB8gHqAf8B/gH8AfoC/wH+Af0B/wH+Af0B/AH/AfwB9gHwAf8B+AHoAdkB/wH2AeMB0QH/
+ AfYB4gHOAf8B5gHIAa0B/wHOAaABAAH/Ax0BKggAAzQBVAIAAfMB/wETARUB7gH/AZQBmQHrAf8BjQGR
+ AekB/wIAAewB/wMfAS0BXQJZAdIB1gGOAQAB/wG4AgAB/wFgAloB3gMuAUgUAAFcAlUB6gPwAf8D3gH/
+ A9QB/wPSAf8D2wH/A9YB/wO/Af8DsAH/A7MB/wPeAf8BXAJVAeoMAANBAXIBzgGdAQAB/wHVAawBjAH/
+ AcsBmwEAAf8BzAGgAQAB/wHIAZsBAAH/AcUBlQEAAf8BwAGPAQAB/wGsAgAB/wNCAXYcAAFYAlYBuQHt
+ AdMBuwH/AfoB8AHlAf8B/QH5AfUB/wH+AfwB+gH/Af4B/QH8Af8B/QH5AfQB/wH2AeMBzwH/AfcB5QHT
+ Af8B9gHjAdEB/wHdAbkBmgH/AVcCVgG4CAADEAEVA18B8wGVAZkB8gH/AaUBqgHuAf8BEQGBAeYB/wGX
+ AZoB6wH/AgAB7wH/Ax8BLQFdAVsBWQHSAdsBmQEGAf8B5gGkARUB/wHLAYABAAH/AaYCAAH/AzQBVBAA
+ AVwCVQHqA/IB/wPiAf8D2AH/A9UB/wPcAf8D2AH/A8AB/wOzAf8DtwH/A+AB/wFcAlUB6hAAAVYCVQGx
+ AdMBqAGGAf8B1gGsAY4B/wHJAZgBAAH/AcQBkAEAAf8BvwGKAQAB/wHCAY8BAAH/Ab8BiwEAAf8BXwFd
+ AUYB+wMdASkcAAFVAlMBsAN/Af4B9wHqAd4B/wH+AfoB9wH/Af4B/AH5Af8B/QH3AfIB/wH6Ae0B4gH/
+ AesB0AG3Af8CfwF+Af4DVAGuDAADDQERA04BmQJiAWoB+QGEAYUB9AH/AaMBqAHvAf8BoAGlAe0B/wIA
+ AfEB/wMfAS0CXQFZAdIB3gGhAQ8B/wHeAYkBAAH/AeYBpgEVAf8B0AGHAQAB/wFfAkwB8wMQARUMAAFc
+ AlUB6gPzAf8D5wH/A90B/wPZAf8D4AH/A9sB/wPEAf8DuAH/A7sB/wPhAf8BXAJVAeoQAAMxAU4B1AGj
+ AQAB/wHcAbUBmAH/AdABoQEAAf8BzAGaAQAB/wHPAaQBgwH/AcgBmgEAAf8BAAGMAQAB/wEAAbgBAAH/
+ AV8BTgEwAfsDVAGvAwcBCRgAAycBOgFhAlsB4QHzAeIB0gH/AfwB9AHtAf8B+wHxAecB/wHpAcwBtQH/
+ AWECXAHcAyYBOBAAA0IBcwM8AWYDFAEbA0oBjQJdAV8B8wESARQB8wH/AgAB9AH/Ax8BLQJdAVkB0gHh
+ AagBgQH/AeABkgEAAf8B2QEPAQAB/wHnAagBhAH/Ab4BBgEAAf8DSAGEDAABXAJVAeoD9AH/A+oB/wPh
+ Af8D3QH/A+MB/wPeAf8DyQH/A70B/wO/Af8D4gH/AVwCVQHqEAADJgE5AdsBqwGJAf8B4QG9AaIB/wHW
+ AaoBhwH/AdkBswGUAf8BzgGfAQAB/wFfAl0B+wEAAbwBAAH/AZMCAAH/AbACAAH/AaQCAAH/AWECXgHa
+ AwMBBBwAA1kBxwH0AeMB0AH/AfMB3wHNAf8BWwJZAcMYAAFZAVwBWQHPAZABvwGTAf8BVQFcAVUB6gNB
+ AXIDFQEdA0QBewNdAe0DHwEtAl0BWQHSAeQBsAGLAf8B4wGcAQMB/wHdAYUBAAH/AeIBlgEAAf8B2gGX
+ AQMB/wFcAlkBzwwAAVwCVQHqA/UB/wPuAf8D5gH/A+IB/wPmAf8D4QH/A80B/wPCAf8DwgH/A+MB/wFc
+ AlUB6hAAAxYBHgHgAbEBjwH/AeYBxAGrAf8B4gG/AaQB/wHYAa0BjgH/A00B+gNDAXcDKwH8AbsBhAEA
+ Af8BwAGPAQAB/wG8AYoBAAH/AZwCAAH/AxYBHhwAAVsCWQHDAfQB4QHOAf8B8wHfAcwB/wFZAlcBwhgA
+ AVoCXQHwAcoB6AHIAf8BrwHZAasB/wGSAb8BlAH/A10B7QFFAUYBRQF+Aw8BFAMSARgCXQFZAdIB5wG3
+ AZMB/wHnAaYBDQH/AeABkAEAAf8B3gGOAQAB/wHmAa0BiAH/AV8BVAFMAfMMAAFcAlUB6gP2Af8D6wH/
+ A94B/wPWAf8D1QH/A9EB/wPDAf8DvAH/A8AB/wPlAf8BXAJVAeoQAAMDAQQBYQJeAdoB5AG7AZ8B/wHk
+ AbsBnwH/AysB/AEAAcEBAAH/AysB/AHHAZYBAAH/AcsBngEAAf8BvAGFAQAB/wHDAZIBAAH/AaYCAAH/
+ AyYBORQAAyYBOAFeAlgB3QHzAd0ByQH/AfoB7gHiAf8B+QHrAd4B/wHtAdABtgH/AV8CWgHbAyYBOBAA
+ AWACagH5AbYB4AGxAf8BEQHMAQUB/wGSAdIBiQH/Aa0B2QGpAf8BiQG4AYsB/wNQAZ0DNQFWAmIBSQH2
+ Ae8ByAGpAf8B5gGmAQkB/wHiAZsBAAH/AeIBmAEAAf8B5wGzAY8B/wFdAVwBTgHwDAABXAJVAeoD9wH/
+ A+cB/wPvAf8D9gH/A/sB/wP6Af8D8AH/A94B/wPDAf8D5gH/AVwCVQHqFAADBwEJA1QBrwFqAmYB+QEA
+ AcUBggH/AbUBsAGBAf8B2AGwAZIB/wHXAa4BjwH/AckBlwEAAf8BwwGPAQAB/wHIAZsBAAH/AbECAAH/
+ AzEBThAAA1QBrwN/Af4B+QHsAeAB/wH9AfgB9AH/AfsB8AHmAf8B+AHnAdcB/wH5AesB3gH/AfIB2gHF
+ Af8DfwH+A1QBrgwAA1wBzwG6Ad8BuAH/ARABzAEDAf8BAAHGAQAB/wEIAcgBAAH/AagB2gGjAf8BAAGo
+ AQMB/wMoATwDWwHDAeYBtQGOAf8B8AHMAawB/wHlAaYBBwH/AekBsQGEAf8B4wGvAYgB/wJcAVkBzwwA
+ AVwCVQHqA/gB/wP+Gf8D+wH/A+oB/wFcAlUB6hwAAxsBJgGoAaYBhAH9AeIBvgGjAf8B3wG3AZoB/wHV
+ AagBhgH/AdABoQEAAf8BywGaAQAB/wHOAaIBgQH/Ab8BiwEAAf8BTgJNAZUMAAFXAlYBuAH5AeMBzQH/
+ AfsB8wHsAf8B/gH6AfcB/wH+AfsB+AH/AfwB9QHtAf8B9wHmAdUB/wH2AeEBzAH/AfkB7AHfAf8B+QHr
+ Ad0B/wHrAc4BtAH/AVcCVgG4CAADSAGEAbMB2gG1Af8BogHYAZoB/wEDAcoBAAH/AQABxgEAAf8BgAHM
+ AQsB/wGjAc4BowH/AVkBXAFZAc8DIgEyAysB/AHyAdEBsgH/AesBuQGNAf8B8AHJAaoB/wHYAZwBBgH/
+ A0gBhAwAAVkCVwG/A+EB/wP+Gf8D+wH/A88B/wFSAlEBoSAAA0IBdgHkAboBnQH/AeYBxAGrAf8B4gG+
+ AaQB/wHeAbkBnAH/AdkBsgGTAf8B0QGjAQAB/wHRAaYBhQH/AbsCAAH/AykBPwQAAx0BKgHAAcUBzQH/
+ AZoBtwHcAf8BAAGmAdUB/wEAAZUBygH/AQABhwG+Af8CAAGzAf8CAAGoAf8CAAGfAf8CAAGYAf8CAAGa
+ Af8BAAGDAacB/wGIAZQBmgH/Ax0BKgQAAw0BEgNfAfMBvgHhAb4B/wGUAdQBiQH/AQQBygEAAf8BBAHJ
+ AQAB/wGeAdYBlwH/AZMBwQGWAf8DPQFpA04BlgHnAbQBjgH/AfMB0wG1Af8B6QG7AZgB/wJfAUwB8wMN
+ ARIMAAMdASoBXAJYAdED0AH/A+gB/wPzAf8D/QH/A/wB/wPtAf8D4AH/A8IB/wFbAlkBwwMUARsgAAMH
+ AQkBWwJYAcYB4wG0AZMB/wHfAbEBjgH/AdoBqwGJAf8B2gGtAYwB/wHcAbUBmAH/AdcBrwGQAf8BzAGb
+ AQAB/wNNAfoEAAFcAlgB0QGHAbcB4AH/AZUBxgHmAf8BmwHNAekB/wGcAc0B6QH/AZkBxwHnAf8BlQHB
+ AeQB/wGOAbgB4AH/AYkBsAHdAf8BgQGnAdcB/wEAAZsBzwH/AQABjAHCAf8CAAGuAf8BXAJYAdEIAAMy
+ AVEBoAHVAagB/wG6AeABuwH/AacB2gGgAf8BEwHOAQYB/wEVAc0BCQH/AbAB2QGtAf8DXQHtAxkBIwNd
+ Ae0B6wHCAZ4B/wHdAaIBCQH/AzIBURQAAwUBBwE1AjQBVQNUAa4BYAJbAdYBXwJdAfsBagJmAfkBXAJa
+ Ac0DUgGpAy0BRgMCAQMoAAMDAQQDFgEeAyYBOQMxBE4BlAHYAacBggH/AdcBrAGLAf8B0wGnAYQB/wFi
+ AVwBSQH2BAABWwJZAcQBhwG3AeAB/wGVAcYB5gH/AZ0BzwHqAf8BoQHTAewB/wGgAdEB6wH/AZsBygHo
+ Af8BlgHCAeUB/wGPAboB4gH/AYcBsQHdAf8BAAGjAdQB/wEAAZABxAH/AgABrgH/AVsCWQHEDAADKQE/
+ A2AB3gG0AdwBtwH/AbwB4AG6Af8BuQHhAbUB/wHOAeoBywH/AaQBzgGmAf8BTQJOAZYDPQFpA2AB3gMp
+ AT98AAMpAT4BXwJdAfsBYgJcAfYDLgFIBAADBgEIAUACPwFuA1YBswFeAlgB3QFlAl0B9AFAAZ0BpgH9
+ AQABmQHRAf8BAAGQAcgB/wFAAYQBpgH9AVICXQH0AVoCWAHdA1YBswFAAj8BbgMGAQgQAAMJAQwDRgF+
+ A1sBxgMrAfwDKwH8A1sBxgNFAX0DAgEDAwcBChEAAZ0B2QH/AQABmQHYAf8BAAGUAdcB/wEAAZAB1gH/
+ AQABjAHVAf8BAAGIAdQB/wEAAYQB0wH/AQABgQHSAf8CAAHRAf8CAAHRAf8CAAHQAf8CAAHPAf8CAAHP
+ Af8CAAHOAf9gAAM7AWMBWQJXAb8BWAJXAb8DOwFjIAADFQEdAyMBNAMkATYDJAE2AyQBNgMkATYDJAE2
+ AyQBNgMkATYDJAE2AyQBNgMkATYDIwEzAxUBHQEAAaMB2gH/AbwB6wH6Af8BvAHrAfwB/wG/Ae4B/gH/
+ AcYB9AL/Ac4B+AL/AdMB+gL/AdAB+AL/AccB8gL/AboB6QH8Af8BswHkAfkB/wGwAeIB+AH/AbAB4gH4
+ Af8CAAHPAf9UAAMdASkDCgEOAwEBAgFcAlUB6gO9Af8DsgH/AVwCVQHqAwEBAgMKAQ4DHQEpFAADIwE0
+ A1kB9QGoAqYB/QP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/AagCpgH9AV8CXQHzAyMBMwEA
+ AagB2wH/Ab8B7AH7Af8BAAHPAfUB/wEAAbAB7AH/AwAB/wIAAYkB/wEAAYkBvgH/AQABmgHIAf8BAAGu
+ AecB/wEAAaUB5gH/AQABmgHhAf8BAAG4Ae4B/wGxAeMB+AH/AgAB0AH/CAADUgGpAcMBjgEAAf8BwAGL
+ AQAB/wG+AYgBAAH/AbsBhQEAAf8BuQGDAQAB/wG0AgAB/wGyAgAB/wGxAgAB/wGuAgAB/wGtAgAB/wGr
+ AgAB/wGpAgAB/wGpAgAB/wNSAakMAAFQAk8BmwNAAf0BZAJcAecDEgEZAWQCXAHnA8sB/wPHAf8BYwJc
+ AecDEgEZA1wB5wNAAf0BUAJPAZsIAAM3AVsBXQFUAU4B8AFiAVwBSAH2AeUBtwGaAf8B+wL6Af8D/AH/
+ A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8BqAKmAf0DJAE2AQABrQHcAf8BwQHuAfsB/wEA
+ AdMB9wH/AQAB2wH8Af8CAAGFAf8BlAHHAfkB/wGRAckB+QH/AQABhQHJAf8CAAGuAf8BAAG9AewB/wEA
+ Ab4B7wH/AQABugHuAf8BswHjAfkB/wIAAdEB/wgAAcgBkgEANf8BqQIAAf8IAANEAXsDvAH/A94B/wOm
+ Af8BZQJdAfQDfwH+A8QB/wPCAf8BbgJtAf4BZQJdAfQDpgH/A9IB/wOBAf8DRAF7BAABYgJYAe8B5gG4
+ AZwB/wHpAb8BpQH/AdwBmwEAAf8B5QG4AZ0B/wP8Af8D/AH/A/wB/wP7Af8D+wH/A/sB/wP7Af8D+wH/
+ A/sB/wP8Af8DJAE2AQABsgHdAf8BwwHvAfsB/wEAAdYB+AH/AQABtgHsAf8BAAGJAaoB/wHgAfIC/wEA
+ AZoB2AH/AgABvgH/AQABmAHFAf8BAAGGAcUB/wEAAZsB3gH/AQABvgHvAf8BtAHlAfkB/wIAAdIB/wgA
+ AcoBlAEAC/8B/gP/Af0B/wL+Af0B/wL+AfwB/wL+AfwB/wL+AfwB/wL+AfwB/wL+AfoB/wL+AfoB/wL8
+ AfkF/wGqAgAB/wgAA0UBfQN/Af4D1QH/A8UB/wPLAf8D0QH/A8kB/wPHAf8DzAH/A8UB/wO9Af8DywH/
+ AW8CbgH+A0UBfQQAAW0CZwH3AesBxAGtAf8B7AHIAbIB/wHqAcEBqQH/Ad4BngEAAf8B5wG7AaEB/wP8
+ Af8D+wH/A/sB/wP6Af8D+gH/A/oB/wP6Af8D+gH/A/wB/wMkATYBAAG3Ad4B/wHGAfAB/AH/AQAB2QH4
+ Af8BAAHiAf0B/wEAAbcB2QH/AQABtgHVAf8BkAG3AdEB/wEAAckB5AH/AQAB3wH1Af8BAAHQAe0B/wEA
+ AZgB3AH/AQABugHtAf8BtgHnAfkB/wEAAYMB0wH/CAABzAGXAQAH/wH8A/8B/QH/Av4B/AH/Av4B/AH/
+ Av4B+wH/Av0B+gH/Av0B+gH/Av0B+gH/Av0B+gH/AvwB9wH/AvsB9gX/AawCAAH/DAADSAGFA8UB/wPB
+ Af8DxQH/A8cB/wOqAf8DpwH/A8EB/wO+Af8DtQH/A6oB/wNIAYUIAANCAXUBagJmAfkB7AHHAbAB/wHt
+ AcoBtQH/AesBwwGrAf8B3gGhAQAB/wHnAboBnwH/A/sB/wP7Af8D+wH/A/oB/wP6Af8D+AH/A/gB/wP8
+ Af8DJAE2AQABuwHfAf8BxwHxAfwB/wEAAdwB+QH/AQABuwHtAf8BAAG9Ae8B/wEAAcYB5wH/AQABuAHW
+ Af8BwgH2Af0B/wEAAd8B9wH/AQAB4gH4Af8BAAHTAfAB/wEAAZcB3AH/AagB3AH1Af8BAAGIAdQB/wgA
+ AdEBnAEABf8C/gH8Af8C/gH8Af8C/gH8Af8C/QH7Af8C/QH7Af8C/QH6Af8C/QH4Af8C+wH5Af8B+wH6
+ AfcB/wH7AfoB9gH/AfsB+AH0Bf8BsAIAAf8EAAFcAloBzQFfAlgB4wFhAlYB7gPPAf8DxgH/A8wB/wFb
+ AlgBxgMsAUQDLAFEAVsCWAHGA8EB/wO8Af8DuQH/AWECVgHuAVsCWAHjA1oBzQQAA0MBeAN/Af4B7QHI
+ AbMB/wHtAc0BuAH/AekBvgGjAf8B1gGOAQAB/wP8Af8D/AH/A/wB/wP7Af8D+QH/A/kB/wP4Af8D/AH/
+ AyQBNgEAAb8B4AH/AcgB8wH8Af8BAAHfAfkB/wGJAeYB/QH/AZUB5wL/AZoB5QL/AQABygHnAf8BAAHL
+ AecB/wHHAfcB/QH/AQAB3AH1Af8BAAHhAfcB/wEAAdQB8QH/AQABmQHeAf8BAAGNAdYB/wgAAdQBngEA
+ Bf8C/gH8Af8C/QH7Af8C/QH8Af8C/QH7Af8C/QH5Af8C/AH4Af8B+wH5AfcB/wH7AfkB9QH/AfsB+AH0
+ Af8B+wH3AfIB/wH7AfUB8gX/AbICAAH/BAABqAKmAf0D4gH/A9IB/wPGAf8DzQH/A7EB/wMsAUQIAAMs
+ AUQDqAH/A8IB/wO3Af8DwAH/A9IB/wNAAf0HAAEBA0wBkgHgAakBiAH/AesBxwGwAf8B3QGhAQAB/wG8
+ AaUBlQH/A6wB/wPQAf8D1AH/A+8B/wP5Af8D9gH/A/YB/wP8Af8DJAE2AQABwgHhAf8ByQHzAfwB/wHL
+ AfMB/QH/AdQB9gH+Af8B1wH2Av8B2AH0Av8B4AH4Av8BqQHjAfUB/wEAAdMB7gH/AccB9wH9Af8BAAHc
+ AfUB/wEAAeIB9wH/AQAB1gHyAf8BAAGYAd4B/wMhATAEAAHVAaABAAX/Av0B/AH/Av0B+wH/Av0B+gH/
+ AvwB+QH/AfwB+wH3Af8B+wH5AfUB/wH7AfgB9AH/AfsB9wHzAf8B+wH1AfIB/wH6AfMB7wH/AfgB8gHs
+ Bf8BtQIAAf8EAAGoAqYB/QPpAf8D1gH/A8kB/wPOAf8DpQH/AywBRAgAAywBRAOsAf8DxAH/A7oB/wPG
+ Af8D3QH/A0AB/QcAAQEDJAE2AfAB1gHGAf8B3gGtAZAB/wHEAa8BowH/A9UB/wO7Af8DpgH/A6AB/wOQ
+ Af8DyQH/A/MB/wPyAf8D/AH/AyQBNgEAAcMB4QH/AYgBoAGoAf8DkQH/A44B/wEAAbkB3AH/AQABuAHf
+ Af8BAAG1Ad4B/wEAAbEB3QH/AQABsAHeAf8BAAHUAe4B/wHEAfYB/QH/AQAB3QH2Af8BAAHKAe0B/wEA
+ AaMB1wH/AWACWQHsAxsBJgHYAaIBAAX/Av0B+gH/AvwB+gH/AfwB+wH5Af8B+wH6AfYB/wH7AfgB9QH/
+ AfsB9wH0Af8B+wH2AfEB/wH4AfQB7gH/AfcB8gHrAf8B9wHwAeoB/wH2AewB6AX/AbcBgQEAAf8EAAFc
+ AloBzQFfAlgB4wFhAlYB7gPYAf8DzQH/A7wB/wFbAlgBxgMsAUQDLAFEAVsCWAHGA8MB/wPCAf8DzQH/
+ AWECVgHuAV8CWAHjAVwCWgHNBwABAQMkATYD/AH/A/sB/wOsAf8DywH/A9IB/wPJAf8D0gH/A8YB/wOP
+ Af8D7wH/A+0B/wP8Af8DJAE2BAABWwJZAcMDxgH/A5QB/wMGAQgQAAM3AVoBAAHTAesB/wGyAeMB+QH/
+ AYsBwAHnAf8BrgHTAfYB/wHEAeAB/AH/A2cB9wHZAaMBAAX/AfwB+wH5Af8B/AH7AfgB/wH7AfkB9wH/
+ AfsB9wH0Af8B+gH3AfIB/wH5AfUB8AH/AfcB8wHtAf8B9gHvAeoB/wH1AesB5wH/AfMB6gHkAf8B8gHn
+ Ad4F/wG6AYUBAAH/DAADSAGFA9QB/wPMAf8DyQH/A7oB/wOcAf8DoQH/A8IB/wPGAf8DwQH/A7cB/wNI
+ AYUPAAEBAyQBNgP8Af8D+wH/A9sB/wOyAf8D1gH/A6AB/wOSAf8DwAH/A4oB/wPqAf8D5gH/A/wB/wMk
+ ATYEAANUAa4DxAH/A6EB/wMdASkQAAMdASkBAAGZAakB/wEAAb4B5wH/AbQB0gHwAf8B5QHzAv8BrAHS
+ Ae8B/wFfAlcB6AHbAaQBADX/Ab0BhwEAAf8IAANFAX0DfwH+A9wB/wPUAf8D2QH/A9sB/wPWAf8D1AH/
+ A9kB/wPSAf8DywH/A8gB/wF6AnkB/gNFAX0LAAEBAyQBNgP8Af8D+QH/A9oB/wO1Af8D5gH/A5oB/wOw
+ Af8DrwH/A70B/wP8Af8D/AH/A/wB/wMkATYEAANCAXUDugH/A78B/wFeAlgB3QMWAR8DBAEFAwQBBQMW
+ AR8BZQJeAeUDqAH/AQABpAGzAf8BAAGlAdgB/wGFAbEB2wH/AQABnQHQAf8DOAFeAdwBpwEAAf8B3AGn
+ AQAB/wHcAacBAAH/AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/
+ AdwBpwEAAf8B3AGnAQAB/wHcAacBAAH/AdwBpwEAAf8B3AGnAQAB/wHAAYsBAAH/CAADRAF7A9wB/wPt
+ Af8D2wH/AWUCXQH0A38B/gPWAf8D1AH/A38B/gFlAl0B9APLAf8D5wH/A7cB/wNEAXsLAAEBAyQBNgP8
+ Af8D9wH/A+8B/wOmAf8D4QH/A9IB/wO0Af8D6gH/A/wB/wP2Af8D9AH/AU0CTAGRAxcBIAQAAwkBDAFf
+ AloB2wPEAf8DvgH/A6EB/wOWAf8DkwH/A5cB/wOuAf8DrgH/AV8CWgHbAwcBCQwAAagBpgGDAf0B6AG5
+ AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/
+ AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wGoAY4BQAH9DAABUAJPAZsBqAKm
+ Af0BZAJcAecDEgEZAWQCXAHnA94B/wPdAf8BZAJcAecDEgEZAWQCXAHnAacCpQH9AVACTwGbEAADJAE2
+ AagCpgH9A/QB/wP1Af8D1AH/A6UB/wOdAf8DvgH/A+kB/wP8Af8D5wH/AU0CTAGRAxcBIAMBAQIIAAMh
+ ATABYAJaAd4DvAH/A8oB/wPMAf8DygH/A8IB/wOtAf8BYAJaAd4DIQEwEAADPgFrAWUCXQH0AdwBpwEA
+ Af8B3AGmAQAB/wHaAaQBAAH/AdgBogEAAf8B1QGgAQAB/wHUAZ4BAAH/AdIBnQEAAf8BzwGaAQAB/wHO
+ AZkBAAH/AcsBlgEAAf8ByQGUAQAB/wFlAl0B9AM+AWsQAAMdASkDCgEOAwEBAgFcAlUB6gPlAf8D5AH/
+ AVwCVQHqAwEBAgMKAQ4DHQEpFAADIwEzAV0CVAHwAagCpgH9A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/
+ A/gB/wFNAkwBkQMXASADAQECEAADCQEMAUcCRgGBAVcCVQG6AVwCWQHMAVwCWQHMAVcCVQG6AUcCRgGB
+ AwkBDGwAAzsBYwFZAlcBvwFZAlcBvwM7AWMgAAMUARwDIwEzAyQBNgMkATYDJAE2AyQBNgMkATYDJAE2
+ AyQBNgMkATYDFwEgAwEBAggAAUIBTQE+BwABPgMAASgDAAFAAwABMAMAAQEBAAEBBQABgAEBFgAD/wEA
+ Av8BgAEBAYcB/wQAAYABAQEDAf8FAAIBAf8HAAH/BwABfwYAAYABPwYAAcABPwYAAeABHwMAAR8CAAHw
+ AQEDAAEfAgAB+AQAAR8CAAH+AwAB+AEfAgAB/wMAAfgBHwEAAQEB/wEIAgAB+AEfAYABAQH/AQcCAAH4
+ AR8BgAEDAf8BBwIAAv8BgAEHAf8BhwIAAfwBPwEPAf8BgAEBAv8B4AIHAf8BgAEBAeAB/wHAAQMBAAE/
+ AYABAQHAAQ8BwAEDAQABHwGAAQEBgAEHAcABAwGAAR8BwAEDAQABAwHAAQMBwAEPAeABBwEAAQEBwAED
+ AcABAwHwAQ8BAAEBAcABAwHAAQEB/AE/AQABAQHAAQMBwAEBAfwBPwEAAQEBwAEDAcABAQHwAQ8BAAEB
+ AcABAwHgAQEB4AEHAQABAQHAAQMB+AEBAcABAwEAAQEBwAEDAfwBAAGAAQEBAAEBAcABAwH8AQABgAEB
+ AYABAwHgAQcB/gEAAYABAQHAAQcD/wHwAYABAQHgAQ8BAAEDAv8B/AE/AcACAAEDAv8B4AEHAcACAAED
+ AQABAQHAAQMDAAEDAQABAQGAAQEDAAEDAQABAQGAAQEDAAEDAQABAQHAAQMDAAEDAQABAQIAAYACAAED
+ AQACAQKAAgABAQEAAgECgAQAAQECAAGAAQABhwGAAQABAQHAAQMBgAEAAYcBgAEAAQEBgAEBAYABAAGA
+ AgABAQGAAQEBgAEAAYABBwEAAQEBwAEDAcABAAHAAQ8BAAEBAeABBwHAAQEB4AEfAv8B/AE/AcABAws=
-
- 338, 17
-
457, 17
diff --git a/trunk/ProcessHacker/Forms/ProtectProcessWindow.Designer.cs b/trunk/ProcessHacker/Forms/ProtectProcessWindow.Designer.cs
new file mode 100644
index 000000000..7625f84ad
--- /dev/null
+++ b/trunk/ProcessHacker/Forms/ProtectProcessWindow.Designer.cs
@@ -0,0 +1,143 @@
+namespace ProcessHacker
+{
+ partial class ProtectProcessWindow
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.checkProtect = new System.Windows.Forms.CheckBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.listProcessAccess = new System.Windows.Forms.CheckedListBox();
+ this.listThreadAccess = new System.Windows.Forms.CheckedListBox();
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.buttonOK = new System.Windows.Forms.Button();
+ this.SuspendLayout();
+ //
+ // checkProtect
+ //
+ this.checkProtect.AutoSize = true;
+ this.checkProtect.FlatStyle = System.Windows.Forms.FlatStyle.System;
+ this.checkProtect.Location = new System.Drawing.Point(12, 12);
+ this.checkProtect.Name = "checkProtect";
+ this.checkProtect.Size = new System.Drawing.Size(125, 18);
+ this.checkProtect.TabIndex = 0;
+ this.checkProtect.Text = "Protect this process";
+ this.checkProtect.UseVisualStyleBackColor = true;
+ this.checkProtect.CheckedChanged += new System.EventHandler(this.checkProtect_CheckedChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 42);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(124, 13);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "Allowed process access:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(12, 155);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(117, 13);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "Allowed thread access:";
+ //
+ // listProcessAccess
+ //
+ this.listProcessAccess.FormattingEnabled = true;
+ this.listProcessAccess.Location = new System.Drawing.Point(12, 58);
+ this.listProcessAccess.Name = "listProcessAccess";
+ this.listProcessAccess.Size = new System.Drawing.Size(474, 94);
+ this.listProcessAccess.TabIndex = 3;
+ //
+ // listThreadAccess
+ //
+ this.listThreadAccess.FormattingEnabled = true;
+ this.listThreadAccess.Location = new System.Drawing.Point(12, 171);
+ this.listThreadAccess.Name = "listThreadAccess";
+ this.listThreadAccess.Size = new System.Drawing.Size(474, 94);
+ this.listThreadAccess.TabIndex = 3;
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonCancel.Location = new System.Drawing.Point(411, 271);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 4;
+ this.buttonCancel.Text = "Cancel";
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
+ //
+ // buttonOK
+ //
+ this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOK.Location = new System.Drawing.Point(330, 271);
+ this.buttonOK.Name = "buttonOK";
+ this.buttonOK.Size = new System.Drawing.Size(75, 23);
+ this.buttonOK.TabIndex = 4;
+ this.buttonOK.Text = "OK";
+ this.buttonOK.UseVisualStyleBackColor = true;
+ this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
+ //
+ // ProtectProcessWindow
+ //
+ this.AcceptButton = this.buttonOK;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(498, 306);
+ this.Controls.Add(this.buttonOK);
+ this.Controls.Add(this.buttonCancel);
+ this.Controls.Add(this.listThreadAccess);
+ this.Controls.Add(this.listProcessAccess);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.checkProtect);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "ProtectProcessWindow";
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Protect Process";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.CheckBox checkProtect;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.CheckedListBox listProcessAccess;
+ private System.Windows.Forms.CheckedListBox listThreadAccess;
+ private System.Windows.Forms.Button buttonCancel;
+ private System.Windows.Forms.Button buttonOK;
+ }
+}
\ No newline at end of file
diff --git a/trunk/ProcessHacker/Forms/ProtectProcessWindow.cs b/trunk/ProcessHacker/Forms/ProtectProcessWindow.cs
new file mode 100644
index 000000000..755dd84a7
--- /dev/null
+++ b/trunk/ProcessHacker/Forms/ProtectProcessWindow.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using ProcessHacker.Native;
+using ProcessHacker.Native.Objects;
+using ProcessHacker.Native.Security;
+
+namespace ProcessHacker
+{
+ public partial class ProtectProcessWindow : Form
+ {
+ private int _pid;
+ private bool _isProtected;
+
+ public ProtectProcessWindow(int pid)
+ {
+ InitializeComponent();
+
+ _pid = pid;
+
+ ProcessAccess processAccess;
+ ThreadAccess threadAccess;
+
+ if (ProtectQuery(_pid, out processAccess, out threadAccess))
+ checkProtect.Checked = _isProtected = true;
+
+ foreach (string value in Enum.GetNames(typeof(ProcessAccess)))
+ {
+ if (value == "All")
+ continue;
+
+ listProcessAccess.Items.Add(value,
+ (processAccess & (ProcessAccess)Enum.Parse(typeof(ProcessAccess), value)) != 0);
+ }
+
+ foreach (string value in Enum.GetNames(typeof(ThreadAccess)))
+ {
+ if (value == "All")
+ continue;
+
+ listThreadAccess.Items.Add(value,
+ (threadAccess & (ThreadAccess)Enum.Parse(typeof(ThreadAccess), value)) != 0);
+ }
+
+ checkProtect_CheckedChanged(null, null);
+ }
+
+ private bool ProtectQuery(int pid, out ProcessAccess processAccess, out ThreadAccess threadAccess)
+ {
+ try
+ {
+ using (var phandle = new ProcessHandle(pid, Program.MinProcessQueryRights))
+ KProcessHacker.Instance.ProtectQuery(phandle, out processAccess, out threadAccess);
+
+ return true;
+ }
+ catch
+ {
+ processAccess = 0;
+ threadAccess = 0;
+
+ return false;
+ }
+ }
+
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+
+ private void buttonOK_Click(object sender, EventArgs e)
+ {
+ // remove protection
+ if (_isProtected)
+ {
+ try
+ {
+ using (var phandle = new ProcessHandle(_pid, Program.MinProcessQueryRights))
+ KProcessHacker.Instance.ProtectRemove(phandle);
+ }
+ catch
+ { }
+ }
+
+ // re-add protection (with new masks)
+ if (checkProtect.Checked)
+ {
+ ProcessAccess processAccess = 0;
+ ThreadAccess threadAccess = 0;
+
+ foreach (string value in listProcessAccess.CheckedItems)
+ processAccess |= (ProcessAccess)Enum.Parse(typeof(ProcessAccess), value);
+ foreach (string value in listThreadAccess.CheckedItems)
+ threadAccess |= (ThreadAccess)Enum.Parse(typeof(ThreadAccess), value);
+
+ try
+ {
+ using (var phandle = new ProcessHandle(_pid, Program.MinProcessQueryRights))
+ KProcessHacker.Instance.ProtectAdd(phandle, processAccess, threadAccess);
+ }
+ catch
+ { }
+ }
+
+ this.Close();
+ }
+
+ private void checkProtect_CheckedChanged(object sender, EventArgs e)
+ {
+ listProcessAccess.Enabled = checkProtect.Checked;
+ listThreadAccess.Enabled = checkProtect.Checked;
+ }
+ }
+}
diff --git a/trunk/ProcessHacker/Forms/ProtectProcessWindow.resx b/trunk/ProcessHacker/Forms/ProtectProcessWindow.resx
new file mode 100644
index 000000000..ff31a6db5
--- /dev/null
+++ b/trunk/ProcessHacker/Forms/ProtectProcessWindow.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/trunk/ProcessHacker/ProcessHacker.csproj b/trunk/ProcessHacker/ProcessHacker.csproj
index f77eecf86..f2a06542e 100644
--- a/trunk/ProcessHacker/ProcessHacker.csproj
+++ b/trunk/ProcessHacker/ProcessHacker.csproj
@@ -230,6 +230,9 @@
ProcessWindow.cs
Designer
+
+ ProtectProcessWindow.cs
+
StructWindow.cs
@@ -330,6 +333,12 @@
ProcessStatistics.cs
+
+ Form
+
+
+ ProtectProcessWindow.cs
+
diff --git a/trunk/ProcessHacker/Properties/Settings.Designer.cs b/trunk/ProcessHacker/Properties/Settings.Designer.cs
index 099e372b6..7448c2cf9 100644
--- a/trunk/ProcessHacker/Properties/Settings.Designer.cs
+++ b/trunk/ProcessHacker/Properties/Settings.Designer.cs
@@ -1452,5 +1452,17 @@ namespace ProcessHacker.Properties {
this["HideProcessHackerNetworkConnections"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool EnableExperimentalFeatures {
+ get {
+ return ((bool)(this["EnableExperimentalFeatures"]));
+ }
+ set {
+ this["EnableExperimentalFeatures"] = value;
+ }
+ }
}
}
diff --git a/trunk/ProcessHacker/Properties/Settings.settings b/trunk/ProcessHacker/Properties/Settings.settings
index acbfd414f..d420789c8 100644
--- a/trunk/ProcessHacker/Properties/Settings.settings
+++ b/trunk/ProcessHacker/Properties/Settings.settings
@@ -359,5 +359,8 @@
True
+
+ False
+
\ No newline at end of file
diff --git a/trunk/ProcessHacker/app.config b/trunk/ProcessHacker/app.config
index cd60bb70a..03329be84 100644
--- a/trunk/ProcessHacker/app.config
+++ b/trunk/ProcessHacker/app.config
@@ -364,6 +364,9 @@
True
+
+ False
+
\ No newline at end of file