我有一项服务,我想从中为当前登录的用户创建一个受限制的进程。 如果我尝试将进程分配给具有JOB_OBJECT_UILIMIT_HANDLES设置的作业对象,则调用将失败并显示ERROR_ACCESS_DENIED。如果我从作业设置中删除JOB_OBJECT_UILIMIT_HANDLES一切正常。如果我在用户的上下文中执行此代码,它也可以工作。
知道这是什么问题?
谢谢。
编辑:
这是一个重现问题的示例程序。程序启动一个与指定进程具有相同令牌的进程,并将该进程分配给作业对象。
如果以系统方式启动进程(可以创建服务,并将可执行文件路径设置为cmd.exe,然后可以切换到系统会话并从那里启动程序),请为任何用户进程指定源进程并将limit UI设置为true,对AssignProcessToJobObject的调用将失败,状态为ERROR_ACCESS_DENIED。如果将限制UI设置为false,则一切正常。
# define _CRT_SECURE_NO_WARNINGS
# include "stdafx.h"
# include <windows.h>
# include <stdio.h>
# include <assert.h>
# include <conio.h>
void main()
{
HANDLE job = NULL;
STARTUPINFO startupInfo = { 0 };
PROCESS_INFORMATION processInformation = { 0 };
JOBOBJECT_EXTENDED_LIMIT_INFORMATION eli = { 0 };
JOBOBJECT_BASIC_UI_RESTRICTIONS bur = { 0 };
HANDLE token = NULL;
HANDLE process = NULL;
BOOL limitUI = TRUE;
DWORD sourcePid = 0;
printf("Enter source pid: ");
scanf("%u", &sourcePid);
process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sourcePid);
if(process == NULL)
{
printf("OpenProcess failed\n");
goto cleanup;
}
if(!OpenProcessToken(process, TOKEN_ALL_ACCESS, &token))
{
printf("OpenProcessToken failed\n");
goto cleanup;
}
job = CreateJobObject(NULL, NULL);
if(job == NULL)
{
printf("CreateJobObject failed\n");
goto cleanup;
}
eli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
eli.BasicLimitInformation.PriorityClass = NORMAL_PRIORITY_CLASS;
if(!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &eli, sizeof(eli)))
{
printf("SetInformationJobObject failed\n");
goto cleanup;
}
printf("Limit UI: ");
scanf("%u", &limitUI);
if(limitUI)
{
bur.UIRestrictionsClass = JOB_OBJECT_UILIMIT_HANDLES;
if(!SetInformationJobObject(job, JobObjectBasicUIRestrictions, &bur, sizeof(bur)))
{
printf("SetInformationJobObject failed\n");
goto cleanup;
}
}
if(!CreateProcessAsUser(token, L"c:\\windows\\system32\\notepad.exe", L"", NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
{
printf("CreateProcessAsUser failed\n");
goto cleanup;
}
if(!AssignProcessToJobObject(job, processInformation.hProcess))
{
printf("AssignProcessToJobObject failed\n");
goto cleanup;
}
if(ResumeThread(processInformation.hThread) == (DWORD)-1)
{
printf("ResumeThread failed\n");
goto cleanup;
}
WaitForSingleObject(processInformation.hProcess, INFINITE);
cleanup:
if(processInformation.hThread != NULL)
CloseHandle(processInformation.hThread);
if(processInformation.hProcess != NULL)
CloseHandle(processInformation.hProcess);
if(job != NULL)
CloseHandle(job);
if(token != NULL)
CloseHandle(token);
if(process != NULL)
CloseHandle(process);
printf("Last Error: %d\n", GetLastError());
}