Windows 从服务调用时,带有作业\u对象\u UILIMIT\u句柄的AssignProcessToJobObject失败

Windows 从服务调用时,带有作业\u对象\u UILIMIT\u句柄的AssignProcessToJobObject失败,windows,security,Windows,Security,我有一个服务,我想从中为当前登录的用户创建一个受限进程。 如果我尝试将进程分配给设置了job\u object\u UILIMIT\u句柄的job对象,调用将失败,错误为\u ACCESS\u DENIED。如果我从作业设置中删除作业\对象\限制\句柄,一切正常。如果我在用户的上下文中执行此代码,它也可以工作 你知道这是怎么回事吗 多谢各位 编辑: 这是一个复制该问题的示例程序。程序启动与指定进程具有相同令牌的进程,并将该进程分配给作业对象 如果将进程作为系统启动(您可以创建一个可执行路径设置为

我有一个服务,我想从中为当前登录的用户创建一个受限进程。 如果我尝试将进程分配给设置了job\u object\u UILIMIT\u句柄的job对象,调用将失败,错误为\u ACCESS\u DENIED。如果我从作业设置中删除作业\对象\限制\句柄,一切正常。如果我在用户的上下文中执行此代码,它也可以工作

你知道这是怎么回事吗

多谢各位

编辑:

这是一个复制该问题的示例程序。程序启动与指定进程具有相同令牌的进程,并将该进程分配给作业对象

如果将进程作为系统启动(您可以创建一个可执行路径设置为cmd.exe的服务,然后切换到系统会话并从那里启动程序),请将源进程指定给任何用户进程,并将limit UI设置为true。调用AssignProcessToJobObject将失败,状态错误为\u ACCESS\u DENIED。如果LimitUI设置为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());
}
\define\u CRT\u SECURE\u NO\u警告
#包括“stdafx.h”
#包括
#包括
#包括
#包括
void main()
{   
handlejob=NULL;
STARTUPINFO STARTUPINFO={0};
进程信息processInformation={0};
JOBOBJECT_扩展_限制_信息eli={0};
JOBOBJECT_BASIC_UI_RESTRICTIONS bur={0};
handletoken=NULL;
句柄进程=NULL;
BOOL limitUI=TRUE;
DWORD源PID=0;
printf(“输入源pid:”);
scanf(“%u”和&sourcePid);
process=OpenProcess(process\u ALL\u ACCESS,FALSE,sourcePid);
if(进程==NULL)
{
printf(“OpenProcess失败\n”);
去清理;
}
if(!OpenProcessToken(进程、令牌\u所有访问权和令牌))
{
printf(“OpenProcessToken失败\n”);
去清理;
}
job=CreateJobObject(NULL,NULL);
如果(作业==NULL)
{
printf(“CreateJobObject失败\n”);
去清理;
}
eli.BasicLimitInformation.LimitFlags=作业\对象\限制\杀死\作业\关闭;
eli.BasicLimitInformation.PriorityClass=正常优先级等级;
if(!SetInformationJobObject(作业,JobObjectExtendedLimitInformation,&eli,sizeof(eli)))
{
printf(“SetInformationJobObject失败\n”);
去清理;
}
printf(“限制用户界面:”);
scanf(“%u”&limitUI);
if(limitUI)
{
bur.UIRestrictionsClass=作业\u对象\u UILIMIT\u句柄;
if(!SetInformationJobObject(作业,JobObjectBasicUIRestrictions,&bur,sizeof(bur)))
{
printf(“SetInformationJobObject失败\n”);
去清理;
}
}
如果(!CreateProcessAsUser(标记,L“c:\\windows\\system32\\notepad.exe”,L“”,则为NULL,NULL,FALSE,
创建(挂起、NULL、NULL和startupInfo以及processInformation))
{
printf(“CreateProcessAsUser失败\n”);
去清理;
}
if(!AssignProcessToJobObject(作业,processInformation.hpProcess))
{
printf(“AssignProcessToJobObject失败\n”);
去清理;
}
if(ResumeThread(processInformation.hThread)==(DWORD)-1)
{
printf(“恢复线程失败\n”);
去清理;
}
WaitForSingleObject(processInformation.hpProcess,无限);
清理:
if(processInformation.hThread!=NULL)
CloseHandle(processInformation.hThread);
if(processInformation.hProcess!=NULL)
CloseHandle(processInformation.hproces);
如果(作业!=NULL)
闭柄(工作);
if(令牌!=NULL)
闭合手柄(令牌);
if(进程!=NULL)
闭柄(过程);
printf(“上次错误:%d\n”,GetLastError());
}

Chris,你解决过这个问题吗?