diff --git a/CPUSTRES/AffinityDlg.cpp b/CPUSTRES/AffinityDlg.cpp
new file mode 100644
index 0000000..55c12f3
--- /dev/null
+++ b/CPUSTRES/AffinityDlg.cpp
@@ -0,0 +1,164 @@
+// AffinityDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+#include "AffinityDlg.h"
+#include "afxdialogex.h"
+#include "Globals.h"
+#include "Thread.h"
+
+// CAffinityDlg dialog
+
+IMPLEMENT_DYNAMIC(CAffinityDlg, CDialogEx)
+
+CAffinityDlg::CAffinityDlg(bool affinity, CThread* pThread, const CString& title, CWnd* pParent)
+ : CDialogEx(IDD_AFFINITY, pParent), m_Affinity(affinity), m_Title(title), m_pThread(pThread) {
+}
+
+CAffinityDlg::CAffinityDlg(const CString& title, CWnd* pParent) : CDialogEx(IDD_AFFINITY, pParent), m_Title(title), m_Process(true), m_Affinity(true) {
+}
+
+CAffinityDlg::~CAffinityDlg() {
+}
+
+void CAffinityDlg::DoDataExchange(CDataExchange* pDX) {
+ CDialogEx::DoDataExchange(pDX);
+ if(!m_Affinity) {
+ DDX_Radio(pDX, IDC_FIRST, m_IdealCPU);
+ }
+}
+
+BEGIN_MESSAGE_MAP(CAffinityDlg, CDialogEx)
+ ON_BN_CLICKED(IDC_SELECTALL, &CAffinityDlg::OnBnClickedSelectall)
+ ON_BN_CLICKED(IDC_UNSELECTALL, &CAffinityDlg::OnBnClickedUnselectall)
+END_MESSAGE_MAP()
+
+
+// CAffinityDlg message handlers
+
+
+BOOL CAffinityDlg::OnInitDialog() {
+
+ SetWindowText(m_Title);
+
+ CRect rc;
+ GetDlgItem(IDC_DUMMY)->GetClientRect(&rc);
+ int cpus = CGlobals::GetProcessorCount();
+
+ DWORD_PTR processAffinity, systemAffinity;
+ BOOL validAffinity = FALSE;
+
+ if(m_Affinity && m_Process)
+ validAffinity = ::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinity, &systemAffinity);
+
+ CString name;
+ int row = cpus > 32 ? 8 : 4;
+ auto font = GetFont();
+ for(int i = 0; i < cpus; i++) {
+ name.Format(L"CPU %d", i);
+ m_Buttons[i].Create(name, WS_CHILD | WS_VISIBLE | (m_Affinity ? BS_AUTOCHECKBOX : BS_AUTORADIOBUTTON | (i == 0 ? WS_GROUP : 0) | WS_TABSTOP),
+ CRect(CPoint(10 + (rc.Width() + 10) * (i % row), 20 + (rc.Height() + 10) * (i / row)), CSize(rc.Width(), rc.Height())),
+ this, IDC_FIRST + i);
+ if(m_Affinity && m_pThread == nullptr)
+ CheckDlgButton(IDC_FIRST + i, (validAffinity && processAffinity & (1i64 << i)) == 0 ? BST_UNCHECKED : BST_CHECKED);
+ m_Buttons[i].SetFont(font);
+ }
+
+ if(cpus > 16) {
+ CRect rcButton, rcWindow;
+ GetDlgItem(IDOK)->GetClientRect(&rcButton);
+ GetWindowRect(&rcWindow);
+ int sizex = row == 4 ? rcWindow.Width() : (rcWindow.Width() - rcButton.Width()) * 2 + rcButton.Width();
+ if(row > 4) {
+ int x1 = sizex / 2 - rcButton.Width() - 20;
+ int x2 = sizex / 2 + 20;
+ CRect rcButton2;
+ GetDlgItem(IDOK)->GetWindowRect(&rcButton2);
+ ScreenToClient(&rcButton2);
+ GetDlgItem(IDOK)->MoveWindow(x1, rcButton2.top, rcButton.Width(), rcButton.Height());
+ GetDlgItem(IDCANCEL)->MoveWindow(x2, rcButton2.top, rcButton.Width(), rcButton.Height());
+
+ GetDlgItem(IDC_SELECTALL)->MoveWindow(sizex - rcButton.Width() - 30, 20, rcButton.Width(), rcButton.Height());
+ GetDlgItem(IDC_UNSELECTALL)->MoveWindow(sizex - rcButton.Width() - 30, 30 + rcButton.Height(), rcButton.Width(), rcButton.Height());
+ }
+ SetWindowPos(nullptr, 0, 0, sizex, rcWindow.Height(), SWP_NOMOVE | SWP_NOZORDER);
+ }
+
+ if(!m_Affinity) {
+ GetDlgItem(IDC_SELECTALL)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_UNSELECTALL)->ShowWindow(SW_HIDE);
+ }
+
+ if(m_Affinity && m_pThread) {
+ auto affinity = m_pThread->GetAffinity();
+ int i = 0;
+ while(affinity) {
+ if(affinity & 1)
+ CheckDlgButton(IDC_FIRST + i, BST_CHECKED);
+ affinity >>= 1;
+ i++;
+ }
+ }
+ if(m_Affinity && !m_Process)
+ DisableNonProcessAffinity();
+
+ if(!m_Affinity) {
+ m_IdealCPU = m_pThread ? m_pThread->GetIdealCPU() : 0;
+ }
+ CDialogEx::OnInitDialog();
+
+ return TRUE;
+}
+
+void CAffinityDlg::DisableNonProcessAffinity() {
+ DWORD_PTR processAffinity, systemAffinity;
+ if(!::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinity, &systemAffinity))
+ return;
+
+ if(processAffinity == systemAffinity)
+ return;
+
+ // disable CPUs that are not part of the process affinity mask
+ int n = 0;
+ while(processAffinity) {
+ if((processAffinity & 1) == 0) {
+ CheckDlgButton(IDC_FIRST + n, BST_UNCHECKED);
+ m_Buttons[n].EnableWindow(FALSE);
+ }
+ processAffinity >>= 1;
+ ++n;
+ }
+}
+
+DWORD_PTR CAffinityDlg::CalcAffinity() {
+ DWORD_PTR affinity = 0;
+ for(int i = 0; i < CGlobals::GetProcessorCount(); i++)
+ if(m_Buttons[i].GetCheck() == BST_CHECKED)
+ affinity |= (DWORD_PTR)1 << i;
+ return affinity;
+}
+
+void CAffinityDlg::OnOK() {
+ UpdateData();
+
+ if(m_Affinity) {
+ auto affinity = CalcAffinity();
+ if(affinity == 0) {
+ AfxMessageBox(L"Affinity of zero is not allowed");
+ return;
+ }
+ m_SelectedAfinity = affinity;
+ }
+ EndDialog(IDOK);
+}
+
+void CAffinityDlg::OnBnClickedSelectall() {
+ for(int i = 0; i < CGlobals::GetProcessorCount(); i++)
+ CheckDlgButton(IDC_FIRST + i, BST_CHECKED);
+}
+
+void CAffinityDlg::OnBnClickedUnselectall() {
+ for(int i = 0; i < CGlobals::GetProcessorCount(); i++)
+ CheckDlgButton(IDC_FIRST + i, BST_UNCHECKED);
+}
diff --git a/CPUSTRES/AffinityDlg.h b/CPUSTRES/AffinityDlg.h
new file mode 100644
index 0000000..c70d70a
--- /dev/null
+++ b/CPUSTRES/AffinityDlg.h
@@ -0,0 +1,50 @@
+#pragma once
+
+class CThread;
+
+// CAffinityDlg dialog
+
+class CAffinityDlg : public CDialogEx
+{
+ DECLARE_DYNAMIC(CAffinityDlg)
+
+public:
+ CAffinityDlg(bool affinity, CThread* pThread, const CString& title, CWnd* pParent = nullptr);
+ CAffinityDlg(const CString& title, CWnd* pParent = nullptr);
+
+ virtual ~CAffinityDlg();
+
+// Dialog Data
+#ifdef AFX_DESIGN_TIME
+ enum { IDD = IDD_AFFINITY };
+#endif
+
+ enum { IDC_FIRST = 100 };
+
+ DWORD_PTR GetSelectedAffinity() const {
+ return m_SelectedAfinity;
+ }
+ int GetSelectedCPU() const {
+ return m_IdealCPU;
+ }
+
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ DWORD_PTR CalcAffinity();
+ void DisableNonProcessAffinity();
+
+ bool m_Affinity;
+ bool m_Process = false;
+ CString m_Title;
+ CButton m_Buttons[64];
+ CThread* m_pThread;
+ DWORD_PTR m_SelectedAfinity;
+ int m_IdealCPU;
+
+ DECLARE_MESSAGE_MAP()
+ virtual BOOL OnInitDialog();
+ void OnOK() override;
+public:
+ afx_msg void OnBnClickedSelectall();
+ afx_msg void OnBnClickedUnselectall();
+};
diff --git a/CPUSTRES/CPUSTRES.sln b/CPUSTRES/CPUSTRES.sln
new file mode 100644
index 0000000..91b0813
--- /dev/null
+++ b/CPUSTRES/CPUSTRES.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPUStressEx", "CPUStressEx.vcxproj", "{DC1EF85A-8628-457A-A805-49CCC97DF5BF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|Win32.Build.0 = Debug|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x64.ActiveCfg = Debug|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x64.Build.0 = Debug|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|Win32.ActiveCfg = Release|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|Win32.Build.0 = Release|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x64.ActiveCfg = Release|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/CPUSTRES/CPUStressEx.cpp b/CPUSTRES/CPUStressEx.cpp
new file mode 100644
index 0000000..6cd802a
--- /dev/null
+++ b/CPUSTRES/CPUStressEx.cpp
@@ -0,0 +1,123 @@
+
+// CPUStressEx.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "afxwinappex.h"
+#include "afxdialogex.h"
+#include "CPUStressEx.h"
+#include "MainFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CCPUStressExApp
+
+BEGIN_MESSAGE_MAP(CCPUStressExApp, CWinApp)
+ ON_COMMAND(ID_APP_ABOUT, &CCPUStressExApp::OnAppAbout)
+END_MESSAGE_MAP()
+
+
+// CCPUStressExApp construction
+
+CCPUStressExApp::CCPUStressExApp() {
+ // TODO: replace application ID string below with unique ID string; recommended
+ // format for string is CompanyName.ProductName.SubProduct.VersionInformation
+ SetAppID(_T("CPUStressEx.AppID.NoVersion"));
+
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+// The one and only CCPUStressExApp object
+
+CCPUStressExApp theApp;
+
+
+// CCPUStressExApp initialization
+
+BOOL CCPUStressExApp::InitInstance() {
+ int argc = 0;
+ auto argv = ::CommandLineToArgvW(::GetCommandLine(), &argc);
+
+ ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+
+ // InitCommonControlsEx() is required on Windows XP if an application
+ // manifest specifies use of ComCtl32.dll version 6 or later to enable
+ // visual styles. Otherwise, any window creation will fail.
+ INITCOMMONCONTROLSEX InitCtrls;
+ InitCtrls.dwSize = sizeof(InitCtrls);
+ // Set this to include all the common control classes you want to use
+ // in your application.
+ InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&InitCtrls);
+
+ CWinApp::InitInstance();
+
+ // To create the main window, this code creates a new frame window
+ // object and then sets it as the application's main window object
+ CMainFrame* pFrame = new CMainFrame;
+ if (!pFrame)
+ return FALSE;
+
+ m_pMainWnd = pFrame;
+ // create and load the frame with its resources
+ pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW, NULL, NULL);
+ pFrame->SetWindowPos(nullptr, 0, 0, 640, 400, SWP_NOMOVE | SWP_NOZORDER | SWP_NOREPOSITION);
+
+ // The one and only window has been initialized, so show and update it
+ pFrame->ShowWindow(SW_SHOW);
+ pFrame->UpdateWindow();
+
+ return TRUE;
+}
+
+int CCPUStressExApp::ExitInstance() {
+ //TODO: handle additional resources you may have added
+ return CWinApp::ExitInstance();
+}
+
+// CCPUStressExApp message handlers
+
+
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialogEx {
+public:
+ CAboutDlg();
+
+ // Dialog Data
+#ifdef AFX_DESIGN_TIME
+ enum { IDD = IDD_ABOUTBOX };
+#endif
+
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+// Implementation
+protected:
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX) {
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX) {
+ CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
+END_MESSAGE_MAP()
+
+// App command to run the dialog
+void CCPUStressExApp::OnAppAbout() {
+ CAboutDlg aboutDlg;
+ aboutDlg.DoModal();
+}
+
+// CCPUStressExApp message handlers
+
+
+
diff --git a/CPUSTRES/CPUStressEx.h b/CPUSTRES/CPUStressEx.h
new file mode 100644
index 0000000..f1e215e
--- /dev/null
+++ b/CPUSTRES/CPUStressEx.h
@@ -0,0 +1,35 @@
+
+// CPUStressEx.h : main header file for the CPUStressEx application
+//
+#pragma once
+
+#ifndef __AFXWIN_H__
+ #error "include 'stdafx.h' before including this file for PCH"
+#endif
+
+#include "resource.h" // main symbols
+
+
+// CCPUStressExApp:
+// See CPUStressEx.cpp for the implementation of this class
+//
+
+class CCPUStressExApp : public CWinApp
+{
+public:
+ CCPUStressExApp();
+
+
+// Overrides
+public:
+ virtual BOOL InitInstance();
+ virtual int ExitInstance();
+
+// Implementation
+
+public:
+ afx_msg void OnAppAbout();
+ DECLARE_MESSAGE_MAP()
+};
+
+extern CCPUStressExApp theApp;
diff --git a/CPUSTRES/CPUStressEx.rc b/CPUSTRES/CPUStressEx.rc
new file mode 100644
index 0000000..dbf0cb0
--- /dev/null
+++ b/CPUSTRES/CPUStressEx.rc
@@ -0,0 +1,589 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+#include "verrsrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#ifndef APSTUDIO_INVOKED\r\n"
+ "#include ""targetver.h""\r\n"
+ "#endif\r\n"
+ "#include ""afxres.h""\r\n"
+ "#include ""verrsrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#include ""res\\CPUStressEx.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON "res\\CPUStressEx.ico"
+
+IDI_KILL ICON "Icons\\gear_delete.ico"
+
+IDI_PAUSE ICON "Icons\\gear_pause.ico"
+
+IDI_PLAY ICON "Icons\\gear_run.ico"
+
+IDI_CREATE ICON "Icons\\gear_add.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MAINFRAME MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "E&xit", ID_APP_EXIT
+ END
+ POPUP "&Process"
+ BEGIN
+ POPUP "Priority &Class"
+ BEGIN
+ MENUITEM "&Idle", ID_PRIORITYCLASS_IDLE
+ MENUITEM "&Below Normal", ID_PRIORITYCLASS_BELOWNORMAL
+ MENUITEM "&Normal", ID_PRIORITYCLASS_NORMAL
+ MENUITEM "&Above Normal", ID_PRIORITYCLASS_ABOVENORMAL
+ MENUITEM "&High", ID_PRIORITYCLASS_HIGH
+ MENUITEM "&Realtime", ID_PRIORITYCLASS_REALTIME
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "A&ffinity...", ID_PROCESS_AFFINITY
+ MENUITEM SEPARATOR
+ MENUITEM "Create &Thread", ID_PROCESS_CREATETHREAD
+ MENUITEM "Create &4 Threads", ID_PROCESS_CREATE4THREADS
+ MENUITEM SEPARATOR
+ MENUITEM "&Refresh\tF5", ID_PROCESS_REFRESH
+ END
+ POPUP "&Thread"
+ BEGIN
+ MENUITEM "&Activate", ID_THREAD_ACTIVATE
+ MENUITEM "&Deactivate", ID_THREAD_DEACTIVATE
+ MENUITEM SEPARATOR
+ POPUP "Activity &Level"
+ BEGIN
+ MENUITEM "&Low (25%)", ID_ACTIVITYLEVEL_LOW
+ MENUITEM "&Medium (50%)", ID_ACTIVITYLEVEL_MEDIUM
+ MENUITEM "&Busy (75%)", ID_ACTIVITYLEVEL_BUSY
+ MENUITEM "&Maximum (100%)", ID_ACTIVITYLEVEL_MAXIMUM
+ END
+ POPUP "&Priority"
+ BEGIN
+ MENUITEM "&Idle (-Sat)", ID_PRIORITY_IDLE
+ MENUITEM "&Lowest (-2)", ID_PRIORITY_LOWEST
+ MENUITEM "&Below Normal (-1)", ID_PRIORITY_BELOWNORMAL
+ MENUITEM "&Normal (0)", ID_PRIORITY_NORMAL
+ MENUITEM "&Above Normal (+1)", ID_PRIORITY_ABOVENORMAL
+ MENUITEM "&Highest (+2)", ID_PRIORITY_HIGHEST
+ MENUITEM "&Time Critical (+Sat)", ID_PRIORITY_TIMECRITICAL
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "A&ffinity...", ID_THREAD_AFFINITY
+ MENUITEM "&Ideal CPU...", ID_THREAD_IDEALCPU
+ MENUITEM SEPARATOR
+ MENUITEM "&Kill", ID_THREAD_KILL
+ END
+ POPUP "&Options"
+ BEGIN
+ MENUITEM "&Always on Top", ID_OPTIONS_ALWAYSONTOP
+ MENUITEM "Auto Refresh Thread Indices", ID_OPTIONS_AUTOREFRESHTHREADINDICES, CHECKED
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About CPUSTRES 2.0...", ID_APP_ABOUT
+ END
+END
+
+IDR_CONTEXTMENU MENU
+BEGIN
+ POPUP "thread"
+ BEGIN
+ MENUITEM "&Activate", ID_THREAD_ACTIVATE
+ MENUITEM "&Deactivate", ID_THREAD_DEACTIVATE
+ MENUITEM SEPARATOR
+ POPUP "Activity &Level"
+ BEGIN
+ MENUITEM "&Low (25%)", ID_ACTIVITYLEVEL_LOW
+ MENUITEM "&Medium (50%)", ID_ACTIVITYLEVEL_MEDIUM
+ MENUITEM "&Busy (75%)", ID_ACTIVITYLEVEL_BUSY
+ MENUITEM "&Maximum (100%)", ID_ACTIVITYLEVEL_MAXIMUM
+ END
+ POPUP "&Priority"
+ BEGIN
+ MENUITEM "&Idle (-Sat)", ID_PRIORITY_IDLE
+ MENUITEM "&Lowest (-2)", ID_PRIORITY_LOWEST
+ MENUITEM "&Below Normal (-1)", ID_PRIORITY_BELOWNORMAL
+ MENUITEM "&Normal (0)", ID_PRIORITY_NORMAL
+ MENUITEM "&Above Normal (+1)", ID_PRIORITY_ABOVENORMAL
+ MENUITEM "&Highest (+2)", ID_PRIORITY_HIGHEST
+ MENUITEM "&Time Critical (+Sat)", ID_PRIORITY_TIMECRITICAL
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "A&ffinity...", ID_THREAD_AFFINITY
+ MENUITEM "&Ideal CPU...", ID_THREAD_IDEALCPU
+ MENUITEM SEPARATOR
+ MENUITEM "&Kill", ID_THREAD_KILL
+ END
+ POPUP "process"
+ BEGIN
+ POPUP "Priority &Class"
+ BEGIN
+ MENUITEM "&Idle", ID_PRIORITYCLASS_IDLE
+ MENUITEM "&Below Normal", ID_PRIORITYCLASS_BELOWNORMAL
+ MENUITEM "&Normal", ID_PRIORITYCLASS_NORMAL
+ MENUITEM "&Above Normal", ID_PRIORITYCLASS_ABOVENORMAL
+ MENUITEM "&High", ID_PRIORITYCLASS_HIGH
+ MENUITEM "&Realtime", ID_PRIORITYCLASS_REALTIME
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Process A&ffinity...", ID_PROCESS_AFFINITY
+ MENUITEM SEPARATOR
+ MENUITEM "Create &Thread", ID_PROCESS_CREATETHREAD
+ MENUITEM "Create &4 Threads", ID_PROCESS_CREATE4THREADS
+ END
+ POPUP "activity"
+ BEGIN
+ MENUITEM "&Low (25%)", ID_ACTIVITYLEVEL_LOW
+ MENUITEM "&Medium (50%)", ID_ACTIVITYLEVEL_MEDIUM
+ MENUITEM "&Busy (75%)", ID_ACTIVITYLEVEL_BUSY
+ MENUITEM "&Maximum (100%)", ID_ACTIVITYLEVEL_MAXIMUM
+ END
+ POPUP "priority"
+ BEGIN
+ MENUITEM "&Idle (-Sat)", ID_PRIORITY_IDLE
+ MENUITEM "&Lowest (-2)", ID_PRIORITY_LOWEST
+ MENUITEM "&Below Normal (-1)", ID_PRIORITY_BELOWNORMAL
+ MENUITEM "&Normal (0)", ID_PRIORITY_NORMAL
+ MENUITEM "&Above Normal (+1)", ID_PRIORITY_ABOVENORMAL
+ MENUITEM "&Highest (+2)", ID_PRIORITY_HIGHEST
+ MENUITEM "&Time Critical (+Sat)", ID_PRIORITY_TIMECRITICAL
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_MAINFRAME ACCELERATORS
+BEGIN
+ "C", ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, ID_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
+ "X", ID_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
+ "V", ID_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_EDIT_PASTE, VIRTKEY, SHIFT, NOINVERT
+ VK_BACK, ID_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
+ "Z", ID_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
+ VK_F6, ID_NEXT_PANE, VIRTKEY, NOINVERT
+ VK_F6, ID_PREV_PANE, VIRTKEY, SHIFT, NOINVERT
+ VK_F5, ID_PROCESS_REFRESH, VIRTKEY, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 263, 84
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About CPUStressEx"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ ICON IDR_MAINFRAME,IDC_STATIC,14,14,20,20
+ LTEXT "CPUSTRES v2.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 2016 Pavel Yosifovich",IDC_STATIC,42,26,170,8
+ DEFPUSHBUTTON "OK",IDOK,106,63,50,14,WS_GROUP
+ CONTROL "Sysinternals - www.sysinternals.com",IDC_LINK,"MfcLink",WS_TABSTOP,39,38,182,14
+END
+
+IDR_MAINFRAME DIALOGEX 0, 0, 438, 30
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",ID_THREAD_ACTIVATE,"MfcButton",WS_TABSTOP,0,0,29,24
+ CONTROL "",ID_THREAD_DEACTIVATE,"MfcButton",WS_TABSTOP,31,0,29,24
+ CONTROL "",ID_PROCESS_CREATETHREAD,"MfcButton",WS_TABSTOP,77,0,29,24
+ CONTROL "",ID_THREAD_KILL,"MfcButton",WS_TABSTOP,111,0,29,24
+ LTEXT "Process Affinity:",IDC_PROCESS_AFFINITY,148,1,289,8
+ LTEXT "Process Priority Class:",IDC_PRIORITYCLASS,148,16,167,8
+END
+
+IDD_AFFINITY DIALOGEX 0, 0, 239, 165
+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,61,144,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,127,144,50,14
+ CONTROL "CPU 0",IDC_DUMMY,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,7,7,35,10
+ PUSHBUTTON "Select All",IDC_SELECTALL,182,7,50,14
+ PUSHBUTTON "Unselect All",IDC_UNSELECTALL,182,28,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,0,0,0
+ PRODUCTVERSION 2,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Windows Internals Book Tools"
+ VALUE "FileDescription", "CPU Stress"
+ VALUE "FileVersion", "2.0.0.0"
+ VALUE "InternalName", "CPUSTRES"
+ VALUE "LegalCopyright", "Copyright (C) 2016 by Pavel Yosifovich"
+ VALUE "OriginalFilename", "CPUSTRES"
+ VALUE "ProductName", "Sysinternals CPUSTRES"
+ VALUE "ProductVersion", "2.0.0.0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 256
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 77
+ END
+
+ IDR_MAINFRAME, DIALOG
+ BEGIN
+ RIGHTMARGIN, 332
+ BOTTOMMARGIN, 24
+ END
+
+ IDD_AFFINITY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 232
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 158
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDR_MAINFRAME AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_AFFINITY AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_ABOUTBOX AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDR_MAINFRAME DLGINIT
+BEGIN
+ ID_THREAD_ACTIVATE, 0x37c, 471, 0
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x535f, 0x7974, 0x656c, 0x353e,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7453, 0x6c79, 0x3e65,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x415f, 0x7475, 0x736f, 0x7a69,
+0x3e65, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x415f, 0x7475, 0x736f, 0x7a69, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x413e, 0x7463, 0x7669, 0x7461,
+0x2065, 0x6854, 0x6572, 0x6461, 0x3c73, 0x4d2f, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4243, 0x7475,
+0x6f74, 0x5f6e, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x463e,
+0x4c41, 0x4553, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7546,
+0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x3c3e, 0x464d, 0x4243, 0x7475,
+0x6f74, 0x5f6e, 0x7543, 0x7372, 0x726f, 0x7954, 0x6570, 0x313e, 0x3c31,
+0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x435f, 0x7275, 0x6f73, 0x5472,
+0x7079, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d,
+0x6567, 0x7954, 0x6570, 0x393e, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74,
+0x5f6e, 0x6d49, 0x6761, 0x5465, 0x7079, 0x3e65, 0x4d3c, 0x4346, 0x7542,
+0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x4449, 0x333e, 0x3231, 0x2f3c,
+0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4965, 0x3e44,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x493e,
+0x4944, 0x505f, 0x414c, 0x3c59, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x495f, 0x616d, 0x6567, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x6d49, 0x6761, 0x4f65, 0x546e, 0x706f, 0x463e, 0x4c41, 0x4553, 0x2f3c,
+0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x546e,
+0x706f, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761,
+0x4f65, 0x526e, 0x6769, 0x7468, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d,
+0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x526e, 0x6769,
+0x7468, "\076"
+ ID_THREAD_DEACTIVATE, 0x37c, 474, 0
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x535f, 0x7974, 0x656c, 0x353e,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7453, 0x6c79, 0x3e65,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x415f, 0x7475, 0x736f, 0x7a69,
+0x3e65, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x415f, 0x7475, 0x736f, 0x7a69, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x443e, 0x6165, 0x7463, 0x7669,
+0x7461, 0x2065, 0x6854, 0x6572, 0x6461, 0x3c73, 0x4d2f, 0x4346, 0x7542,
+0x7474, 0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4243,
+0x7475, 0x6f74, 0x5f6e, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f,
+0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x3c3e, 0x464d, 0x4243,
+0x7475, 0x6f74, 0x5f6e, 0x7543, 0x7372, 0x726f, 0x7954, 0x6570, 0x313e,
+0x3c31, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x435f, 0x7275, 0x6f73,
+0x5472, 0x7079, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f,
+0x616d, 0x6567, 0x7954, 0x6570, 0x393e, 0x2f3c, 0x464d, 0x4243, 0x7475,
+0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x5465, 0x7079, 0x3e65, 0x4d3c, 0x4346,
+0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x4449, 0x333e, 0x3431,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4965,
+0x3e44, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567,
+0x493e, 0x4944, 0x505f, 0x5541, 0x4553, 0x2f3c, 0x464d, 0x4243, 0x7475,
+0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x495f, 0x616d, 0x6567, 0x6e4f, 0x6f54, 0x3e70, 0x4146, 0x534c,
+0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567,
+0x6e4f, 0x6f54, 0x3e70, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f,
+0x616d, 0x6567, 0x6e4f, 0x6952, 0x6867, 0x3e74, 0x4146, 0x534c, 0x3c45,
+0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x6e4f,
+0x6952, 0x6867, 0x3e74,
+ ID_PROCESS_CREATETHREAD, 0x37c, 471, 0
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x535f, 0x7974, 0x656c, 0x353e,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7453, 0x6c79, 0x3e65,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x415f, 0x7475, 0x736f, 0x7a69,
+0x3e65, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x415f, 0x7475, 0x736f, 0x7a69, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x433e, 0x6572, 0x7461, 0x2065,
+0x6854, 0x6572, 0x6461, 0x3c73, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74,
+0x5f6e, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x463e, 0x4c41,
+0x4553, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7546, 0x6c6c,
+0x6554, 0x7478, 0x6f54, 0x6c6f, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74,
+0x5f6e, 0x7543, 0x7372, 0x726f, 0x7954, 0x6570, 0x313e, 0x3c31, 0x4d2f,
+0x4346, 0x7542, 0x7474, 0x6e6f, 0x435f, 0x7275, 0x6f73, 0x5472, 0x7079,
+0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567,
+0x7954, 0x6570, 0x393e, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x6d49, 0x6761, 0x5465, 0x7079, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x495f, 0x616d, 0x6567, 0x4449, 0x333e, 0x3631, 0x2f3c, 0x464d,
+0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4965, 0x3e44, 0x4d3c,
+0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x493e, 0x4944,
+0x435f, 0x4552, 0x5441, 0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x495f, 0x616d, 0x6567, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x6d49, 0x6761, 0x4f65, 0x546e, 0x706f, 0x463e, 0x4c41, 0x4553, 0x2f3c,
+0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x546e,
+0x706f, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761,
+0x4f65, 0x526e, 0x6769, 0x7468, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d,
+0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x526e, 0x6769,
+0x7468, "\076"
+ ID_THREAD_KILL, 0x37c, 467, 0
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x535f, 0x7974, 0x656c, 0x353e,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7453, 0x6c79, 0x3e65,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x415f, 0x7475, 0x736f, 0x7a69,
+0x3e65, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x415f, 0x7475, 0x736f, 0x7a69, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474,
+0x6e6f, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x4b3e, 0x6c69, 0x206c, 0x6854,
+0x6572, 0x6461, 0x3c73, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x545f,
+0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x463e, 0x4c41, 0x4553,
+0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x7546, 0x6c6c, 0x6554,
+0x7478, 0x6f54, 0x6c6f, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e,
+0x7543, 0x7372, 0x726f, 0x7954, 0x6570, 0x313e, 0x3c31, 0x4d2f, 0x4346,
+0x7542, 0x7474, 0x6e6f, 0x435f, 0x7275, 0x6f73, 0x5472, 0x7079, 0x3e65,
+0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x7954,
+0x6570, 0x393e, 0x2f3c, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49,
+0x6761, 0x5465, 0x7079, 0x3e65, 0x4d3c, 0x4346, 0x7542, 0x7474, 0x6e6f,
+0x495f, 0x616d, 0x6567, 0x4449, 0x333e, 0x3331, 0x2f3c, 0x464d, 0x4243,
+0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4965, 0x3e44, 0x4d3c, 0x4346,
+0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d, 0x6567, 0x493e, 0x4944, 0x4b5f,
+0x4c49, 0x3c4c, 0x4d2f, 0x4346, 0x7542, 0x7474, 0x6e6f, 0x495f, 0x616d,
+0x6567, 0x3c3e, 0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761,
+0x4f65, 0x546e, 0x706f, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x4243,
+0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x546e, 0x706f, 0x3c3e,
+0x464d, 0x4243, 0x7475, 0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x526e,
+0x6769, 0x7468, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x4243, 0x7475,
+0x6f74, 0x5f6e, 0x6d49, 0x6761, 0x4f65, 0x526e, 0x6769, 0x7468, "\076"
+ 0
+END
+
+IDD_ABOUTBOX DLGINIT
+BEGIN
+ IDC_LINK, 0x37c, 184, 0
+0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x3a70,
+0x2f2f, 0x7777, 0x2e77, 0x7973, 0x6973, 0x746e, 0x7265, 0x616e, 0x736c,
+0x632e, 0x6d6f, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 0x3e6c,
+0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665, 0x7869,
+0x3c3e, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x7250, 0x6665,
+0x7869, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974,
+0x3e70, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x6f54, 0x6c6f, 0x6974,
+0x3e70, 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, 0x546c, 0x7865,
+0x5474, 0x6f6f, 0x746c, 0x7069, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d,
+0x4c43, 0x6e69, 0x5f6b, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f,
+0x6974, 0x3e70,
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDR_MAINFRAME "CPU Stress (PID: $)"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDS_APP_TITLE "CPU Stress"
+ AFX_IDS_IDLEMESSAGE "Ready"
+END
+
+STRINGTABLE
+BEGIN
+ ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
+ ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
+END
+
+STRINGTABLE
+BEGIN
+ ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
+ ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
+END
+
+STRINGTABLE
+BEGIN
+ ID_EDIT_CLEAR "Erase the selection\nErase"
+ ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
+ ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
+ ID_EDIT_UNDO "Undo the last action\nUndo"
+ ID_EDIT_REDO "Redo the previously undone action\nRedo"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDS_SCSIZE "Change the window size"
+ AFX_IDS_SCMOVE "Change the window position"
+ AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
+ AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
+ AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
+ AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
+ AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents"
+END
+
+STRINGTABLE
+BEGIN
+ AFX_IDS_SCRESTORE "Restore the window to normal size"
+ AFX_IDS_SCTASKLIST "Activate Task List"
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+#include "res\CPUStressEx.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/CPUSTRES/CPUStressEx.vcxproj b/CPUSTRES/CPUStressEx.vcxproj
new file mode 100644
index 0000000..a5ad904
--- /dev/null
+++ b/CPUSTRES/CPUStressEx.vcxproj
@@ -0,0 +1,240 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}
+ CPUStressEx
+ 8.1
+ MFCProj
+ CPUSTRES
+
+
+
+ Application
+ true
+ v140_xp
+ Unicode
+ Dynamic
+
+
+ Application
+ false
+ v140_xp
+ true
+ Unicode
+ Static
+
+
+ Application
+ true
+ v120_xp
+ Unicode
+ Dynamic
+
+
+ Application
+ false
+ v120_xp
+ true
+ Unicode
+ Static
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+ false
+ true
+
+
+ false
+ true
+
+
+
+ Use
+ Level3
+ Disabled
+ WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+ false
+ true
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ _DEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+
+
+ Use
+ Level3
+ Disabled
+ _WINDOWS;_DEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+
+
+ false
+ true
+ _DEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ _DEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+
+
+ false
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+ Use
+ MaxSpeed
+ true
+ true
+ _WINDOWS;NDEBUG;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+
+
+ false
+ true
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ 0x0409
+ NDEBUG;%(PreprocessorDefinitions)
+ $(IntDir);%(AdditionalIncludeDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CPUSTRES/CPUStressEx.vcxproj.filters b/CPUSTRES/CPUStressEx.vcxproj.filters
new file mode 100644
index 0000000..fc4164b
--- /dev/null
+++ b/CPUSTRES/CPUStressEx.vcxproj.filters
@@ -0,0 +1,103 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Resource Files
+
+
+
+
+ Resource Files
+
+
+
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+ Resource Files
+
+
+
\ No newline at end of file
diff --git a/CPUSTRES/ChildView.cpp b/CPUSTRES/ChildView.cpp
new file mode 100644
index 0000000..7f31a6f
--- /dev/null
+++ b/CPUSTRES/ChildView.cpp
@@ -0,0 +1,358 @@
+
+// ChildView.cpp : implementation of the CChildView class
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+#include "ChildView.h"
+#include "AffinityDlg.h"
+#include "Globals.h"
+
+using namespace std;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CChildView
+
+CChildView::CChildView() : m_List(m_Threads) {}
+
+CChildView::~CChildView() {}
+
+BEGIN_MESSAGE_MAP(CChildView, CWnd)
+ ON_WM_PAINT()
+ ON_WM_CREATE()
+ ON_WM_SIZE()
+ ON_COMMAND(ID_THREAD_ACTIVATE, &CChildView::OnThreadActivate)
+ ON_UPDATE_COMMAND_UI(ID_THREAD_ACTIVATE, &CChildView::OnUpdateThreadActivate)
+ ON_WM_ERASEBKGND()
+ ON_COMMAND(ID_THREAD_DEACTIVATE, &CChildView::OnThreadDeactivate)
+ ON_UPDATE_COMMAND_UI(ID_THREAD_DEACTIVATE, &CChildView::OnUpdateThreadDeactivate)
+
+ ON_COMMAND_RANGE(ID_ACTIVITYLEVEL_LOW, ID_ACTIVITYLEVEL_MAXIMUM, OnChangeThreadActivity)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_ACTIVITYLEVEL_LOW, ID_ACTIVITYLEVEL_MAXIMUM, OnUpdateChangeThreadActivity)
+
+ ON_COMMAND(ID_PROCESS_CREATETHREAD, &CChildView::OnProcessCreatethread)
+ ON_UPDATE_COMMAND_UI(ID_PROCESS_CREATETHREAD, &CChildView::OnUpdateProcessCreatethread)
+ ON_COMMAND(ID_PROCESS_CREATE4THREADS, &CChildView::OnProcessCreate4threads)
+ ON_UPDATE_COMMAND_UI(ID_PROCESS_CREATE4THREADS, &CChildView::OnUpdateProcessCreate4threads)
+ ON_COMMAND_RANGE(ID_PRIORITY_IDLE, ID_PRIORITY_TIMECRITICAL, OnChangeThreadPriority)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_PRIORITY_IDLE, ID_PRIORITY_TIMECRITICAL, OnUpdateChangeThreadPriority)
+
+ ON_NOTIFY(NM_RCLICK, IDC_LIST, OnRClickList)
+ ON_COMMAND(ID_THREAD_AFFINITY, &CChildView::OnThreadAffinity)
+ ON_UPDATE_COMMAND_UI(ID_THREAD_AFFINITY, OnUpdateChangeThreadPriority)
+
+ ON_COMMAND(ID_THREAD_IDEALCPU, &CChildView::OnThreadIdealcpu)
+ ON_UPDATE_COMMAND_UI(ID_THREAD_IDEALCPU, OnUpdateChangeThreadPriority)
+ ON_COMMAND(ID_THREAD_KILL, &CChildView::OnThreadKill)
+ ON_UPDATE_COMMAND_UI(ID_THREAD_KILL, OnUpdateChangeThreadPriority)
+ ON_WM_TIMER()
+ ON_COMMAND(ID_PROCESS_REFRESH, &CChildView::OnProcessRefresh)
+ ON_COMMAND(ID_OPTIONS_AUTOREFRESHTHREADINDICES, &CChildView::OnOptionsAutorefreshthreadindices)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_AUTOREFRESHTHREADINDICES, &CChildView::OnUpdateOptionsAutorefreshthreadindices)
+END_MESSAGE_MAP()
+
+void CChildView::DoDataExchange(CDataExchange* pDX) {
+ CWnd::DoDataExchange(pDX);
+
+ DDX_Control(pDX, IDC_LIST, m_List);
+}
+
+// CChildView message handlers
+
+BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) {
+ if (!CWnd::PreCreateWindow(cs))
+ return FALSE;
+
+ cs.dwExStyle |= WS_EX_CLIENTEDGE;
+ cs.style &= ~WS_BORDER;
+ cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,
+ ::LoadCursor(NULL, IDC_ARROW), reinterpret_cast(COLOR_WINDOW + 1), NULL);
+
+ return TRUE;
+}
+
+void CChildView::OnRClickList(NMHDR*, LRESULT*) {
+ CPoint pt;
+ ::GetCursorPos(&pt);
+ CPoint screen(pt);
+ m_List.ScreenToClient(&pt);
+ int item = m_List.HitTest(pt);
+ CMenu menu;
+ menu.LoadMenu(IDR_CONTEXTMENU);
+ menu.GetSubMenu(item < 0 ? 1 : 0)->TrackPopupMenu(TPM_RIGHTBUTTON, screen.x, screen.y, AfxGetMainWnd());
+}
+
+void CChildView::OnPaint() {
+ CPaintDC dc(this);
+}
+
+int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) {
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ m_List.Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER,
+ CRect(), this, IDC_LIST);
+ m_List.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_AUTOSIZECOLUMNS | LVS_EX_FLATSB);
+
+ m_List.InsertColumn(0, L"#", 0, 60);
+ m_List.InsertColumn(1, L"ID", LVCFMT_LEFT, 60);
+ m_List.InsertColumn(2, L"Active?", LVCFMT_CENTER, 80);
+ m_List.InsertColumn(3, L"Activity", LVCFMT_LEFT, 80);
+ m_List.InsertColumn(4, L"Priority", LVCFMT_LEFT, 100);
+ m_List.InsertColumn(5, L"Ideal CPU", LVCFMT_CENTER, 80);
+ m_List.InsertColumn(6, L"Affinity", LVCFMT_RIGHT, 120);
+
+ CreateThreads();
+
+ SetTimer(1, 10000, nullptr);
+
+ return 0;
+}
+
+void CChildView::CreateThreads() {
+ for (int i = 0; i < 4; i++) {
+ auto thread = CreateThread();
+ if (i == 0)
+ thread->Resume();
+ AddThread(thread);
+ }
+ UpdateThreadProcessIndices();
+}
+
+void CChildView::AddThread(unique_ptr& thread) {
+ CString number;
+ number.Format(L"%d", m_List.GetItemCount() + 1);
+ int n = m_List.InsertItem(m_List.GetItemCount(), number);
+ number.Format(L"%d", thread->GetThreadId());
+ m_List.SetItemText(n, 1, number);
+ UpdateThread(n, thread.get());
+
+ m_Threads.push_back(move(thread));
+}
+
+void CChildView::UpdateThread(int n, const CThread* thread) {
+ if (thread == nullptr)
+ thread = reinterpret_cast(m_List.GetItemData(n));
+ CString str;
+ m_List.SetItemText(n, 2, thread->IsActive() ? L"Yes" : L"");
+ m_List.SetItemText(n, 3, ActivityLevelToString(thread->GetActivityLevel()));
+ m_List.SetItemText(n, 4, ThreadPriorityToString(thread->GetPriority()));
+ str.Format(L"%d", thread->GetIdealCPU());
+ m_List.SetItemText(n, 5, str);
+ WCHAR buffer[65];
+ _ui64tow_s(thread->GetAffinity(), buffer, 65, 2);
+ m_List.SetItemText(n, 6, buffer);
+
+ m_List.SetItemData(n, reinterpret_cast(thread));
+}
+
+PCWSTR CChildView::ActivityLevelToString(ActivityLevel level) {
+ static const PCWSTR Levels[] = { L"Low", L"Medium", L"Busy", L"Maximum" };
+ return Levels[(int)level - 1];
+}
+
+PCWSTR CChildView::ThreadPriorityToString(int priority) {
+ static const PCWSTR Levels[] = {
+ L"Idle", L"Lowest", L"Below Normal", L"Normal", L"Above Normal", L"Highest", L"Time Critical"
+ };
+ return Levels[3 + (::abs(priority) == 15 ? priority - 12 * priority / 15 : priority)];
+}
+
+void CChildView::UpdateThreadProcessIndices() {
+ auto threads = CGlobals::EnumerateThreads(::GetCurrentProcessId());
+ if (m_CurrentThreadIds == threads)
+ return;
+
+ m_CurrentThreadIds = threads;
+
+ int i = 0;
+ CString text;
+ for (auto tid : threads) {
+ int j = 0;
+ for (auto& thread : m_Threads) {
+ if (thread->GetThreadId() == tid) {
+ thread->SetProcessIndex(i);
+ text.Format(L"%d (%d)", j + 1, i);
+ m_List.SetItemText(j, 0, text);
+ break;
+ }
+ j++;
+ }
+ i++;
+ }
+}
+
+unique_ptr CChildView::CreateThread() {
+ auto thread = make_unique();
+ return thread;
+}
+
+void CChildView::OnSize(UINT nType, int cx, int cy) {
+ CWnd::OnSize(nType, cx, cy);
+
+ m_List.MoveWindow(0, 0, cx, cy);
+}
+
+
+vector> CChildView::GetSelectedThreads() const {
+ vector> selectedThreads;
+ for (auto pos = m_List.GetFirstSelectedItemPosition(); pos; ) {
+ int n = m_List.GetNextSelectedItem(pos);
+ auto data = m_List.GetItemData(n);
+
+ selectedThreads.push_back(make_pair(reinterpret_cast(data), n));
+ }
+ return selectedThreads;
+}
+
+void CChildView::OnThreadActivate() {
+ for (auto& item : GetSelectedThreads()) {
+ item.first->Resume();
+ UpdateThread(item.second, item.first);
+ }
+}
+
+
+void CChildView::OnUpdateThreadActivate(CCmdUI *pCmdUI) {
+ pCmdUI->Enable(m_List.GetSelectedCount() > 0);
+}
+
+
+BOOL CChildView::OnEraseBkgnd(CDC* pDC) {
+ return TRUE;
+}
+
+
+void CChildView::OnThreadDeactivate() {
+ for (auto& item : GetSelectedThreads()) {
+ item.first->Suspend();
+ UpdateThread(item.second, item.first);
+ }
+}
+
+void CChildView::OnUpdateThreadDeactivate(CCmdUI *pCmdUI) {
+ pCmdUI->Enable(m_List.GetSelectedCount() > 0);
+}
+
+void CChildView::OnChangeThreadActivity(UINT id) {
+ auto level = (ActivityLevel)(id - ID_ACTIVITYLEVEL_LOW + 1);
+
+ for (auto& item : GetSelectedThreads()) {
+ item.first->SetActivityLevel(level);
+ UpdateThread(item.second, item.first);
+ }
+}
+
+void CChildView::OnUpdateChangeThreadActivity(CCmdUI* pCmdUI) {
+ pCmdUI->Enable(m_List.GetSelectedCount() > 0);
+}
+
+
+void CChildView::OnProcessCreatethread() {
+ AddThread(CreateThread());
+ UpdateThreadProcessIndices();
+}
+
+
+void CChildView::OnUpdateProcessCreatethread(CCmdUI *pCmdUI) {
+ pCmdUI->Enable(m_Threads.size() < 64);
+}
+
+
+void CChildView::OnProcessCreate4threads() {
+ for (int i = 0; i < 4; i++) {
+ AddThread(CreateThread());
+ }
+ UpdateThreadProcessIndices();
+}
+
+
+void CChildView::OnUpdateProcessCreate4threads(CCmdUI *pCmdUI) {
+ pCmdUI->Enable(m_Threads.size() < 60);
+}
+
+void CChildView::OnChangeThreadPriority(UINT id) {
+ for (auto& item : GetSelectedThreads()) {
+ item.first->SetPriority(IndexToPriority(id - ID_PRIORITY_IDLE));
+ UpdateThread(item.second, item.first);
+ }
+}
+void CChildView::OnUpdateChangeThreadPriority(CCmdUI* pCmdUI) {
+ pCmdUI->Enable(m_List.GetFirstSelectedItemPosition() != nullptr);
+}
+
+int CChildView::IndexToPriority(int index) {
+ static int priorities[] = {
+ THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
+ THREAD_PRIORITY_NORMAL,
+ THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL
+ };
+ return priorities[index];
+}
+
+void CChildView::OnThreadAffinity() {
+ auto threads = GetSelectedThreads();
+ CAffinityDlg dlg(true, threads.size() == 1 ? threads[0].first : nullptr, L"Select CPU Affinity");
+ if (dlg.DoModal() == IDOK) {
+ for (auto& item : GetSelectedThreads()) {
+ item.first->SetAfinity(dlg.GetSelectedAffinity());
+ UpdateThread(item.second, item.first);
+ }
+ }
+}
+
+void CChildView::OnThreadIdealcpu() {
+ auto threads = GetSelectedThreads();
+ CAffinityDlg dlg(false, threads.size() == 1 ? threads[0].first : nullptr, L"Select Ideal CPU");
+ if (dlg.DoModal() == IDOK) {
+ for (auto& item : GetSelectedThreads()) {
+ item.first->SetIdealCPU(dlg.GetSelectedCPU());
+ UpdateThread(item.second, item.first);
+ }
+ }
+}
+
+void CChildView::OnThreadKill() {
+ auto threads = GetSelectedThreads();
+ CString text;
+ text.Format(L"Terminate %d thread(s)?", threads.size());
+ if (AfxMessageBox(text, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDNO)
+ return;
+
+ int offset = 0;
+ for (size_t i = 0; i < threads.size(); i++) {
+ auto& item = threads[i];
+ item.first->Terminate();
+ int index = item.second;
+ m_List.DeleteItem(index - offset);
+ m_Threads.erase(m_Threads.begin() + (index - offset));
+ offset++;
+ }
+ UpdateThreadProcessIndices();
+}
+
+void CChildView::OnTimer(UINT_PTR nIDEvent) {
+ UpdateThreadProcessIndices();
+}
+
+void CChildView::OnProcessRefresh() {
+ UpdateThreadProcessIndices();
+}
+
+
+void CChildView::OnOptionsAutorefreshthreadindices() {
+ m_AutoRefreshThreadIndices = !m_AutoRefreshThreadIndices;
+ if (m_AutoRefreshThreadIndices)
+ SetTimer(1, 10000, nullptr);
+ else
+ KillTimer(1);
+}
+
+
+void CChildView::OnUpdateOptionsAutorefreshthreadindices(CCmdUI *pCmdUI) {
+ pCmdUI->SetCheck(m_AutoRefreshThreadIndices);
+}
diff --git a/CPUSTRES/ChildView.h b/CPUSTRES/ChildView.h
new file mode 100644
index 0000000..376657a
--- /dev/null
+++ b/CPUSTRES/ChildView.h
@@ -0,0 +1,79 @@
+
+#pragma once
+
+#include "Thread.h"
+#include "ThreadsListCtrl.h"
+
+// CChildView window
+
+class CChildView : public CWnd {
+ // Construction
+public:
+ CChildView();
+
+ // Attributes
+public:
+
+ enum { IDC_LIST = 1234 };
+
+ // Operations
+public:
+
+ // Overrides
+protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+// Implementation
+public:
+ virtual ~CChildView();
+
+private:
+ CThreadsListCtrl m_List;
+ std::vector < std::unique_ptr> m_Threads;
+ std::vector m_CurrentThreadIds;
+ bool m_AutoRefreshThreadIndices = true;
+
+ void CreateThreads();
+ std::unique_ptr CreateThread();
+ void AddThread(std::unique_ptr& thread);
+ static PCWSTR ActivityLevelToString(ActivityLevel level);
+ static PCWSTR ThreadPriorityToString(int priority);
+ void UpdateThreadProcessIndices();
+
+ // Generated message map functions
+protected:
+ afx_msg void OnPaint();
+ DECLARE_MESSAGE_MAP()
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ std::vector> GetSelectedThreads() const;
+ void UpdateThread(int n, const CThread* thread = nullptr);
+ static int IndexToPriority(int index);
+ void OnThreadActivate();
+ void OnUpdateThreadActivate(CCmdUI *pCmdUI);
+ BOOL OnEraseBkgnd(CDC* pDC);
+ void OnThreadDeactivate();
+ void OnUpdateThreadDeactivate(CCmdUI *pCmdUI);
+ void OnRClickList(NMHDR*, LRESULT*);
+
+ void OnChangeThreadActivity(UINT id);
+ void OnUpdateChangeThreadActivity(CCmdUI* pCmdUI);
+ void OnProcessCreatethread();
+ void OnUpdateProcessCreatethread(CCmdUI *pCmdUI);
+ void OnProcessCreate4threads();
+ void OnUpdateProcessCreate4threads(CCmdUI *pCmdUI);
+ void OnChangeThreadPriority(UINT id);
+ void OnUpdateChangeThreadPriority(CCmdUI* pCmdUI);
+
+ afx_msg void OnThreadAffinity();
+ afx_msg void OnThreadIdealcpu();
+// afx_msg void OnProcessAffinity();
+// afx_msg void OnUpdateProcessAffinity(CCmdUI *pCmdUI);
+ afx_msg void OnThreadKill();
+ afx_msg void OnTimer(UINT_PTR nIDEvent);
+ afx_msg void OnProcessRefresh();
+ afx_msg void OnOptionsAutorefreshthreadindices();
+ afx_msg void OnUpdateOptionsAutorefreshthreadindices(CCmdUI *pCmdUI);
+};
+
diff --git a/CPUSTRES/Globals.cpp b/CPUSTRES/Globals.cpp
new file mode 100644
index 0000000..c3dcc26
--- /dev/null
+++ b/CPUSTRES/Globals.cpp
@@ -0,0 +1,32 @@
+#include "stdafx.h"
+#include "Globals.h"
+
+using namespace std;
+
+int CGlobals::s_Processors;
+
+int CGlobals::GetProcessorCount() {
+ if (s_Processors == 0) {
+ s_Processors = ::GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
+ }
+ return s_Processors;
+}
+
+std::vector CGlobals::EnumerateThreads(DWORD pid) {
+ vector threads;
+
+ auto hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ ASSERT(hSnapshot != INVALID_HANDLE_VALUE);
+
+ THREADENTRY32 te = { sizeof(te) };
+ if (::Thread32First(hSnapshot, &te)) {
+ do {
+ if (te.th32OwnerProcessID == pid)
+ threads.push_back(te.th32ThreadID);
+ } while (::Thread32Next(hSnapshot, &te));
+ }
+
+ ::CloseHandle(hSnapshot);
+ return threads;
+}
+
diff --git a/CPUSTRES/Globals.h b/CPUSTRES/Globals.h
new file mode 100644
index 0000000..902304c
--- /dev/null
+++ b/CPUSTRES/Globals.h
@@ -0,0 +1,11 @@
+#pragma once
+class CGlobals {
+public:
+ static int GetProcessorCount();
+
+ static std::vector EnumerateThreads(DWORD pid);
+
+private:
+ static int s_Processors;
+};
+
diff --git a/CPUSTRES/Icons/gear_add.ico b/CPUSTRES/Icons/gear_add.ico
new file mode 100644
index 0000000..7caa905
Binary files /dev/null and b/CPUSTRES/Icons/gear_add.ico differ
diff --git a/CPUSTRES/Icons/gear_delete.ico b/CPUSTRES/Icons/gear_delete.ico
new file mode 100644
index 0000000..8555a2e
Binary files /dev/null and b/CPUSTRES/Icons/gear_delete.ico differ
diff --git a/CPUSTRES/Icons/gear_pause.ico b/CPUSTRES/Icons/gear_pause.ico
new file mode 100644
index 0000000..01a7e71
Binary files /dev/null and b/CPUSTRES/Icons/gear_pause.ico differ
diff --git a/CPUSTRES/Icons/gear_run.ico b/CPUSTRES/Icons/gear_run.ico
new file mode 100644
index 0000000..d9e8fd2
Binary files /dev/null and b/CPUSTRES/Icons/gear_run.ico differ
diff --git a/CPUSTRES/MainDialogBar.cpp b/CPUSTRES/MainDialogBar.cpp
new file mode 100644
index 0000000..abd3764
--- /dev/null
+++ b/CPUSTRES/MainDialogBar.cpp
@@ -0,0 +1,55 @@
+// MainDialogBar.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+#include "MainDialogBar.h"
+#include "ChildView.h"
+
+// CMainDialogBar
+
+IMPLEMENT_DYNAMIC(CMainDialogBar, CDialogBar)
+
+CMainDialogBar::CMainDialogBar() {
+}
+
+CMainDialogBar::~CMainDialogBar() {
+}
+
+
+BEGIN_MESSAGE_MAP(CMainDialogBar, CDialogBar)
+ ON_WM_CREATE()
+ ON_COMMAND_RANGE(ID_ACTIVITYLEVEL_LOW, ID_ACTIVITYLEVEL_MAXIMUM, OnSetActivityLevel)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_ACTIVITYLEVEL_LOW, ID_ACTIVITYLEVEL_MAXIMUM, OnUpdateSetActivityLevel)
+END_MESSAGE_MAP()
+
+// CMainDialogBar message handlers
+
+
+int CMainDialogBar::OnCreate(LPCREATESTRUCT lpCreateStruct) {
+ if (CDialogBar::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ return 0;
+}
+
+void CMainDialogBar::OnSetActivityLevel(UINT id) {
+ m_pView->OnChangeThreadActivity(id);
+}
+
+void CMainDialogBar::OnUpdateSetActivityLevel(CCmdUI* pCmdUI) {
+ m_pView->OnUpdateChangeThreadActivity(pCmdUI);
+}
+
+void CMainDialogBar::InitControls(CChildView* pView) {
+ m_pView = pView;
+
+ // menu button
+
+ auto pButton = (CMFCMenuButton*)GetDlgItem(IDC_THREAD_ACTIVITY);
+ CMenu menu;
+ menu.LoadMenuW(IDR_CONTEXTMENU);
+ pButton->m_hMenu = menu.GetSubMenu(0)->m_hMenu;
+ menu.Detach();
+}
+
diff --git a/CPUSTRES/MainDialogBar.h b/CPUSTRES/MainDialogBar.h
new file mode 100644
index 0000000..bb4dc7c
--- /dev/null
+++ b/CPUSTRES/MainDialogBar.h
@@ -0,0 +1,27 @@
+#pragma once
+
+class CChildView;
+
+// CMainDialogBar
+
+class CMainDialogBar : public CDialogBar
+{
+ DECLARE_DYNAMIC(CMainDialogBar)
+
+public:
+ CMainDialogBar();
+ virtual ~CMainDialogBar();
+
+ void InitControls(CChildView*);
+
+protected:
+ CChildView* m_pView;
+
+ void OnSetActivityLevel(UINT id);
+ void OnUpdateSetActivityLevel(CCmdUI* pCmdUI);
+
+ DECLARE_MESSAGE_MAP()
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+};
+
+
diff --git a/CPUSTRES/MainFrm.cpp b/CPUSTRES/MainFrm.cpp
new file mode 100644
index 0000000..a55b6f9
--- /dev/null
+++ b/CPUSTRES/MainFrm.cpp
@@ -0,0 +1,192 @@
+
+// MainFrm.cpp : implementation of the CMainFrame class
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+
+#include "MainFrm.h"
+#include "AffinityDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+// CMainFrame
+
+IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
+ ON_WM_CREATE()
+ ON_WM_SETFOCUS()
+ ON_COMMAND(ID_OPTIONS_ALWAYSONTOP, &CMainFrame::OnOptionsAlwaysontop)
+ ON_UPDATE_COMMAND_UI(ID_OPTIONS_ALWAYSONTOP, &CMainFrame::OnUpdateOptionsAlwaysontop)
+ ON_COMMAND(ID_PROCESS_AFFINITY, &CMainFrame::OnProcessAffinity)
+ ON_COMMAND_RANGE(ID_PRIORITYCLASS_IDLE, ID_PRIORITYCLASS_REALTIME, OnChangePriorityClass)
+ ON_UPDATE_COMMAND_UI_RANGE(ID_PRIORITYCLASS_IDLE, ID_PRIORITYCLASS_REALTIME, OnUpdateChangePriorityClass)
+END_MESSAGE_MAP()
+
+// CMainFrame construction/destruction
+
+CMainFrame::CMainFrame() {
+ // TODO: add member initialization code here
+}
+
+CMainFrame::~CMainFrame() {}
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
+ if(CFrameWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ // create a view to occupy the client area of the frame
+ if(!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(), this, AFX_IDW_PANE_FIRST)) {
+ TRACE0("Failed to create view window\n");
+ return -1;
+ }
+
+ if(!m_wndDlgBar.Create(this, IDR_MAINFRAME, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR)) {
+ TRACE0("Failed to create dialogbar\n");
+ return -1;
+ }
+
+ SetProcessAffinityText();
+ SetProcessPriorityClassText();
+
+ // main icon window
+
+ SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), TRUE);
+ SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);
+
+ CString title;
+ title.LoadStringW(IDR_MAINFRAME);
+ CString pid;
+ pid.Format(L"%u", ::GetCurrentProcessId());
+ title.Replace(L"$", pid);
+ SetWindowText(title);
+
+ return 0;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) {
+ if(!CFrameWnd::PreCreateWindow(cs))
+ return FALSE;
+
+ cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
+ cs.lpszClass = AfxRegisterWndClass(0);
+ return TRUE;
+}
+
+// CMainFrame diagnostics
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const {
+ CFrameWnd::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const {
+ CFrameWnd::Dump(dc);
+}
+#endif //_DEBUG
+
+
+// CMainFrame message handlers
+
+void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/) {
+ // forward focus to the view window
+ m_wndView.SetFocus();
+}
+
+BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) {
+ // let the view have first crack at the command
+
+ if(m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
+ return TRUE;
+
+ // otherwise, do default handling
+
+ return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
+}
+
+void CMainFrame::OnOptionsAlwaysontop() {
+ bool onTop = (GetExStyle() & WS_EX_TOPMOST) > 0;
+ ::SetWindowPos(GetSafeHwnd(), onTop ? HWND_NOTOPMOST : HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+}
+
+
+void CMainFrame::OnUpdateOptionsAlwaysontop(CCmdUI *pCmdUI) {
+ pCmdUI->SetCheck((GetExStyle() & WS_EX_TOPMOST) > 0);
+}
+
+
+void CMainFrame::OnProcessAffinity() {
+ CAffinityDlg dlg(L"Set Process Affinity");
+ if(dlg.DoModal() == IDOK) {
+ if(!::SetProcessAffinityMask(::GetCurrentProcess(), dlg.GetSelectedAffinity())) {
+ AfxMessageBox(L"Failed to set process affinity mask");
+ return;
+ }
+ SetProcessAffinityText();
+ }
+}
+
+void CMainFrame::SetProcessAffinityText() {
+ DWORD_PTR processAffinity, systemAffinity;
+ ::GetProcessAffinityMask(::GetCurrentProcess(), &processAffinity, &systemAffinity);
+ WCHAR buffer[65];
+ _ui64tow_s(processAffinity, buffer, 65, 2);
+ m_wndDlgBar.GetDlgItem(IDC_PROCESS_AFFINITY)->SetWindowText(CString(L"Process Affinity: ") + buffer);
+}
+
+void CMainFrame::SetProcessPriorityClassText() {
+ int priority = ::GetPriorityClass(::GetCurrentProcess());
+ m_wndDlgBar.GetDlgItem(IDC_PRIORITYCLASS)->SetWindowText(CString(L"Process Priority Class: ") + PriorityClassToString(priority));
+}
+
+PCWSTR CMainFrame::PriorityClassToString(int priority) {
+ switch(priority) {
+ case NORMAL_PRIORITY_CLASS:
+ return L"Normal";
+ case IDLE_PRIORITY_CLASS:
+ return L"Idle";
+ case BELOW_NORMAL_PRIORITY_CLASS:
+ return L"Below Normal";
+ case ABOVE_NORMAL_PRIORITY_CLASS:
+ return L"Above Normal";
+ case HIGH_PRIORITY_CLASS:
+ return L"High";
+ case REALTIME_PRIORITY_CLASS:
+ return L"Realtime";
+ }
+ return nullptr;
+}
+
+void CMainFrame::OnChangePriorityClass(UINT id) {
+ static int priorities[] = {
+ IDLE_PRIORITY_CLASS, BELOW_NORMAL_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS,
+ ABOVE_NORMAL_PRIORITY_CLASS, HIGH_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS
+ };
+ ::SetPriorityClass(::GetCurrentProcess(), priorities[id - ID_PRIORITYCLASS_IDLE]);
+ SetProcessPriorityClassText();
+}
+
+void CMainFrame::OnUpdateChangePriorityClass(CCmdUI* pCmdUI) {
+ pCmdUI->SetRadio(pCmdUI->m_nID == PriorityClassToID(::GetPriorityClass(::GetCurrentProcess())));
+}
+
+int CMainFrame::PriorityClassToID(int priority) {
+ switch(priority) {
+ case NORMAL_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_NORMAL;
+ case IDLE_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_IDLE;
+ case BELOW_NORMAL_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_BELOWNORMAL;
+ case ABOVE_NORMAL_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_ABOVENORMAL;
+ case HIGH_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_HIGH;
+ case REALTIME_PRIORITY_CLASS:
+ return ID_PRIORITYCLASS_REALTIME;
+ }
+ return 0;
+}
diff --git a/CPUSTRES/MainFrm.h b/CPUSTRES/MainFrm.h
new file mode 100644
index 0000000..1cae3d1
--- /dev/null
+++ b/CPUSTRES/MainFrm.h
@@ -0,0 +1,57 @@
+
+// MainFrm.h : interface of the CMainFrame class
+//
+
+#pragma once
+#include "ChildView.h"
+
+class CMainFrame : public CFrameWnd {
+
+public:
+ CMainFrame();
+protected:
+ DECLARE_DYNAMIC(CMainFrame)
+
+ // Attributes
+public:
+
+ // Operations
+public:
+
+ // Overrides
+public:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
+
+ // Implementation
+public:
+ virtual ~CMainFrame();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+ static PCWSTR PriorityClassToString(int priority);
+ static int PriorityClassToID(int priority);
+
+protected: // control bar embedded members
+ CDialogBar m_wndDlgBar;
+ CChildView m_wndView;
+
+ // Generated message map functions
+protected:
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSetFocus(CWnd *pOldWnd);
+ DECLARE_MESSAGE_MAP()
+
+ void SetProcessAffinityText();
+
+ afx_msg void OnOptionsAlwaysontop();
+ afx_msg void OnUpdateOptionsAlwaysontop(CCmdUI *pCmdUI);
+ afx_msg void OnProcessAffinity();
+ void OnChangePriorityClass(UINT id);
+ void OnUpdateChangePriorityClass(CCmdUI* pCmdUI);
+ void SetProcessPriorityClassText();
+};
+
+
diff --git a/CPUSTRES/README.md b/CPUSTRES/README.md
new file mode 100644
index 0000000..13e34d1
--- /dev/null
+++ b/CPUSTRES/README.md
@@ -0,0 +1,3 @@
+# CPUStressEx
+
+An enhanced version of the old CPUSTRES tool.
diff --git a/CPUSTRES/Thread.cpp b/CPUSTRES/Thread.cpp
new file mode 100644
index 0000000..64a87be
--- /dev/null
+++ b/CPUSTRES/Thread.cpp
@@ -0,0 +1,88 @@
+// Thread.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+#include "Thread.h"
+#include "Globals.h"
+
+// CThread
+
+CThread::CThread() {
+ int cpus = CGlobals::GetProcessorCount();
+ if(cpus == sizeof(DWORD_PTR) * 8)
+ m_Affinity = (DWORD_PTR)-1;
+ else
+ m_Affinity = (((DWORD_PTR)1) << cpus) - 1;
+ m_hTerminate = ::CreateEvent(nullptr, FALSE, FALSE, nullptr);
+ m_hThread = ::CreateThread(nullptr, 0, ThreadFunction, this, CREATE_SUSPENDED, &m_ID);
+}
+
+CThread::~CThread() {
+ ::CloseHandle(m_hThread);
+ ::CloseHandle(m_hTerminate);
+}
+
+void CThread::Suspend() {
+ if (!IsActive()) return;
+
+ ::SuspendThread(m_hThread);
+ m_Active = false;
+}
+
+void CThread::Resume() {
+ if (IsActive()) return;
+
+ ::ResumeThread(m_hThread);
+ m_Active = true;
+}
+
+DWORD CThread::ThreadFunction(PVOID p) {
+ return reinterpret_cast(p)->ThreadFunction();
+}
+
+DWORD CThread::ThreadFunction() {
+ auto hTerminate = m_hTerminate;
+ for (;;) {
+ if (::WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0)
+ break;
+
+ auto level = m_ActivityLevel;
+ if (level != ActivityLevel::Maximum) {
+ auto time = ::GetTickCount();
+ while (::GetTickCount() - time < (unsigned)level * 25)
+ ;
+ ::Sleep(100 - (int)level * 25);
+ }
+ }
+
+ return 0;
+}
+
+void CThread::SetAfinity(DWORD_PTR affinity) {
+ ::SetThreadAffinityMask(m_hThread, m_Affinity = affinity);
+}
+
+DWORD_PTR CThread::GetAffinity() const {
+ return m_Affinity;
+}
+
+DWORD CThread::SetIdealCPU(int n) {
+ return ::SetThreadIdealProcessor(m_hThread, n);
+}
+
+int CThread::GetIdealCPU() const {
+ PROCESSOR_NUMBER n;
+ ::GetThreadIdealProcessorEx(m_hThread, &n);
+ return n.Number;
+}
+
+void CThread::Terminate() {
+ m_ActivityLevel = ActivityLevel::None;
+ ::SetEvent(m_hTerminate);
+ Resume();
+ if(::WaitForSingleObject(m_hThread, 500) == WAIT_TIMEOUT)
+ ::TerminateThread(m_hThread, 1);
+}
+
+
diff --git a/CPUSTRES/Thread.h b/CPUSTRES/Thread.h
new file mode 100644
index 0000000..02785d7
--- /dev/null
+++ b/CPUSTRES/Thread.h
@@ -0,0 +1,72 @@
+
+#pragma once
+
+enum class ActivityLevel {
+ None = 0,
+ Low = 1,
+ Medium = 2,
+ Busy = 3,
+ Maximum = 4
+};
+
+// CThread command target
+
+class CThread {
+public:
+ CThread();
+ virtual ~CThread();
+
+ DWORD GetThreadId() const {
+ return m_ID;
+ }
+
+ int GetPriority() const {
+ return ::GetThreadPriority(m_hThread);
+ }
+
+ void SetProcessIndex(int index) {
+ m_IndexInProcess = index;
+ }
+
+ int GetProcessIndex() const {
+ return m_IndexInProcess;
+ }
+
+ ActivityLevel GetActivityLevel() const {
+ return m_ActivityLevel;
+ }
+
+ bool IsActive() const {
+ return m_Active;
+ }
+
+ void SetPriority(int priority) {
+ ::SetThreadPriority(m_hThread, priority);
+ }
+
+ void SetAfinity(DWORD_PTR affinity);
+ DWORD_PTR GetAffinity() const;
+
+ DWORD SetIdealCPU(int n);
+ int GetIdealCPU() const;
+
+ void Terminate();
+ void Suspend();
+ void Resume();
+ void SetActivityLevel(ActivityLevel level) {
+ m_ActivityLevel = level;
+ }
+
+ static DWORD CALLBACK ThreadFunction(PVOID);
+ DWORD CALLBACK ThreadFunction();
+
+private:
+ HANDLE m_hThread, m_hTerminate;
+ DWORD m_ID;
+ int m_IndexInProcess;
+ ActivityLevel m_ActivityLevel = ActivityLevel::Low;
+ bool m_Active = false;
+ DWORD_PTR m_Affinity;
+};
+
+
diff --git a/CPUSTRES/ThreadsListCtrl.cpp b/CPUSTRES/ThreadsListCtrl.cpp
new file mode 100644
index 0000000..f095acd
--- /dev/null
+++ b/CPUSTRES/ThreadsListCtrl.cpp
@@ -0,0 +1,59 @@
+// ThreadsListCtrl.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CPUStressEx.h"
+#include "ThreadsListCtrl.h"
+
+
+// CThreadsListCtrl
+
+IMPLEMENT_DYNAMIC(CThreadsListCtrl, CMFCListCtrl)
+
+CThreadsListCtrl::CThreadsListCtrl(const std::vector>& threads) : m_Threads(threads)
+{
+}
+
+CThreadsListCtrl::~CThreadsListCtrl()
+{
+}
+
+
+COLORREF CThreadsListCtrl::OnGetCellBkColor(int nRow, int nColumn) {
+ auto thread = GetThread(nRow);
+ if (!thread->IsActive())
+ return (COLORREF)Color::White;
+
+ switch (thread->GetActivityLevel()) {
+ case ActivityLevel::Low:
+ return (COLORREF)Color::Yellow;
+ case ActivityLevel::Medium:
+ return (COLORREF)Color::Orange;
+ case ActivityLevel::Busy:
+ return (COLORREF)Color::Red;
+ case ActivityLevel::Maximum:
+ return (COLORREF)Color::DarkRed;
+ default:
+ ASSERT(0);
+ return 0;
+ }
+}
+
+COLORREF CThreadsListCtrl::OnGetCellTextColor(int nRow, int nColumn) {
+ auto thread = GetThread(nRow);
+ auto color = Color::Black;
+ if (thread->IsActive() && thread->GetActivityLevel() >= ActivityLevel::Busy)
+ color = Color::White;
+ return (COLORREF)color;
+}
+
+CThread * CThreadsListCtrl::GetThread(int row) const {
+ return reinterpret_cast(GetItemData(row));
+}
+
+BEGIN_MESSAGE_MAP(CThreadsListCtrl, CMFCListCtrl)
+END_MESSAGE_MAP()
+
+// CThreadsListCtrl message handlers
+
+
diff --git a/CPUSTRES/ThreadsListCtrl.h b/CPUSTRES/ThreadsListCtrl.h
new file mode 100644
index 0000000..9381b00
--- /dev/null
+++ b/CPUSTRES/ThreadsListCtrl.h
@@ -0,0 +1,36 @@
+#pragma once
+
+
+// CThreadsListCtrl
+
+enum class Color : unsigned {
+ White = RGB(255, 255, 255),
+ Black = 0,
+ DarkRed = RGB(128, 0, 0),
+ Red = RGB(255, 0, 0),
+ Orange = RGB(255, 128, 0),
+ Yellow = RGB(255, 255, 0)
+};
+
+#include "Thread.h"
+
+class CThreadsListCtrl : public CMFCListCtrl {
+ DECLARE_DYNAMIC(CThreadsListCtrl)
+
+public:
+ CThreadsListCtrl(const std::vector>& threads);
+ virtual ~CThreadsListCtrl();
+
+ COLORREF OnGetCellBkColor(int nRow, int nColumn);
+ COLORREF OnGetCellTextColor(int nRow, int nColumn);
+
+private:
+ CThread* GetThread(int row) const;
+
+protected:
+ const std::vector>& m_Threads;
+
+ DECLARE_MESSAGE_MAP()
+};
+
+
diff --git a/CPUSTRES/publish_config.json b/CPUSTRES/publish_config.json
new file mode 100644
index 0000000..ada80e6
--- /dev/null
+++ b/CPUSTRES/publish_config.json
@@ -0,0 +1,15 @@
+{
+ "packageName": "CPUSTRES.zip",
+ "files": [
+ {
+ "name": "CPUSTRES.EXE",
+ "platform": "Win32",
+ "configuration": "Release"
+ },
+ {
+ "name": "CPUSTRES64.EXE",
+ "platform": "x64",
+ "configuration": "Release"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/CPUSTRES/res/CPUStressEx.ico b/CPUSTRES/res/CPUStressEx.ico
new file mode 100644
index 0000000..a6e753b
Binary files /dev/null and b/CPUSTRES/res/CPUStressEx.ico differ
diff --git a/CPUSTRES/res/CPUStressEx.rc2 b/CPUSTRES/res/CPUStressEx.rc2
new file mode 100644
index 0000000..b698c2f
Binary files /dev/null and b/CPUSTRES/res/CPUStressEx.rc2 differ
diff --git a/CPUSTRES/resource.h b/CPUSTRES/resource.h
new file mode 100644
index 0000000..2ec9abe
--- /dev/null
+++ b/CPUSTRES/resource.h
@@ -0,0 +1,65 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by CPUStressEx.rc
+//
+#define IDD_ABOUTBOX 100
+#define IDR_MAINFRAME 128
+#define IDR_CPUStressExTYPE 130
+#define IDI_PLAY 312
+#define IDI_KILL 313
+#define IDI_PAUSE 314
+#define IDR_CONTEXTMENU 315
+#define IDI_CREATE 316
+#define IDD_AFFINITY 317
+#define IDC_THREAD_ACTIVITY 1002
+#define IDC_DUMMY 1003
+#define IDC_SELECTALL 1004
+#define IDC_UNSELECTALL 1005
+#define IDC_PROCESS_AFFINITY 1006
+#define IDC_PRIORITYCLASS 1007
+#define IDC_MFCLINK1 1008
+#define IDC_LINK 1008
+#define ID_THREAD_ACTIVE 32771
+#define ID_THREAD_ACTIVITYLEVEL 32772
+#define ID_ACTIVITYLEVEL_LOW 32773
+#define ID_ACTIVITYLEVEL_MEDIUM 32774
+#define ID_ACTIVITYLEVEL_BUSY 32775
+#define ID_ACTIVITYLEVEL_MAXIMUM 32776
+#define ID_THREAD_AFFINITY 32778
+#define ID_THREAD_IDEALCPU 32779
+#define ID_THREAD_KILL 32780
+#define ID_PROCESS_AFFINITY 32781
+#define ID_PROCESS_PRIORITYCLASS 32782
+#define ID_PRIORITYCLASS_IDLE 32783
+#define ID_PRIORITYCLASS_BELOWNORMAL 32784
+#define ID_PRIORITYCLASS_NORMAL 32785
+#define ID_PRIORITYCLASS_ABOVENORMAL 32786
+#define ID_PRIORITYCLASS_HIGH 32787
+#define ID_PRIORITYCLASS_REALTIME 32788
+#define ID_THREAD_PRIORITY 32789
+#define ID_PRIORITY_IDLE 32790
+#define ID_PRIORITY_LOWEST 32791
+#define ID_PRIORITY_BELOWNORMAL 32792
+#define ID_PRIORITY_NORMAL 32793
+#define ID_PRIORITY_ABOVENORMAL 32794
+#define ID_PRIORITY_HIGHEST 32795
+#define ID_PRIORITY_TIMECRITICAL 32796
+#define ID_OPTIONS_ALWAYSONTOP 32797
+#define ID_THREAD_ACTIVATE 32798
+#define ID_THREAD_DEACTIVATE 32799
+#define ID_THREAD_ACTIVE32800 32800
+#define ID_PROCESS_CREATETHREAD 32801
+#define ID_PROCESS_CREATE4THREADS 32802
+#define ID_PROCESS_REFRESH 32803
+#define ID_OPTIONS_AUTOREFRESHTHREADINDICES 32806
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 321
+#define _APS_NEXT_COMMAND_VALUE 32807
+#define _APS_NEXT_CONTROL_VALUE 1009
+#define _APS_NEXT_SYMED_VALUE 310
+#endif
+#endif
diff --git a/CPUSTRES/stdafx.cpp b/CPUSTRES/stdafx.cpp
new file mode 100644
index 0000000..f529dd1
--- /dev/null
+++ b/CPUSTRES/stdafx.cpp
@@ -0,0 +1,8 @@
+
+// stdafx.cpp : source file that includes just the standard includes
+// CPUStressEx.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
diff --git a/CPUSTRES/stdafx.h b/CPUSTRES/stdafx.h
new file mode 100644
index 0000000..d30a405
--- /dev/null
+++ b/CPUSTRES/stdafx.h
@@ -0,0 +1,54 @@
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+// turns off MFC's hiding of some common and often safely ignored warning messages
+#define _AFX_ALL_WARNINGS
+
+#include // MFC core and standard components
+#include // MFC extensions
+
+#include
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include // MFC support for Internet Explorer 4 Common Controls
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include // MFC support for ribbons and control bars
+
+#include
+#include
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+
diff --git a/CPUSTRES/targetver.h b/CPUSTRES/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/CPUSTRES/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include
diff --git a/Tools.sln b/Tools.sln
index d4a099e..464ddb6 100644
--- a/Tools.sln
+++ b/Tools.sln
@@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chapter05", "Chapter05", "{
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemCombine", "MemCombine\MemCombine.vcxproj", "{6502E3AD-8D8E-4F1A-923C-0F4F89FF02E7}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPUSTRES", "CPUSTRES\CPUStressEx.vcxproj", "{DC1EF85A-8628-457A-A805-49CCC97DF5BF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -96,6 +98,14 @@ Global
{6502E3AD-8D8E-4F1A-923C-0F4F89FF02E7}.Release|x64.Build.0 = Release|x64
{6502E3AD-8D8E-4F1A-923C-0F4F89FF02E7}.Release|x86.ActiveCfg = Release|Win32
{6502E3AD-8D8E-4F1A-923C-0F4F89FF02E7}.Release|x86.Build.0 = Release|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x64.ActiveCfg = Debug|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x64.Build.0 = Debug|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x86.ActiveCfg = Debug|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Debug|x86.Build.0 = Debug|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x64.ActiveCfg = Release|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x64.Build.0 = Release|x64
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x86.ActiveCfg = Release|Win32
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -108,5 +118,6 @@ Global
{BA4AD343-6096-45A8-868E-3D56316F62FF} = {8832CADD-82A2-4129-9595-3A4B6EEB1D7F}
{616F6D2F-29E2-40B0-BB28-00BED735FB03} = {8832CADD-82A2-4129-9595-3A4B6EEB1D7F}
{6502E3AD-8D8E-4F1A-923C-0F4F89FF02E7} = {C3EFEE31-DD3B-4A28-B916-3B957FBC0ED4}
+ {DC1EF85A-8628-457A-A805-49CCC97DF5BF} = {83E4C2CE-DD24-45E9-983D-58B01228443A}
EndGlobalSection
EndGlobal