📄 joblab.cpp
字号:
// Set Basic and Extended Limits
JOBOBJECT_EXTENDED_LIMIT_INFORMATION joeli = { 0 };
joeli.BasicLimitInformation.LimitFlags = 0;
q = GetDlgItemInt(hwnd, IDC_PERPROCESSUSERTIMELIMIT, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PROCESS_TIME;
joeli.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart =
q * nNanosecondsPerMillisecond / 100;
}
q = GetDlgItemInt(hwnd, IDC_PERJOBUSERTIMELIMIT, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_TIME;
joeli.BasicLimitInformation.PerJobUserTimeLimit.QuadPart =
q * nNanosecondsPerMillisecond / 100;
}
s = GetDlgItemInt(hwnd, IDC_MINWORKINGSETSIZE, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_WORKINGSET;
joeli.BasicLimitInformation.MinimumWorkingSetSize = s * 1024 * 1024;
s = GetDlgItemInt(hwnd, IDC_MAXWORKINGSETSIZE, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.MaximumWorkingSetSize = s * 1024 * 1024;
} else {
joeli.BasicLimitInformation.LimitFlags &=~JOB_OBJECT_LIMIT_WORKINGSET;
chMB("Both minimum and maximum working set sizes must be set.\n"
"The working set limits will NOT be in effect.");
}
}
d = GetDlgItemInt(hwnd, IDC_ACTIVEPROCESSLIMIT, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
joeli.BasicLimitInformation.ActiveProcessLimit = d;
}
s = GetDlgItemInt(hwnd, IDC_AFFINITYMASK, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_AFFINITY;
joeli.BasicLimitInformation.Affinity = s;
}
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
switch (ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PRIORITYCLASS))) {
case 0:
joeli.BasicLimitInformation.LimitFlags &=
~JOB_OBJECT_LIMIT_PRIORITY_CLASS;
break;
case 1:
joeli.BasicLimitInformation.PriorityClass =
IDLE_PRIORITY_CLASS;
break;
case 2:
joeli.BasicLimitInformation.PriorityClass =
BELOW_NORMAL_PRIORITY_CLASS;
break;
case 3:
joeli.BasicLimitInformation.PriorityClass =
NORMAL_PRIORITY_CLASS;
break;
case 4:
joeli.BasicLimitInformation.PriorityClass =
ABOVE_NORMAL_PRIORITY_CLASS;
break;
case 5:
joeli.BasicLimitInformation.PriorityClass =
HIGH_PRIORITY_CLASS;
break;
case 6:
joeli.BasicLimitInformation.PriorityClass =
REALTIME_PRIORITY_CLASS;
break;
}
int nSchedulingClass =
ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_SCHEDULINGCLASS));
if (nSchedulingClass > 0) {
joeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_SCHEDULING_CLASS;
joeli.BasicLimitInformation.SchedulingClass = nSchedulingClass - 1;
}
s = GetDlgItemInt(hwnd, IDC_MAXCOMMITPERJOB, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_MEMORY;
joeli.JobMemoryLimit = s * 1024 * 1024;
}
s = GetDlgItemInt(hwnd, IDC_MAXCOMMITPERPROCESS, &f, FALSE);
if (f) {
joeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_PROCESS_MEMORY;
joeli.ProcessMemoryLimit = s * 1024 * 1024;
}
if (IsDlgButtonChecked(hwnd, IDC_CHILDPROCESSESCANBREAKAWAYFROMJOB))
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;
if (IsDlgButtonChecked(hwnd, IDC_CHILDPROCESSESDOBREAKAWAYFROMJOB))
joeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
if (IsDlgButtonChecked(hwnd, IDC_TERMINATEPROCESSONEXCEPTIONS))
joeli.BasicLimitInformation.LimitFlags |=
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
f = g_job.SetExtendedLimitInfo(&joeli,
((joeli.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME)
!= 0) ? FALSE :
IsDlgButtonChecked(hwnd, IDC_PRESERVEJOBTIMEWHENAPPLYINGLIMITS));
chASSERT(f);
// Set UI Restrictions
DWORD jobuir = JOB_OBJECT_UILIMIT_NONE; // A fancy zero (0)
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTACCESSTOOUTSIDEUSEROBJECTS))
jobuir |= JOB_OBJECT_UILIMIT_HANDLES;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTREADINGCLIPBOARD))
jobuir |= JOB_OBJECT_UILIMIT_READCLIPBOARD;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTWRITINGCLIPBOARD))
jobuir |= JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTEXITWINDOW))
jobuir |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTCHANGINGSYSTEMPARAMETERS))
jobuir |= JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTDESKTOPS))
jobuir |= JOB_OBJECT_UILIMIT_DESKTOP;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTDISPLAYSETTINGS))
jobuir |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;
if (IsDlgButtonChecked(hwnd, IDC_RESTRICTGLOBALATOMS))
jobuir |= JOB_OBJECT_UILIMIT_GLOBALATOMS;
chVERIFY(g_job.SetBasicUIRestrictions(jobuir));
}
///////////////////////////////////////////////////////////////////////////////
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {
switch (id) {
case IDCANCEL:
// User is terminating our app, kill the job too.
KillTimer(hwnd, 1);
g_job.Terminate(0);
EndDialog(hwnd, id);
break;
case IDC_PERJOBUSERTIMELIMIT:
{
// The job time must be reset if setting a job time limit
BOOL f;
GetDlgItemInt(hwnd, IDC_PERJOBUSERTIMELIMIT, &f, FALSE);
EnableWindow(
GetDlgItem(hwnd, IDC_PRESERVEJOBTIMEWHENAPPLYINGLIMITS), !f);
}
break;
case IDC_APPLYLIMITS:
Dlg_ApplyLimits(hwnd);
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
break;
case IDC_TERMINATE:
g_job.Terminate(0);
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
break;
case IDC_SPAWNCMDINJOB:
{
// Spawn a command shell and place it in the job
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR sz[] = TEXT("CMD");
CreateProcess(NULL, sz, NULL, NULL,
FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
g_job.AssignProcess(pi.hProcess);
ResumeThread(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
break;
case IDC_ASSIGNPROCESSTOJOB:
{
DWORD dwProcessId = GetDlgItemInt(hwnd, IDC_PROCESSID, NULL, FALSE);
HANDLE hProcess = OpenProcess(
PROCESS_SET_QUOTA | PROCESS_TERMINATE, FALSE, dwProcessId);
if (hProcess != NULL) {
chVERIFY(g_job.AssignProcess(hProcess));
CloseHandle(hProcess);
} else chMB("Could not assign process to job.");
}
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
void WINAPI Dlg_OnTimer(HWND hwnd, UINT id) {
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
}
///////////////////////////////////////////////////////////////////////////////
INT_PTR WINAPI Dlg_Proc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
chHANDLE_DLGMSG(hwnd, WM_TIMER, Dlg_OnTimer);
chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand);
}
return(FALSE);
}
///////////////////////////////////////////////////////////////////////////////
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) {
// Check if we are not already associated with a job.
// If this is the case, there is no way to switch to
// another job.
BOOL bInJob = FALSE;
IsProcessInJob(GetCurrentProcess(), NULL, &bInJob);
if (bInJob) {
MessageBox(NULL, TEXT("Process already in a job"),
TEXT(""), MB_ICONINFORMATION | MB_OK);
return(-1);
}
// Create the completion port that receives job notifications
g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
// Create a thread that waits on the completion port
g_hThreadIOCP = chBEGINTHREADEX(NULL, 0, JobNotify, NULL, 0, NULL);
// Create the job object
g_job.Create(NULL, TEXT("JobLab"));
g_job.SetEndOfJobInfo(JOB_OBJECT_POST_AT_END_OF_JOB);
g_job.AssociateCompletionPort(g_hIOCP, COMPKEY_JOBOBJECT);
DialogBox(hinstExe, MAKEINTRESOURCE(IDD_JOBLAB), NULL, Dlg_Proc);
// Post a special key that tells the completion port thread to terminate
PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_TERMINATE, NULL);
// Wait for the completion port thread to terminate
WaitForSingleObject(g_hThreadIOCP, INFINITE);
// Clean up everything properly
CloseHandle(g_hIOCP);
CloseHandle(g_hThreadIOCP);
// NOTE: The job is closed when the g_job's destructor is called.
return(0);
}
///////////////////////////////// End Of File /////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -