作业可以视为进程的集合,或者说沙箱,可以对这一系列进程进行统一的限制等操作
下面是windows核心编程中的StartRestrictedPrcess函数:
void StartRestrictedProcess()
{
BOOL bInJob = FALSE;
IsProcessInJob(GetCurrentProcess(), NULL, &bInJob);
if(bInJob)
{
MessageBox(NULL, TEXT("Process already in a job"), TEXT(""), MB_ICONINFORMATION | MB_OK);
return;
}
HANDLE hjob = CreateJobObject(NULL, TEXT("Wintellect_RestrictedProcessJob"));
JOBOBJECT_BASIC_LIMIT_INFORMATION jobli = {0};
jobli.PriorityClass = IDLE_PRIORITY_CLASS;
jobli.PerJobUserTimeLimit.QuadPart = 10000;
jobli.LimitFlags = JOB_OBJECT_LIMIT_JOB_TIME;
SetInformationJobObject(hjob, JobObjectBasicLimitInformation, &jobli, sizeof(jobli));
JOBOBJECT_BASIC_UI_RESTRICTIONS jobuir;
jobuir.UIRestrictionsClass = JOB_OBJECT_UILIMIT_NONE;
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_EXITWINDOWS;
jobuir.UIRestrictionsClass |= JOB_OBJECT_UILIMIT_HANDLES;
SetInformationJobObject(hjob, JobObjectBasicUIRestrictions, &jobuir, sizeof(jobuir));
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi;
TCHAR szCmdLine[8];
_tcscpy_s(szCmdLine, _countof(szCmdLine), TEXT("CMD"));
BOOL bResult = CreateProcess(NULL, szCmdLine, NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
AssignProcessToJobObject(hjob, pi.hProcess);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
HANDLE h[2];
h[0] = pi.hProcess;
h[1] = hjob;
DWORD dw = WaitForMultipleObjects(2, h, FALSE, INFINITE);
switch (dw - WAIT_OBJECT_0)
{
case 0:
break;
case 1:
break;
}
FILETIME CreationTime;
FILETIME ExitTime;
FILETIME KernelTime;
FILETIME UserTime;
TCHAR szInfo[MAX_PATH];
GetProcessTimes(pi.hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime);
StringCchPrintf(szInfo, _countof(szInfo), TEXT("Kernel = %u | User = %u\n"), KernelTime.dwLowDateTime / 10000, UserTime.dwLowDateTime /10000);
MessageBox(GetActiveWindow(), szInfo, TEXT("Restricted Process times"), MB_ICONINFORMATION | MB_OK);
CloseHandle(pi.hProcess);
CloseHandle(hjob);
}
这个函数包含了一个作业的创建、设置以及将进程加入作业的全部流程
从头开始分析这个函数:
首先是一个IsProcessInJob函数,可以验证一个进程是否在一个作业控制之下运行,函数原型如下:
BOOL WINAPI IsProcessInJob(
_In_ HANDLE ProcessHandle,
_In_opt_ HANDLE JobHandle,
_Out_ PBOOL Result
);
当第二个参数传入的是NULL时,会遍历所有现有作业
然后如果已经在作业里面了,程序会弹个对话框然后over
接下来是创建作业,使用CreateJobObject函数,原型如下:
HANDLE WINAPI CreateJobObject(
In_opt LPSECURITY_ATTRIBUTES lpJobAttributes,
In_opt LPCTSTR lpName
);
这个函数将返回所创建的作业的句柄,需要指定两个参数
第一个是出镜率极高的安全描述符,和以前一样没特殊需求NULL即可
第二个是命名,如果使用了OpenJobObject函数将会使用到
下一步是对作业中的进程进行限制,使用的函数为SetInformationJobObject,原型如下:
BOOL WINAPI SetInformationJobObject(
_In_ HANDLE hJob,
_In_ JOBOBJECTINFOCLASS JobObjectInfoClass,
_In_ LPVOID lpJobObjectInfo,
_In_ DWORD cbJobObjectInfoLength
);
参数需要注意的是中间两个,分别指定了限制的类型,具体内容
每一个限制类型又对应一个结构体,然后就往里面设置就好了,代码里面很清楚
这个好长= = 干脆把msdn扔上来好了https://msdn.microsoft.com/en-us/library/windows/desktop/ms686216(v=vs.85).aspx
再然后就是把进程加入作业里面了,使用AssignProcessToJobObject函数,这个就俩句柄,原型也懒得找了
如果要结束作业里面所有进程 调用TerminateJobObject即可
参数就一个句柄一个ExitCode