Module: wine Branch: master Commit: ecd41d1de7461b9601e61ee387b24a9610e22b96 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ecd41d1de7461b9601e61ee387...
Author: Andrew Cook ariscop@gmail.com Date: Thu Apr 2 20:40:15 2015 +1100
server: Implement job limit flags.
---
dlls/kernel32/tests/process.c | 1 + dlls/ntdll/sync.c | 42 ++++++++++++++++++++++++++++++++++++++++-- include/wine/server_protocol.h | 19 ++++++++++++++++++- include/winnt.h | 4 ++++ server/process.c | 13 +++++++++++++ server/protocol.def | 7 +++++++ server/request.h | 5 +++++ server/trace.c | 9 +++++++++ 8 files changed, 97 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index fd47951..c991108 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -2387,6 +2387,7 @@ static void test_CompletionPort(void) port_info.CompletionKey = job; port_info.CompletionPort = port; ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info)); + todo_wine ok(ret, "SetInformationJobObject error %u\n", GetLastError());
create_process("wait", &pi); diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index ce1a635..fff38c9 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -634,8 +634,46 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c */ NTSTATUS WINAPI NtSetInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info, ULONG len ) { - FIXME( "stub: %p %u %p %u\n", handle, class, info, len ); - return STATUS_SUCCESS; + NTSTATUS status = STATUS_SUCCESS; + JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit; + ULONG info_size = sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION); + DWORD limit_flags = JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS; + + TRACE( "(%p, %u, %p, %u)\n", handle, class, info, len ); + + if (class >= MaxJobObjectInfoClass) + return STATUS_INVALID_PARAMETER; + + switch (class) + { + + case JobObjectExtendedLimitInformation: + info_size = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION); + limit_flags = JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS; + /* fallthrough */ + case JobObjectBasicLimitInformation: + if (len != info_size) + return STATUS_INVALID_PARAMETER; + + basic_limit = info; + if (basic_limit->LimitFlags & ~limit_flags) + return STATUS_INVALID_PARAMETER; + + SERVER_START_REQ( set_job_limits ) + { + req->handle = wine_server_obj_handle( handle ); + req->limit_flags = basic_limit->LimitFlags; + status = wine_server_call( req ); + } + SERVER_END_REQ; + break; + + default: + FIXME( "stub: %p %u %p %u\n", handle, class, info, len ); + return STATUS_NOT_IMPLEMENTED; + } + + return status; }
/****************************************************************************** diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 5a9f3ab..6e113e7 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5127,6 +5127,20 @@ struct process_in_job_reply };
+ +struct set_job_limits_request +{ + struct request_header __header; + obj_handle_t handle; + unsigned int limit_flags; + char __pad_20[4]; +}; +struct set_job_limits_reply +{ + struct reply_header __header; +}; + + enum request { REQ_new_process, @@ -5388,6 +5402,7 @@ enum request REQ_create_job, REQ_assign_job, REQ_process_in_job, + REQ_set_job_limits, REQ_NB_REQUESTS };
@@ -5654,6 +5669,7 @@ union generic_request struct create_job_request create_job_request; struct assign_job_request assign_job_request; struct process_in_job_request process_in_job_request; + struct set_job_limits_request set_job_limits_request; }; union generic_reply { @@ -5918,8 +5934,9 @@ union generic_reply struct create_job_reply create_job_reply; struct assign_job_reply assign_job_reply; struct process_in_job_reply process_in_job_reply; + struct set_job_limits_reply set_job_limits_reply; };
-#define SERVER_PROTOCOL_VERSION 463 +#define SERVER_PROTOCOL_VERSION 464
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winnt.h b/include/winnt.h index 4b06b2c..c2aa50e 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -5610,6 +5610,10 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION { #define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000 #define JOB_OBJECT_LIMIT_SUBSET_AFFINITY 0x00004000
+#define JOB_OBJECT_LIMIT_VALID_FLAGS 0x0007ffff +#define JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS 0x000000ff +#define JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS 0x00007fff + typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { RelationProcessorCore = 0, diff --git a/server/process.c b/server/process.c index 9534f90..84c6c82 100644 --- a/server/process.c +++ b/server/process.c @@ -146,6 +146,7 @@ struct job struct object obj; /* object header */ struct list process_list; /* list of all processes */ int num_processes; /* count of running processes */ + unsigned int limit_flags; /* limit flags */ };
static const struct object_ops job_ops = @@ -184,6 +185,7 @@ static struct job *create_job_object( struct directory *root, const struct unico SACL_SECURITY_INFORMATION ); list_init( &job->process_list ); job->num_processes = 0; + job->limit_flags = 0; } } return job; @@ -1506,3 +1508,14 @@ DECL_HANDLER(process_in_job) } release_object( process ); } + +/* update limits of the job object */ +DECL_HANDLER(set_job_limits) +{ + struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES ); + + if (!job) return; + + job->limit_flags = req->limit_flags; + release_object( job ); +} diff --git a/server/protocol.def b/server/protocol.def index b85adca..35de6ff 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3528,3 +3528,10 @@ enum coords_relative obj_handle_t job; /* handle to the job */ obj_handle_t process; /* handle to the process */ @END + + +/* Set limit flags on a job */ +@REQ(set_job_limits) + obj_handle_t handle; /* handle to the job */ + unsigned int limit_flags; /* new limit flags */ +@END diff --git a/server/request.h b/server/request.h index aef316a..d76ddea 100644 --- a/server/request.h +++ b/server/request.h @@ -365,6 +365,7 @@ DECL_HANDLER(set_suspend_context); DECL_HANDLER(create_job); DECL_HANDLER(assign_job); DECL_HANDLER(process_in_job); +DECL_HANDLER(set_job_limits);
#ifdef WANT_REQUEST_HANDLERS
@@ -630,6 +631,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_create_job, (req_handler)req_assign_job, (req_handler)req_process_in_job, + (req_handler)req_set_job_limits, };
C_ASSERT( sizeof(affinity_t) == 8 ); @@ -2221,6 +2223,9 @@ C_ASSERT( sizeof(struct assign_job_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct process_in_job_request, job) == 12 ); C_ASSERT( FIELD_OFFSET(struct process_in_job_request, process) == 16 ); C_ASSERT( sizeof(struct process_in_job_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct set_job_limits_request, handle) == 12 ); +C_ASSERT( FIELD_OFFSET(struct set_job_limits_request, limit_flags) == 16 ); +C_ASSERT( sizeof(struct set_job_limits_request) == 24 );
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/trace.c b/server/trace.c index cba15a3..3d8e349 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4119,6 +4119,12 @@ static void dump_process_in_job_request( const struct process_in_job_request *re fprintf( stderr, ", process=%04x", req->process ); }
+static void dump_set_job_limits_request( const struct set_job_limits_request *req ) +{ + fprintf( stderr, " handle=%04x", req->handle ); + fprintf( stderr, ", limit_flags=%08x", req->limit_flags ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -4379,6 +4385,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_job_request, (dump_func)dump_assign_job_request, (dump_func)dump_process_in_job_request, + (dump_func)dump_set_job_limits_request, };
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -4641,6 +4648,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_create_job_reply, NULL, NULL, + NULL, };
static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4903,6 +4911,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "create_job", "assign_job", "process_in_job", + "set_job_limits", };
static const struct