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(