diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.rc b/2.x/trunk/ProcessHacker/ProcessHacker.rc
index 14a931efd..2d596c99b 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.rc
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.rc
@@ -727,6 +727,48 @@ BEGIN
LTEXT "Unknown",IDC_SIZE_,43,18,136,8
END
+IDD_AFFINITY DIALOGEX 0, 0, 199, 145
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Affinity"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,88,124,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,142,124,50,14
+ LTEXT "Affinity controls which CPUs the process' threads are allowed to execute on.",IDC_STATIC,7,7,185,18
+ CONTROL "CPU 0",IDC_CPU0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,28,35,10
+ CONTROL "CPU 1",IDC_CPU1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,40,35,10
+ CONTROL "CPU 2",IDC_CPU2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,51,35,10
+ CONTROL "CPU 3",IDC_CPU3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,63,35,10
+ CONTROL "CPU 4",IDC_CPU4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,74,35,10
+ CONTROL "CPU 5",IDC_CPU5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,85,35,10
+ CONTROL "CPU 6",IDC_CPU6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,96,35,10
+ CONTROL "CPU 7",IDC_CPU7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,107,35,10
+ CONTROL "CPU 8",IDC_CPU8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,28,35,10
+ CONTROL "CPU 9",IDC_CPU9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,40,35,10
+ CONTROL "CPU 10",IDC_CPU10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,51,39,10
+ CONTROL "CPU 11",IDC_CPU11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,63,39,10
+ CONTROL "CPU 12",IDC_CPU12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,74,39,10
+ CONTROL "CPU 13",IDC_CPU13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,85,39,10
+ CONTROL "CPU 14",IDC_CPU14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,96,39,10
+ CONTROL "CPU 15",IDC_CPU15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,107,39,10
+ CONTROL "CPU 16",IDC_CPU16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,28,39,10
+ CONTROL "CPU 17",IDC_CPU17,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,40,39,10
+ CONTROL "CPU 18",IDC_CPU18,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,51,39,10
+ CONTROL "CPU 19",IDC_CPU19,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,63,39,10
+ CONTROL "CPU 20",IDC_CPU20,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,74,39,10
+ CONTROL "CPU 21",IDC_CPU21,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,85,39,10
+ CONTROL "CPU 22",IDC_CPU22,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,96,39,10
+ CONTROL "CPU 23",IDC_CPU23,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,107,39,10
+ CONTROL "CPU 24",IDC_CPU24,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,28,39,10
+ CONTROL "CPU 25",IDC_CPU25,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,40,39,10
+ CONTROL "CPU 26",IDC_CPU26,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,51,39,10
+ CONTROL "CPU 27",IDC_CPU27,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,63,39,10
+ CONTROL "CPU 28",IDC_CPU28,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,74,39,10
+ CONTROL "CPU 29",IDC_CPU29,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,85,39,10
+ CONTROL "CPU 30",IDC_CPU30,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,96,39,10
+ CONTROL "CPU 31",IDC_CPU31,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,144,107,39,10
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -967,6 +1009,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
+
+ IDD_AFFINITY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 192
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 138
+ END
END
#endif // APSTUDIO_INVOKED
diff --git a/2.x/trunk/ProcessHacker/ProcessHacker.vcproj b/2.x/trunk/ProcessHacker/ProcessHacker.vcproj
index 4e494609b..db2736c08 100644
--- a/2.x/trunk/ProcessHacker/ProcessHacker.vcproj
+++ b/2.x/trunk/ProcessHacker/ProcessHacker.vcproj
@@ -368,6 +368,10 @@
RelativePath=".\actions.c"
>
+
+
diff --git a/2.x/trunk/ProcessHacker/about.c b/2.x/trunk/ProcessHacker/about.c
index 15244ba26..f95f84c5b 100644
--- a/2.x/trunk/ProcessHacker/about.c
+++ b/2.x/trunk/ProcessHacker/about.c
@@ -22,7 +22,7 @@
#include
-static INT_PTR CALLBACK PhpAboutDlgProc(
+static INT_PTR CALLBACK PhpAboutDlgProc(
__in HWND hwndDlg,
__in UINT uMsg,
__in WPARAM wParam,
diff --git a/2.x/trunk/ProcessHacker/affinity.c b/2.x/trunk/ProcessHacker/affinity.c
new file mode 100644
index 000000000..c7dc87e2a
--- /dev/null
+++ b/2.x/trunk/ProcessHacker/affinity.c
@@ -0,0 +1,168 @@
+/*
+ * Process Hacker -
+ * process affinity editor
+ *
+ * Copyright (C) 2010 wj32
+ *
+ * This file is part of Process Hacker.
+ *
+ * Process Hacker is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Process Hacker is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Process Hacker. If not, see .
+ */
+
+#include
+#include
+
+INT_PTR CALLBACK PhpProcessAffinityDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ );
+
+VOID PhShowProcessAffinityDialog(
+ __in HWND ParentWindowHandle,
+ __in PPH_PROCESS_ITEM ProcessItem
+ )
+{
+ DialogBoxParam(
+ PhInstanceHandle,
+ MAKEINTRESOURCE(IDD_AFFINITY),
+ ParentWindowHandle,
+ PhpProcessAffinityDlgProc,
+ (LPARAM)ProcessItem
+ );
+}
+
+static INT_PTR CALLBACK PhpProcessAffinityDlgProc(
+ __in HWND hwndDlg,
+ __in UINT uMsg,
+ __in WPARAM wParam,
+ __in LPARAM lParam
+ )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ NTSTATUS status;
+ PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)lParam;
+ HANDLE processHandle;
+ PROCESS_BASIC_INFORMATION basicInfo;
+ SYSTEM_BASIC_INFORMATION systemBasicInfo;
+ ULONG i;
+
+ SetProp(hwndDlg, L"ProcessItem", (HANDLE)processItem);
+ PhCenterWindow(hwndDlg, GetParent(hwndDlg));
+
+ if (NT_SUCCESS(status = PhOpenProcess(
+ &processHandle,
+ ProcessQueryAccess,
+ processItem->ProcessId
+ )))
+ {
+ status = PhGetProcessBasicInformation(processHandle, &basicInfo);
+
+ if (NT_SUCCESS(status))
+ {
+ status = NtQuerySystemInformation(
+ SystemBasicInformation,
+ &systemBasicInfo,
+ sizeof(SYSTEM_BASIC_INFORMATION),
+ NULL
+ );
+ }
+
+ NtClose(processHandle);
+ }
+
+ if (!NT_SUCCESS(status))
+ {
+ PhShowStatus(hwndDlg, L"Unable to retrieve the process' affinity", status, 0);
+ EndDialog(hwndDlg, IDCANCEL);
+ }
+
+ // Disable the CPU checkboxes which aren't part of the system affinity mask,
+ // and check the CPU checkboxes which are part of the process affinity mask.
+
+ for (i = 0; i < 32; i++)
+ {
+ if ((systemBasicInfo.ActiveProcessorsAffinityMask >> i) & 0x1)
+ {
+ if ((basicInfo.AffinityMask >> i) & 0x1)
+ {
+ Button_SetCheck(GetDlgItem(hwndDlg, IDC_CPU0 + i), BST_CHECKED);
+ }
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CPU0 + i), FALSE);
+ }
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ RemoveProp(hwndDlg, L"ProcessItem");
+ }
+ break;
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDCANCEL:
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ case IDOK:
+ {
+ NTSTATUS status;
+ PPH_PROCESS_ITEM processItem = (PPH_PROCESS_ITEM)GetProp(hwndDlg, L"ProcessItem");
+ ULONG i;
+ ULONG_PTR affinityMask;
+ HANDLE processHandle;
+
+ // Work out the affinity mask.
+
+ affinityMask = 0;
+
+ for (i = 0; i < 32; i++)
+ {
+ if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_CPU0 + i)) == BST_CHECKED)
+ affinityMask |= 1 << i;
+ }
+
+ // Open the process and set the affinity mask.
+
+ if (NT_SUCCESS(status = PhOpenProcess(
+ &processHandle,
+ PROCESS_SET_INFORMATION,
+ processItem->ProcessId
+ )))
+ {
+ status = PhSetProcessAffinityMask(processHandle, affinityMask);
+ NtClose(processHandle);
+ }
+
+ if (NT_SUCCESS(status))
+ EndDialog(hwndDlg, IDOK);
+ else
+ PhShowStatus(hwndDlg, L"Unable to set the process' affinity", status, 0);
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/2.x/trunk/ProcessHacker/include/phapp.h b/2.x/trunk/ProcessHacker/include/phapp.h
index 55ab41a78..246a7cf0f 100644
--- a/2.x/trunk/ProcessHacker/include/phapp.h
+++ b/2.x/trunk/ProcessHacker/include/phapp.h
@@ -398,6 +398,13 @@ VOID PhShowAboutDialog(
PPH_STRING PhGetDiagnosticsString();
+// affinity
+
+VOID PhShowProcessAffinityDialog(
+ __in HWND ParentWindowHandle,
+ __in PPH_PROCESS_ITEM ProcessItem
+ );
+
// findobj
VOID PhShowFindObjectsDialog();
diff --git a/2.x/trunk/ProcessHacker/mainwnd.c b/2.x/trunk/ProcessHacker/mainwnd.c
index 771adeb93..44a70c09b 100644
--- a/2.x/trunk/ProcessHacker/mainwnd.c
+++ b/2.x/trunk/ProcessHacker/mainwnd.c
@@ -563,6 +563,18 @@ LRESULT CALLBACK PhMainWndProc(
}
}
break;
+ case ID_PROCESS_AFFINITY:
+ {
+ PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
+
+ if (processItem)
+ {
+ PhReferenceObject(processItem);
+ PhShowProcessAffinityDialog(hWnd, processItem);
+ PhDereferenceObject(processItem);
+ }
+ }
+ break;
case ID_PROCESS_CREATEDUMPFILE:
{
PPH_PROCESS_ITEM processItem = PhpGetSelectedProcess();
diff --git a/2.x/trunk/ProcessHacker/resource.h b/2.x/trunk/ProcessHacker/resource.h
index 56e4bc944..e9555f6f9 100644
--- a/2.x/trunk/ProcessHacker/resource.h
+++ b/2.x/trunk/ProcessHacker/resource.h
@@ -47,6 +47,7 @@
#define IDD_JOBSTATISTICS 146
#define IDD_OBJEVENTPAIR 147
#define IDD_OBJSECTION 148
+#define IDD_AFFINITY 149
#define IDC_TERMINATE 1003
#define IDC_FILEICON 1005
#define IDC_FILE 1006
@@ -149,6 +150,38 @@
#define IDC_SETLOW 1096
#define IDC_SETHIGH 1097
#define IDC_SIZE_ 1098
+#define IDC_CPU0 1099
+#define IDC_CPU1 1100
+#define IDC_CPU2 1101
+#define IDC_CPU3 1102
+#define IDC_CPU4 1103
+#define IDC_CPU5 1104
+#define IDC_CPU6 1105
+#define IDC_CPU7 1106
+#define IDC_CPU8 1107
+#define IDC_CPU9 1108
+#define IDC_CPU10 1109
+#define IDC_CPU11 1110
+#define IDC_CPU12 1111
+#define IDC_CPU13 1112
+#define IDC_CPU14 1113
+#define IDC_CPU15 1114
+#define IDC_CPU16 1115
+#define IDC_CPU17 1116
+#define IDC_CPU18 1117
+#define IDC_CPU19 1118
+#define IDC_CPU20 1119
+#define IDC_CPU21 1120
+#define IDC_CPU22 1121
+#define IDC_CPU23 1122
+#define IDC_CPU24 1123
+#define IDC_CPU25 1124
+#define IDC_CPU26 1125
+#define IDC_CPU27 1126
+#define IDC_CPU28 1127
+#define IDC_CPU29 1128
+#define IDC_CPU30 1129
+#define IDC_CPU31 1130
#define ID_MAINWND_PROCESSTL 2001
#define ID_MAINWND_SERVICELV 2002
#define ID_MAINWND_NETWORKLV 2003
@@ -266,9 +299,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 147
+#define _APS_NEXT_RESOURCE_VALUE 150
#define _APS_NEXT_COMMAND_VALUE 40127
-#define _APS_NEXT_CONTROL_VALUE 1099
+#define _APS_NEXT_CONTROL_VALUE 1100
#define _APS_NEXT_SYMED_VALUE 107
#endif
#endif
diff --git a/2.x/trunk/ProcessHacker/tokprp.c b/2.x/trunk/ProcessHacker/tokprp.c
index b7af1dc58..ba15cedf5 100644
--- a/2.x/trunk/ProcessHacker/tokprp.c
+++ b/2.x/trunk/ProcessHacker/tokprp.c
@@ -830,7 +830,7 @@ INT_PTR CALLBACK PhpTokenGeneralPageProc(
{
if (NT_SUCCESS(PhGetTokenIsVirtualizationEnabled(tokenHandle, &isVirtualizationEnabled)))
{
- tokenVirtualization = isVirtualizationEnabled ? L"Yes" : L"No";
+ tokenVirtualization = isVirtualizationEnabled ? L"Enabled" : L"Disabled";
}
}
else
diff --git a/2.x/trunk/phlib/include/ntexapi.h b/2.x/trunk/phlib/include/ntexapi.h
index 0d003f6a4..b94c1e2b6 100644
--- a/2.x/trunk/phlib/include/ntexapi.h
+++ b/2.x/trunk/phlib/include/ntexapi.h
@@ -923,8 +923,35 @@ typedef struct _KUSER_SHARED_DATA
ULONG NumberOfPhysicalPages;
BOOLEAN SafeBootMode;
+ union
+ {
+ BOOLEAN TscQpcData;
+ struct
+ {
+ BOOLEAN TscQpcEnabled : 1;
+ BOOLEAN TscQpcSpareFlag : 1;
+ UCHAR TscQpcShift : 6;
+ };
+ };
+ BOOLEAN TscQpcPad[2];
- ULONG TraceLogging;
+ union
+ {
+ ULONG TraceLogging;
+ ULONG SharedDataFlags;
+ struct
+ {
+ ULONG DbgErrorPortPresent : 1;
+ ULONG DbgElevationEnabled : 1;
+ ULONG DbgVirtEnabled : 1;
+ ULONG DbgInstallerDetectEnabled : 1;
+ ULONG DbgSystemDllRelocated : 1;
+ ULONG DbgDynProcessorEnabled : 1;
+ ULONG DbgSEHValidationEnabled : 1;
+ ULONG SpareBits : 25;
+ };
+ };
+ ULONG DataFlagsPad[1];
ULONGLONG TestRetInstruction;
ULONG SystemCall;
@@ -935,11 +962,44 @@ typedef struct _KUSER_SHARED_DATA
{
volatile KSYSTEM_TIME TickCount;
volatile ULONG64 TickCountQuad;
+ ULONG ReservedTickCountOverlay[3];
};
+ ULONG TickCountPad[1];
ULONG Cookie;
+ // Entries below all invalid below Windows Vista
+
+ ULONG CookiePad[1];
+ ULONGLONG ConsoleSessionForegroundProcessId;
+
ULONG Wow64SharedInformation[MAX_WOW64_SHARED_ENTRIES];
+
+ USHORT UserModeGlobalLogger[16];
+ ULONG ImageFileExecutionOptions;
+
+ ULONG LangGenerationCount;
+
+ union
+ {
+ ULONGLONG AffinityPad; // only valid on Windows Vista
+ ULONG_PTR ActiveProcessorAffinity; // only valid on Windows Vista
+ LARGE_INTEGER Reserved5;
+ };
+ LARGE_INTEGER InterruptTimeBias;
+ LARGE_INTEGER TscQpcBias;
+
+ ULONG ActiveProcessorCount;
+ USHORT ActiveGroupCount;
+ USHORT Reserved4;
+
+ ULONG AitSamplingValue;
+ ULONG AppCompatFlag;
+ ULONGLONG SystemDllNativeRelocation;
+ ULONG SystemDllWowRelocation;
+
+ ULONG XStatePad[1];
+ XSTATE_CONFIGURATION XState;
} KUSER_SHARED_DATA, *PKUSER_SHARED_DATA;
C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountMultiplier) == 0x4);
@@ -980,7 +1040,6 @@ C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallReturn) == 0x304);
C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCallPad) == 0x308);
C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCount) == 0x320);
C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, TickCountQuad) == 0x320);
-C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, Wow64SharedInformation) == 0x334);
#ifdef _M_IX86
#define USER_SHARED_DATA ((KUSER_SHARED_DATA * const)0x7ffe0000)
diff --git a/2.x/trunk/phlib/include/ph.h b/2.x/trunk/phlib/include/ph.h
index 85a5bd442..c12362874 100644
--- a/2.x/trunk/phlib/include/ph.h
+++ b/2.x/trunk/phlib/include/ph.h
@@ -266,6 +266,11 @@ NTSTATUS PhGetProcessWsCounters(
__out PPH_PROCESS_WS_COUNTERS WsCounters
);
+NTSTATUS PhSetProcessAffinityMask(
+ __in HANDLE ProcessHandle,
+ __in ULONG_PTR AffinityMask
+ );
+
NTSTATUS PhSetProcessIoPriority(
__in HANDLE ProcessHandle,
__in ULONG IoPriority
diff --git a/2.x/trunk/phlib/native.c b/2.x/trunk/phlib/native.c
index 6b86f7e28..97e9d6275 100644
--- a/2.x/trunk/phlib/native.c
+++ b/2.x/trunk/phlib/native.c
@@ -1433,6 +1433,26 @@ NTSTATUS PhGetProcessWsCounters(
return status;
}
+/**
+ * Sets a process' affinity mask.
+ *
+ * \param ProcessHandle A handle to a process. The handle
+ * must have PROCESS_SET_INFORMATION access.
+ * \param AffinityMask The new affinity mask.
+ */
+NTSTATUS PhSetProcessAffinityMask(
+ __in HANDLE ProcessHandle,
+ __in ULONG_PTR AffinityMask
+ )
+{
+ return NtSetInformationProcess(
+ ProcessHandle,
+ ProcessAffinityMask,
+ &AffinityMask,
+ sizeof(ULONG_PTR)
+ );
+}
+
/**
* Sets a process' I/O priority.
*
diff --git a/2.x/trunk/phsvc/client.c b/2.x/trunk/phsvc/client.c
index 7de464567..1b7b9977d 100644
--- a/2.x/trunk/phsvc/client.c
+++ b/2.x/trunk/phsvc/client.c
@@ -144,6 +144,8 @@ BOOLEAN PhSvcAttachClient(
PhReferenceObject(Client);
threadContext->OldClient = threadContext->CurrentClient;
threadContext->CurrentClient = Client;
+
+ return TRUE;
}
VOID PhSvcDetachClient(