Sync to trunk head(r38096)
[reactos.git] / reactos / base / applications / taskmgr / affinity.c
1 /*
2 * ReactOS Task Manager
3 *
4 * affinity.c
5 *
6 * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org>
7 * 2005 Klemens Friedl <frik85@reactos.at>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <precomp.h>
25
26 HANDLE hProcessAffinityHandle;
27
28 static const DWORD dwCpuTable[] = {
29 IDC_CPU0, IDC_CPU1, IDC_CPU2, IDC_CPU3,
30 IDC_CPU4, IDC_CPU5, IDC_CPU6, IDC_CPU7,
31 IDC_CPU8, IDC_CPU9, IDC_CPU10, IDC_CPU11,
32 IDC_CPU12, IDC_CPU13, IDC_CPU14, IDC_CPU15,
33 IDC_CPU16, IDC_CPU17, IDC_CPU18, IDC_CPU19,
34 IDC_CPU20, IDC_CPU21, IDC_CPU22, IDC_CPU23,
35 IDC_CPU24, IDC_CPU25, IDC_CPU26, IDC_CPU27,
36 IDC_CPU28, IDC_CPU29, IDC_CPU30, IDC_CPU31,
37 };
38
39 static INT_PTR CALLBACK AffinityDialogWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
40
41 void ProcessPage_OnSetAffinity(void)
42 {
43 LV_ITEM lvitem;
44 ULONG Index;
45 DWORD dwProcessId;
46 WCHAR strErrorText[260];
47 WCHAR szTitle[256];
48
49 for (Index=0; Index<(ULONG)ListView_GetItemCount(hProcessPageListCtrl); Index++) {
50 memset(&lvitem, 0, sizeof(LV_ITEM));
51 lvitem.mask = LVIF_STATE;
52 lvitem.stateMask = LVIS_SELECTED;
53 lvitem.iItem = Index;
54 (void)ListView_GetItem(hProcessPageListCtrl, &lvitem);
55 if (lvitem.state & LVIS_SELECTED)
56 break;
57 }
58 dwProcessId = PerfDataGetProcessId(Index);
59 if ((ListView_GetSelectedCount(hProcessPageListCtrl) != 1) || (dwProcessId == 0))
60 return;
61 hProcessAffinityHandle = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, FALSE, dwProcessId);
62 if (!hProcessAffinityHandle) {
63 GetLastErrorText(strErrorText, sizeof(strErrorText) / sizeof(WCHAR));
64 LoadStringW(hInst, IDS_MSG_ACCESSPROCESSAFF, szTitle, sizeof(szTitle) / sizeof(WCHAR));
65 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
66 return;
67 }
68 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_AFFINITY_DIALOG), hMainWnd, AffinityDialogWndProc);
69 if (hProcessAffinityHandle) {
70 CloseHandle(hProcessAffinityHandle);
71 hProcessAffinityHandle = NULL;
72 }
73 }
74
75 INT_PTR CALLBACK
76 AffinityDialogWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
77 {
78 DWORD_PTR dwProcessAffinityMask = 0;
79 DWORD_PTR dwSystemAffinityMask = 0;
80 WCHAR strErrorText[260];
81 WCHAR szTitle[256];
82 BYTE nCpu;
83
84 switch (message) {
85 case WM_INITDIALOG:
86
87 /*
88 * Get the current affinity mask for the process and
89 * the number of CPUs present in the system
90 */
91 if (!GetProcessAffinityMask(hProcessAffinityHandle, &dwProcessAffinityMask, &dwSystemAffinityMask)) {
92 GetLastErrorText(strErrorText, sizeof(strErrorText) / sizeof(WCHAR));
93 EndDialog(hDlg, 0);
94 LoadStringW(hInst, IDS_MSG_ACCESSPROCESSAFF, szTitle, sizeof(szTitle) / sizeof(WCHAR));
95 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
96 }
97
98 for (nCpu=0; nCpu<sizeof(dwCpuTable) / sizeof(dwCpuTable[0]); nCpu++) {
99 /*
100 * Enable a checkbox for each processor present in the system
101 */
102 if (dwSystemAffinityMask & (1 << nCpu))
103 EnableWindow(GetDlgItem(hDlg, dwCpuTable[nCpu]), TRUE);
104 /*
105 * Check each checkbox that the current process
106 * has affinity with
107 */
108 if (dwProcessAffinityMask & (1 << nCpu))
109 SendMessageW(GetDlgItem(hDlg, dwCpuTable[nCpu]), BM_SETCHECK, BST_CHECKED, 0);
110 }
111
112 return TRUE;
113
114 case WM_COMMAND:
115
116 /*
117 * If the user has cancelled the dialog box
118 * then just close it
119 */
120 if (LOWORD(wParam) == IDCANCEL) {
121 EndDialog(hDlg, LOWORD(wParam));
122 return TRUE;
123 }
124
125 /*
126 * The user has clicked OK -- so now we have
127 * to adjust the process affinity mask
128 */
129 if (LOWORD(wParam) == IDOK) {
130 for (nCpu=0; nCpu<sizeof(dwCpuTable) / sizeof(dwCpuTable[0]); nCpu++) {
131 /*
132 * First we have to create a mask out of each
133 * checkbox that the user checked.
134 */
135 if (SendMessageW(GetDlgItem(hDlg, dwCpuTable[nCpu]), BM_GETCHECK, 0, 0))
136 dwProcessAffinityMask |= (1 << nCpu);
137 }
138
139 /*
140 * Make sure they are giving the process affinity
141 * with at least one processor. I'd hate to see a
142 * process that is not in a wait state get deprived
143 * of it's cpu time.
144 */
145 if (!dwProcessAffinityMask) {
146 LoadStringW(hInst, IDS_MSG_PROCESSONEPRO, strErrorText, sizeof(strErrorText) / sizeof(WCHAR));
147 LoadStringW(hInst, IDS_MSG_INVALIDOPTION, szTitle, sizeof(szTitle) / sizeof(WCHAR));
148 MessageBoxW(hDlg, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
149 return TRUE;
150 }
151
152 /*
153 * Try to set the process affinity
154 */
155 if (!SetProcessAffinityMask(hProcessAffinityHandle, dwProcessAffinityMask)) {
156 GetLastErrorText(strErrorText, sizeof(strErrorText) / sizeof(WCHAR));
157 EndDialog(hDlg, LOWORD(wParam));
158 LoadStringW(hInst, IDS_MSG_ACCESSPROCESSAFF, szTitle, sizeof(szTitle) / sizeof(WCHAR));
159 MessageBoxW(hMainWnd, strErrorText, szTitle, MB_OK|MB_ICONSTOP);
160 }
161
162 EndDialog(hDlg, LOWORD(wParam));
163 return TRUE;
164 }
165
166 break;
167 }
168
169 return 0;
170 }