演示作业限制设置
演示作业限制设置
文章目录
演示作业限制设置
/*
演示作业限制设置
*/
#include"..\\CommonFiles\\CmnHdr.h"
#include "resource.h"
#include "Job.h"
#include<tchar.h>
#include<strsafe.h>
#include<windowsx.h>
HWND g_hwnd; //对话框句柄(被所有的线程访问)
HANDLE g_hIOCP; //用来接受作业通知完成的端口
HANDLE g_hThreadIOCP; //完成端口线程句柄
CJob g_job; //作业对象句柄
//完成端口的CompletionKey
#define COMPKEY_TERMINATE ((UINT_PTR)0)
#define COMPKEY_STATUS ((UINT_PTR)1)
#define COMPKEY_JOBOBJECT ((UINT_PTR)2)
void GetProcessName(DWORD PID, PTSTR szProcessName, size_t cchSize) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (hProcess ==NULL)
{
_tcscpy_s(szProcessName, cchSize, TEXT("???"));
return;
}
//....
//以上函数调用,可用下列函数来替代,因为下列函数可适用各种情况
DWORD dwSize = (DWORD)cchSize;
QueryFullProcessImageName(hProcess, 0, szProcessName, &dwSize);
CloseHandle(hProcess);
}
DWORD WINAPI JobNotify(PVOID) {
TCHAR sz[3000];
BOOL fDone = FALSE;
ULONG_PTR CompKey;//指定出发这个事件的作业对象的句柄
LPOVERLAPPED po;//进程ID
DWORD dwBytesXferred;//等待的事件ID
while (!fDone)
{
GetQueuedCompletionStatus(g_hIOCP, &dwBytesXferred,
&CompKey, &po, INFINITE);
//应用程序关闭,退出线程
fDone = (CompKey == COMPKEY_TERMINATE);
//lpClassName为NULL则查找所有标题与第二个参数匹配的窗口
HWND hwndLB = FindWindow(NULL, TEXT("Job Lab"));
hwndLB = GetDlgItem(hwndLB, IDC_STATUS);
if (CompKey == COMPKEY_JOBOBJECT)
{
_tcscpy_s(sz, _countof(sz), TEXT("--> Notification:"));
PTSTR psz = sz + _tcslen(sz);
switch (dwBytesXferred)
{
//作业对象中活动进程数量达到上限
case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象中活动进程数已达到上限!"));
break;
//作业对象中当前没有活动的进程
case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象中当前没有活动进程"));
break;
//作业对象耗尽指定的时间片
case JOB_OBJECT_MSG_END_OF_JOB_TIME: {
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("作业对象耗尽指定的时间片"));
}
break;
//作业对象耗尽指定的内存
case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)导致作业对象消耗内存到达到上限!"),szProcessName,po);
}
break;
//新进程加入作业对象
case JOB_OBJECT_MSG_NEW_PROCESS: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)加入作业对象!"), szProcessName, po);
}
break;
//进程正常退出
case JOB_OBJECT_MSG_EXIT_PROCESS: {
TCHAR szProcessName[MAX_PATH];
DWORD dwExitCode = 0;
//注意进程退出了。但其内核对象并没有释放,还可以从内核对象中获取推出吗
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PtrToUlong(po));
if (NULL != hProcess)
{
GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)正常退出,推出码(%d)!"), szProcessName, po, dwExitCode);
}
break;
//进程异常退出
case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: {
TCHAR szProcessName[MAX_PATH];
DWORD dwExitCode = 0;
//注意进程退出了。但其内核对象并没有释放,还可以从内核对象中获取推出吗
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PtrToUlong(po));
if (NULL != hProcess)
{
GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);//po存在进程ID
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程 %s(ID=%d)异常退出,推出码(%d)!"), szProcessName, po, dwExitCode);
}
break;
//进程耗尽时间片
case JOB_OBJECT_MSG_END_OF_PROCESS_TIME: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程%s(ID-%d)耗尽事件片!"), szProcessName, po);
}
break;
//进程小号内存数量达到上限
case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: {
TCHAR szProcessName[MAX_PATH];
GetProcessName(PtrToUlong(po), szProcessName, MAX_PATH);
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("进程%s(ID=%d)小号内存达到上限!"), szProcessName, po);
}
break;
default:
StringCchPrintf(psz, _countof(sz) - _tcslen(sz),
TEXT("未知通知:%d"), dwBytesXferred);
}
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
CompKey = 1;//当作业通知到达时,强迫更新状态
}
//更新作业状态
if (CompKey == COMPKEY_STATUS)
{
static int s_nStatusCount = 0;
StringCchPrintf(sz, _countof(sz),
TEXT("-->状态更新(%u)"), s_nStatusCount++);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
//显示作业对象的基本统计信息
JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION jobai;
g_job.QueryBasicAccountingInfo(&jobai);
StringCchPrintf(sz, _countof(sz),
TEXT("总时间:用户=%I64u,内核=%I64u ")
TEXT("Period时间:用户=%I64u,内核=%I64u"),
jobai.BasicInfo.TotalUserTime.QuadPart,
jobai.BasicInfo.TotalKernelTime.QuadPart);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
StringCchPrintf(sz, _countof(sz),
TEXT("页面错误=%u,总进程数=%u, ")
TEXT("活动进程数=%u,已终止的进程数=%u"),
jobai.BasicInfo.TotalPageFaultCount,
jobai.BasicInfo.TotalProcesses,
jobai.BasicInfo.ActiveProcesses,
jobai.BasicInfo.TotalTerminatedProcesses);
//显示IO统计信息
StringCchPrintf(sz, _countof(sz),
TEXT("读取=%I64u(i64u byte), ")
TEXT("写入=%I64u(i64u byte),其他=%I64u(I64u bytes"),
jobai.IoInfo.ReadOperationCount, jobai.IoInfo.ReadTransferCount,
jobai.IoInfo.WriteOperationCount, jobai.IoInfo.WriteTransferCount,
jobai.IoInfo.OtherOperationCount, jobai.IoInfo.OtherTransferCount
);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
//显示每个进程和作业的内存峰值
JOBOBJECT_EXTENDED_LIMIT_INFORMATION joeli;
g_job.QueryExtendedLimitInfo(&joeli);
StringCchPrintf(sz,_countof(sz),
TEXT("已使用内存峰值:进程=%I64u,作业=%I64u"),
(__int64)joeli.PeakProcessMemoryUsed,
(__int64)joeli.PeakJobMemoryUsed);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
//显示进程ID集
const int iNum = 50;
DWORD dwNumProcess = iNum;
DWORD dwProcessIDList[iNum];
g_job.QueryBasicProcessIdList(dwNumProcess, dwProcessIDList, &dwNumProcess);
StringCchPrintf(sz, _countof(sz), TEXT("进程ID集:%s"),
(dwNumProcess == 0) ? TEXT("none") : TEXT(""));
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
TCHAR szProcessName[MAX_PATH];
for (DWORD x = 0; x < dwNumProcess; x++)
{
GetProcessName(dwProcessIDList[x], szProcessName, _countof(szProcessName));
StringCchPrintf(sz, _countof(sz), TEXT(" %d - %s"),
dwProcessIDList[x], szProcessName);
ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
}
}
}
return 0;
}
void Dlg_ApplayLimits(HWND hwnd) {
const int nNanosecondsPerSecond = 1000000000;//1s=1000ms,1ms=1000us,1us=1000ns
const int nMillisecondsPerSecond = 1000;//1s=1000ms
const int nNanosecondsPerMillisecond =
nNanosecondsPerSecond / nMillisecondsPerSecond;
__int64 q;
SIZE_T s;
DWORD d;
BOOL f;
//设置作业的基本\扩展限制
JOBOBJECT_EXTENDED_LIMIT_INFORMATION joeli = {};
joeli.BasicLimitInformation.LimitFlags = 0;
//进程用户模式时间限制-f指出转换是否成功
q = GetDlgItemInt(hwnd, IDC_PERPROCESSUSERTIMELIMIT, &f, FALSE);
if (f)
{
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PROCESS_TIME;
joeli.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart =
q * nNanosecondsPerMillisecond / 100;//ns/ms
}
//作业用户模式时间限制-f住处转换是否成功
q = GetDlgItemInt(hwnd, IDC_PERJOBUSERTIMELIMIT, &f, FALSE);
if (f)
{
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_TIME;
joeli.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart =
q * nNanosecondsPerMillisecond / 100;//ns/ms
}
//最小工作集
s = GetDlgItemInt(hwnd, IDC_MINWORKINGSETSIZE, &f, FALSE);
if (f)
{
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_WORKINGSET;
joeli.BasicLimitInformation.MinimumWorkingSetSize = s * 1024 * 1025;
s = GetDlgItemInt(hwnd, IDC_MAXWORKINGSETSIZE, &f, FALSE);
if (f)
{
joeli.BasicLimitInformation.MaximumWorkingSetSize = s * 1024 * 1024;
}
else
{
joeli.BasicLimitInformation.LimitFlags &= ~JOB_OBJECT_LIMIT_WORKINGSET;
MessageBox(hwnd, TEXT("最小和最大工作集同时设置。\n"), NULL, MB_OK | MB_OKCANCEL);
}
}
//最大同时活动进程数
d = GetDlgItemInt(hwnd, IDC_ACTIVEPROCESSLIMIT, &f, TRUE);
if (f)
{
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
joeli.BasicLimitInformation.ActiveProcessLimit = d;
}
//进程亲缘性掩码:进程和线程的亲缘性(affinity)是指可以将进程或者是线程强制限制在可用的CPU子集上运行的特性
//使与作业关联的所有进程使用相同的处理器亲缘关系。Affinity成员包含附加信息 。
// 如果作业是嵌套的,则指定的处理器亲和性必须是父作业的有效亲和性的子集。
//如果指定的亲和性是父作业的亲和性的超集,则忽略它并使用父作业的亲和性。
s = GetDlgItemInt(hwnd, IDC_AFFINITYMASK, &f, FALSE);
if (f)
{
joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_AFFINITY;
joeli.BasicLimitInformation.ActiveProcessLimit = 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;
}
//SchedulingClass
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.JobMemoryLimit = 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);//调试版,f弹对话框
//设置UI限制
DWORD jobuir = JOB_OBJECT_UILIMIT_NONE;//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));
}
//
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndfocus, LPARAM lParam)
{
chSETDLGICONS(hwnd, IDI_JOBLAB);
//保存窗口句柄,以便在完成端口线程中可以访问到
g_hwnd = hwnd;
HWND hwndPriorityClass = GetDlgItem(hwnd, IDC_PRIORITYCLASS);
ComboBox_AddString(hwndPriorityClass, TEXT("No limit"));
ComboBox_AddString(hwndPriorityClass, TEXT("Idle"));
ComboBox_AddString(hwndPriorityClass, TEXT("Below normal"));
ComboBox_AddString(hwndPriorityClass, TEXT("Normal"));
ComboBox_AddString(hwndPriorityClass, TEXT("Above normal"));
ComboBox_AddString(hwndPriorityClass, TEXT("High"));
ComboBox_AddString(hwndPriorityClass, TEXT("Realtime"));
ComboBox_SetCurSel(hwndPriorityClass, 0); // Default to "No Limit"
HWND hwndSchedulingClass = GetDlgItem(hwnd, IDC_SCHEDULINGCLASS);
ComboBox_AddString(hwndSchedulingClass, TEXT("No limit"));
for (int n = 0; n <= 9; n++) {
TCHAR szSchedulingClass[2];
StringCchPrintf(szSchedulingClass, _countof(szSchedulingClass),
TEXT("%u"), n);
ComboBox_AddString(hwndSchedulingClass, szSchedulingClass);
}
ComboBox_SetCurSel(hwndSchedulingClass, 0); // Default to "No Limit"
SetTimer(hwnd, 1, 10000, NULL); // 10 second accounting update
return(TRUE);
}
///
void Dlg_ApplyLimits(HWND hwnd) {
const int nNanosecondsPerSecond = 1000000000;
const int nMillisecondsPerSecond = 1000;
const int nNanosecondsPerMillisecond =
nNanosecondsPerSecond / nMillisecondsPerSecond;
BOOL f;
__int64 q;
SIZE_T s;
DWORD d;
// 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);
}
moduel Job.h
/*
moduel Job.h
Notices:
*/
#pragma once
#include <malloc.h> //for _alloca;
class CJob
{
private:
HANDLE m_hJob;
public:
CJob(HANDLE hJob = NULL);
~CJob();
operator HANDLE() const { return(m_hJob); } //重载()运算符
//用于打开或创建一个作业对象
BOOL Create(PSECURITY_ATTRIBUTES psa = NULL, PCTSTR pszName = NULL);
BOOL Open(PCTSTR pszName, DWORD dwDesiredAccess, BOOL fInheritHandle = FALSE);
//用于操作作业对象的函数
BOOL AssignProcess(HANDLE hProcess);
BOOL Terminate(UINT uExitCode = 0);
//用于设置或限制作业对象
BOOL SetExtendedLimitInfo(PJOBOBJECT_EXTENDED_LIMIT_INFORMATION pjoeli, BOOL fPreserveJobTime = FALSE);
BOOL SetBasicUIRestrictions(DWORD fdwLimits);
BOOL GrantUserHandleAccess(HANDLE hUserOjb, BOOL fGrant = TRUE);//设置访问作业外用户对象能力
BOOL SetSecurityLimitInfo(PJOBOBJECT_SECURITY_LIMIT_INFORMATION pjosli);
//查询作业限制信息
BOOL QueryExtendedLimitInfo(PJOBOBJECT_EXTENDED_LIMIT_INFORMATION pjoeli);
BOOL QueryBasicUIRestrictions(PDWORD fdwRestrictions);
BOOL QuerySecurityLimitInfo(PJOBOBJECT_SECURITY_LIMIT_INFORMATION pjosli);
//查询作业状态信息
BOOL QueryBasicAccountingInfo(PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION pjobai);
BOOL QueryBasicProcessIdList(DWORD dwMaxProcess, PDWORD pdwProcessIdList,
PDWORD pdwProcessesReturned = NULL);
//设置或者查询作业的通知事件
BOOL AssociateCompletionPort(HANDLE hIOCP, ULONG_PTR CompKey);
BOOL QueryAssociatedCompletionPort(PJOBOBJECT_ASSOCIATE_COMPLETION_PORT pjoacp);
BOOL SetEndOfJobInfo(DWORD fdwEndOfJobInfo = JOB_OBJECT_TERMINATE_AT_END_OF_JOB);
BOOL QueryEndOfJobTimeInfo(PDWORD pfdwEndOfJobTimeInfo);
};
CJob::CJob(HANDLE hJob)
{
m_hJob = hJob;
}
CJob::~CJob()
{
if (NULL != m_hJob)
{
CloseHandle(m_hJob);
}
}
///
inline BOOL CJob::Create(PSECURITY_ATTRIBUTES psa, PCTSTR pszName) {
m_hJob = CreateJobObject(psa, pszName);
return (m_hJob != NULL);
}
///
inline BOOL CJob::Open(PCTSTR pszName, DWORD dwDesiredAccess, BOOL fInheritHandle /*= FALSE*/) {
m_hJob = OpenJobObject(dwDesiredAccess, fInheritHandle, pszName);
return (m_hJob != NULL);
}
///
inline BOOL CJob::AssignProcess(HANDLE hProcess) {
return(AssignProcessToJobObject(m_hJob, hProcess));
}
///
inline BOOL CJob::Terminate(UINT uExitCode /* = 0*/) {
return(TerminateJobObject(m_hJob, uExitCode));
}
///
inline BOOL CJob::SetExtendedLimitInfo(
PJOBOBJECT_EXTENDED_LIMIT_INFORMATION pjoeli, BOOL fPreserveJobTime /*= FALSE*/) {
if (fPreserveJobTime)
{
pjoeli->BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME;
}
//如果要保留作业事件信息,则JOB_OBJECT_LIMIT_JOB_TIME标志必须去掉
const DWORD fdwFlagTest =
(JOB_OBJECT_LIMIT_JOB_TIME | JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME);
if ((pjoeli->BasicLimitInformation.LimitFlags & fdwFlagTest) == fdwFlagTest);
//DebugBreak();//这两个标志是互斥的,单现在两者同时被设置了。
return (SetInformationJobObject(m_hJob, JobObjectExtendedLimitInformation,
pjoeli, sizeof(*pjoeli)));
}
///
inline BOOL CJob::SetBasicUIRestrictions(DWORD fdwLimits) {
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir = { fdwLimits };
return (SetInformationJobObject(m_hJob, JobObjectBasicUIRestrictions, &jobuir, sizeof(jobuir)));
}
///
inline BOOL CJob::GrantUserHandleAccess(HANDLE hUserOjb, BOOL fGrant /*= TRUE*/){
return UserHandleGrantAccess(hUserOjb, m_hJob, fGrant);
}
///
inline BOOL CJob::SetSecurityLimitInfo(PJOBOBJECT_SECURITY_LIMIT_INFORMATION pjosli) {
return (SetInformationJobObject(m_hJob,
JobObjectSecurityLimitInformation, pjosli, sizeof(*pjosli)));
}
///
inline BOOL CJob::QueryExtendedLimitInfo(PJOBOBJECT_EXTENDED_LIMIT_INFORMATION pjoeli) {
return (QueryInformationJobObject(m_hJob, JobObjectExtendedLimitInformation,
pjoeli, sizeof(*pjoeli), NULL));
}
///
inline BOOL CJob::QueryBasicUIRestrictions(PDWORD fdwRestrictions) {
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
BOOL fOk = QueryInformationJobObject(m_hJob, JobObjectBasicUIRestrictions,
&jobuir, sizeof(jobuir), NULL);
if (fOk)
{
*fdwRestrictions = jobuir.UIRestrictionsClass;
}
return (fOk);
}
///
inline BOOL CJob::QuerySecurityLimitInfo(PJOBOBJECT_SECURITY_LIMIT_INFORMATION pjosli) {
return (QueryInformationJobObject(m_hJob, JobObjectSecurityLimitInformation,
pjosli, sizeof(*pjosli), NULL));
}
inline BOOL CJob::QueryBasicAccountingInfo(PJOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION pjobai) {
return (QueryInformationJobObject(m_hJob,
JobObjectBasicAndIoAccountingInformation, pjobai, sizeof(*pjobai), NULL));
}
///
inline BOOL CJob::QueryBasicProcessIdList(DWORD dwMaxProcess, PDWORD pdwProcessIdList,
PDWORD pdwProcessesReturned /*= NULL*/) {
//计算所需的控件大小
DWORD cb = sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) + (sizeof(DWORD) * (dwMaxProcess - 1));
//从栈上分匹配内存(注意,不是堆,所有无需释放
PJOBOBJECT_BASIC_PROCESS_ID_LIST pjobpil =
(PJOBOBJECT_BASIC_PROCESS_ID_LIST)_alloca(cb);
BOOL fOk = (pjobpil != NULL);
if (fOk)
{
//告知函数,我们分配的最大控件大小
pjobpil->NumberOfProcessIdsInList = dwMaxProcess;
//请求返回 当前进程集ID
fOk = QueryInformationJobObject(m_hJob,
JobObjectBasicProcessIdList, pjobpil, cb, NULL);
if (fOk)
{
//得到信息,并返回给调用者
if (pdwProcessesReturned != NULL)
{
*pdwProcessesReturned = pjobpil->NumberOfProcessIdsInList;
CopyMemory(pdwProcessesReturned, pjobpil,
sizeof(DWORD) * pjobpil->NumberOfProcessIdsInList);
}
}
}
return fOk;
}
///
inline BOOL CJob::AssociateCompletionPort(HANDLE hIOCP, ULONG_PTR CompKey) {
JOBOBJECT_ASSOCIATE_COMPLETION_PORT joacp;
joacp.CompletionPort = hIOCP;
joacp.CompletionKey = (PVOID)CompKey;
return(SetInformationJobObject(m_hJob,
JobObjectAssociateCompletionPortInformation, &joacp, sizeof(joacp)));
}
///
inline BOOL CJob::QueryAssociatedCompletionPort(PJOBOBJECT_ASSOCIATE_COMPLETION_PORT pjoacp) {
return (QueryInformationJobObject(m_hJob,
JobObjectAssociateCompletionPortInformation, pjoacp, sizeof(*pjoacp), NULL));
}
///
inline BOOL CJob::SetEndOfJobInfo(DWORD fdwEndOfJobInfo /*= JOB_OBJECT_TERMINATE_AT_END_OF_JOB*/) {
JOBOBJECT_END_OF_JOB_TIME_INFORMATION joeojti = { fdwEndOfJobInfo };
return (SetInformationJobObject(m_hJob,
JobObjectEndOfJobTimeInformation, &joeojti, sizeof(joeojti)));
}
///
inline BOOL CJob::QueryEndOfJobTimeInfo(PDWORD pfdwEndOfJobTimeInfo) {
JOBOBJECT_END_OF_JOB_TIME_INFORMATION jobojti;
BOOL fOk = QueryInformationJobObject(m_hJob,
JobObjectEndOfJobTimeInformation, &jobojti, sizeof(jobojti), NULL);
if (fOk)
{
*pfdwEndOfJobTimeInfo = jobojti.EndOfJobTimeAction;
}
return (fOk);
}
标签:OBJECT,joeli,windows,hwnd,编程,作业,BasicLimitInformation,JOB,IDC
From: https://blog.csdn.net/zhyjhacker/article/details/141573104