Rebase against upstream changes, partially removed patches for job objects (accepted upstream).

This commit is contained in:
Sebastian Lackner 2015-04-01 22:09:49 +02:00
parent 2aadb491e9
commit c6b84caa19
16 changed files with 608 additions and 992 deletions

1
debian/changelog vendored
View File

@ -22,6 +22,7 @@ wine-staging (1.7.40) UNRELEASED; urgency=low
* Removed patch to emulate 'mov Eb, Gb' instruction on x86 processor architecture (accepted upstream).
* Removed patches for Setup*Log() functions (accepted upstream).
* Removed tests for job objects (accepted upstream).
* Partially removed patches for job objects (accepted upstream).
-- Sebastian Lackner <sebastian@fds-team.de> Mon, 23 Mar 2015 16:12:20 +0100
wine-staging (1.7.39) unstable; urgency=low

View File

@ -1,46 +1,29 @@
From e2eaeb0bfc7411c74f1387e59c121f5cee6c013a Mon Sep 17 00:00:00 2001
From 41ffec5994a45a7f18cd77e98d8cf7bedecfd9a4 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 27 Mar 2015 15:32:44 +0100
Subject: Revert "server: Make directory DACL entries inheritable."
This reverts commit 3eb448cf33b6b6635bac4e06ea7fddd190e26450.
---
dlls/advapi32/tests/security.c | 12 ++++++------
server/file.c | 8 ++++----
2 files changed, 10 insertions(+), 10 deletions(-)
dlls/advapi32/tests/security.c | 2 +-
server/file.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index e3c1659..04a88ae 100644
index b19dbe8..a757c22 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3192,9 +3192,9 @@ static void test_CreateDirectoryA(void)
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
todo_wine ok(bret, "Current User ACE != Current User SID.\n");
- ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Current User ACE has unexpected flags (0x%x != 0x03)\n",
- ((ACE_HEADER *)ace)->AceFlags);
+ todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
+ "Current User ACE has unexpected flags (0x%x != 0x03)\n",
+ ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
ace->Mask);
}
@@ -3204,9 +3204,9 @@ static void test_CreateDirectoryA(void)
ok(bret, "Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
- ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
- ((ACE_HEADER *)ace)->AceFlags);
+ todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
+ "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
+ ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
ace->Mask);
@@ -3262,7 +3262,7 @@ static void test_CreateDirectoryA(void)
}
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
- 0x1f01ff, FALSE, TRUE, FALSE, __LINE__);
+ 0x1f01ff, FALSE, TRUE, TRUE, __LINE__);
LocalFree(pSD);
/* Test inheritance of ACLs in CreateFile without security descriptor */
diff --git a/server/file.c b/server/file.c
index f565f5a..abda2c3 100644
index aa5ff01..c8c880b 100644
--- a/server/file.c
+++ b/server/file.c
@@ -367,7 +367,7 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID

View File

@ -3873,20 +3873,18 @@ fi
# | server/object.h, server/process.c, server/process.h, server/protocol.def
# |
if test "$enable_server_JobObjects" -eq 1; then
patch_apply server-JobObjects/0001-server-Basic-implementation-of-job-objects.-rev-2.patch
patch_apply server-JobObjects/0001-server-Implement-remaining-wineserver-calls-for-job-.patch
patch_apply server-JobObjects/0002-server-Implement-completion-messages-for-job-objects.patch
patch_apply server-JobObjects/0003-server-Properly-track-handle-count-of-objects.patch
patch_apply server-JobObjects/0004-server-Implement-JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.patch
patch_apply server-JobObjects/0005-server-Support-NULL-job-handles-in-IsProcessInJob.patch
patch_apply server-JobObjects/0006-kernel32-tests-Add-tests-for-waiting-on-an-job-objec.patch
patch_apply server-JobObjects/0007-server-Implement-waiting-for-job-objects.patch
patch_apply server-JobObjects/0008-ntdll-Implement-NtQueryInformationJobObject-stub-fun.patch
patch_apply server-JobObjects/0005-kernel32-tests-Add-tests-for-waiting-on-an-job-objec.patch
patch_apply server-JobObjects/0006-server-Implement-waiting-for-job-objects.patch
patch_apply server-JobObjects/0007-ntdll-Implement-NtQueryInformationJobObject-stub-fun.patch
(
echo '+ { "Andrew Cook", "server: Basic implementation of job objects.", 2 },';
echo '+ { "Andrew Cook", "server: Implement remaining wineserver calls for job objects.", 1 },';
echo '+ { "Andrew Cook", "server: Implement completion messages for job objects.", 1 },';
echo '+ { "Andrew Cook", "server: Properly track handle count of objects.", 1 },';
echo '+ { "Andrew Cook", "server: Implement JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.", 1 },';
echo '+ { "Andrew Cook", "server: Support NULL job handles in IsProcessInJob.", 1 },';
echo '+ { "Sebastian Lackner", "kernel32/tests: Add tests for waiting on an job object.", 1 },';
echo '+ { "Sebastian Lackner", "server: Implement waiting for job objects.", 1 },';
echo '+ { "Sebastian Lackner", "ntdll: Implement NtQueryInformationJobObject stub function.", 1 },';

View File

@ -1,74 +1,36 @@
From 7c47d281a127ddb60ac73cdc373afb3f2a27e2cd Mon Sep 17 00:00:00 2001
From 2e6b68d04f4b74591fdbea0ef5fbea4879235c96 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 14:08:36 -0600
Subject: server: Inherit security attributes from parent directories on
creation. (try 7)
---
dlls/advapi32/tests/security.c | 10 ---
dlls/advapi32/tests/security.c | 4 +-
server/file.c | 137 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+), 10 deletions(-)
2 files changed, 139 insertions(+), 2 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 5209c13..e78e5f6 100644
index a530a3f..ae9ec99 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3234,7 +3234,6 @@ static void test_CreateDirectoryA(void)
@@ -3278,7 +3278,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
ok(bret, "GetAclInformation failed\n");
- todo_wine
ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
acl_size.AceCount);
if (acl_size.AceCount > 0)
@@ -3242,9 +3241,7 @@ static void test_CreateDirectoryA(void)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Inherited Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
- todo_wine
ok(bret, "Inherited Current User ACE != Current User SID.\n");
- todo_wine
ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
"Inherited Current User ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff,
@@ -3255,9 +3252,7 @@ static void test_CreateDirectoryA(void)
bret = pGetAce(pDacl, 1, (VOID **)&ace);
ok(bret, "Inherited Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
- todo_wine
ok(bret, "Inherited Administators Group ACE != Administators Group SID.\n");
- todo_wine
ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
"Inherited Administators Group ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff,
@@ -3290,7 +3285,6 @@ static void test_CreateDirectoryA(void)
@@ -3352,7 +3352,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
ok(bret, "GetAclInformation failed\n");
- todo_wine
ok(acl_size.AceCount == 2, "GetAclInformation returned unexpected entry count (%d != 2).\n",
acl_size.AceCount);
if (acl_size.AceCount > 0)
@@ -3298,9 +3292,7 @@ static void test_CreateDirectoryA(void)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Inherited Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
- todo_wine
ok(bret, "Inherited Current User ACE != Current User SID.\n");
- todo_wine
ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
"Inherited Current User ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff,
@@ -3311,9 +3303,7 @@ static void test_CreateDirectoryA(void)
bret = pGetAce(pDacl, 1, (VOID **)&ace);
ok(bret, "Inherited Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
- todo_wine
ok(bret, "Inherited Administators Group ACE != Administators Group SID.\n");
- todo_wine
ok(((ACE_HEADER *)ace)->AceFlags == INHERITED_ACE,
"Inherited Administators Group ACE has unexpected flags (0x%x != 0x10)\n", ((ACE_HEADER *)ace)->AceFlags);
ok(ace->Mask == 0x1f01ff,
diff --git a/server/file.c b/server/file.c
index b6435d1..43be63b 100644
--- a/server/file.c

View File

@ -1,680 +0,0 @@
From fdec43a9ec165284f52d8ecd734abd6e2fe93d90 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 12:25:23 +1100
Subject: server: Basic implementation of job objects. (rev 2)
This patch includes a (hopefully) complete implementation of process
tracking in job objects, but no limits or events outside of those.
This does not implement nested jobs as found in windows 8.
Changes by Sebastian Lackner <sebastian@fds-team.de>:
* Only use a single list instead of two for active / all processes.
* Various cleanups to fit with the rest of the wineserver coding style.
Changes in revision 2:
* Fix a wineserver crash when terminated processes are added to a job.
---
dlls/kernel32/tests/process.c | 10 +-
dlls/ntdll/sync.c | 139 ++++++++++++++++++++---
include/winnt.h | 4 +
server/process.c | 259 ++++++++++++++++++++++++++++++++++++++++++
server/process.h | 3 +
server/protocol.def | 27 +++++
6 files changed, 420 insertions(+), 22 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 15ebd6e..6c2f86d 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2209,7 +2209,6 @@ static void test_IsProcessInJob(void)
out = FALSE;
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
- todo_wine
ok(out, "IsProcessInJob returned out=%u\n", out);
TerminateProcess(pi.hProcess, 0);
@@ -2220,7 +2219,6 @@ static void test_IsProcessInJob(void)
out = FALSE;
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
- todo_wine
ok(out, "IsProcessInJob returned out=%u\n", out);
CloseHandle(pi.hProcess);
@@ -2247,13 +2245,11 @@ static void test_TerminateJobObject(void)
ok(ret, "TerminateJobObject error %u\n", GetLastError());
dwret = WaitForSingleObject(pi.hProcess, 1000);
- todo_wine
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
ret = GetExitCodeProcess(pi.hProcess, &dwret);
ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
- todo_wine
ok(dwret == 123 || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
"wrong exitcode %u\n", dwret);
@@ -2268,9 +2264,7 @@ static void test_TerminateJobObject(void)
SetLastError(0xdeadbeef);
ret = pAssignProcessToJobObject(job, pi.hProcess);
- todo_wine
ok(!ret, "AssignProcessToJobObject unexpectedly succeeded\n");
- todo_wine
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
CloseHandle(pi.hProcess);
@@ -2381,6 +2375,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);
@@ -2478,7 +2473,6 @@ static void test_jobInheritance(HANDLE job)
out = FALSE;
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
- todo_wine
ok(out, "IsProcessInJob returned out=%u\n", out);
dwret = WaitForSingleObject(pi.hProcess, 1000);
@@ -2506,9 +2500,7 @@ static void test_BreakawayOk(HANDLE job)
snprintf(buffer, MAX_PATH, "\"%s\" tests/process.c %s", selfname, "exit");
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
- todo_wine
ok(!ret, "CreateProcessA expected failure\n");
- todo_wine
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
if (ret)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 7d44e60..a0b8c15 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -56,6 +56,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
+#include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -565,9 +566,36 @@ NTSTATUS WINAPI NtQueryMutant(IN HANDLE handle,
*/
NTSTATUS WINAPI NtCreateJobObject( PHANDLE handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
{
- FIXME( "stub: %p %x %s\n", handle, access, attr ? debugstr_us(attr->ObjectName) : "" );
- *handle = (HANDLE)0xdead;
- return STATUS_SUCCESS;
+ DWORD len = attr && attr->ObjectName ? attr->ObjectName->Length : 0;
+ NTSTATUS ret;
+ struct security_descriptor *sd = NULL;
+ struct object_attributes objattr;
+
+ if (len >= MAX_PATH * sizeof(WCHAR)) return STATUS_NAME_TOO_LONG;
+
+ objattr.rootdir = wine_server_obj_handle( attr ? attr->RootDirectory : 0 );
+ objattr.sd_len = 0;
+ objattr.name_len = len;
+ if (attr)
+ {
+ ret = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
+ if (ret != STATUS_SUCCESS) return ret;
+ }
+
+ SERVER_START_REQ( create_job )
+ {
+ req->access = access;
+ req->attributes = attr ? attr->Attributes : 0;
+ wine_server_add_data( req, &objattr, sizeof(objattr) );
+ if (objattr.sd_len) wine_server_add_data( req, sd, objattr.sd_len );
+ if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
+ ret = wine_server_call( req );
+ *handle = wine_server_ptr_handle( reply->handle );
+ }
+ SERVER_END_REQ;
+
+ NTDLL_free_struct_sd( sd );
+ return ret;
}
/******************************************************************************
@@ -586,8 +614,19 @@ NTSTATUS WINAPI NtOpenJobObject( PHANDLE handle, ACCESS_MASK access, const OBJEC
*/
NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
{
- FIXME( "stub: %p %x\n", handle, status );
- return STATUS_SUCCESS;
+ NTSTATUS ret;
+
+ TRACE( "(%p, %d)\n", handle, status );
+
+ SERVER_START_REQ( terminate_job )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->status = status;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return ret;
}
/******************************************************************************
@@ -597,8 +636,17 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
- FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
- return STATUS_NOT_IMPLEMENTED;
+ TRACE( "%p %u %p %u %p\n", handle, class, info, len, ret_len );
+
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+ default:
+ FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
+ return STATUS_NOT_IMPLEMENTED;
+ }
}
/******************************************************************************
@@ -607,8 +655,51 @@ 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;
+ JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TRACE( "(%p, %u, %p, %u)\n", handle, class, info, len );
+
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+
+ case JobObjectExtendedLimitInformation:
+ if (len != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
+
+ basic_limit = &(((JOBOBJECT_EXTENDED_LIMIT_INFORMATION *)info)->BasicLimitInformation);
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS)
+ return STATUS_INVALID_PARAMETER;
+
+ goto set_basic_limits;
+
+ case JobObjectBasicLimitInformation:
+ if (len != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
+
+ basic_limit = info;
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS)
+ return STATUS_INVALID_PARAMETER;
+
+ set_basic_limits:
+ SERVER_START_REQ( job_set_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;
}
/******************************************************************************
@@ -617,8 +708,19 @@ NTSTATUS WINAPI NtSetInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS cla
*/
NTSTATUS WINAPI NtIsProcessInJob( HANDLE process, HANDLE job )
{
- FIXME( "stub: %p %p\n", process, job );
- return STATUS_PROCESS_NOT_IN_JOB;
+ NTSTATUS status;
+
+ TRACE( "(%p %p)\n", job, process );
+
+ SERVER_START_REQ( process_in_job )
+ {
+ req->process_handle = wine_server_obj_handle( process );
+ req->job_handle = wine_server_obj_handle( job );
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return status;
}
/******************************************************************************
@@ -627,8 +729,19 @@ NTSTATUS WINAPI NtIsProcessInJob( HANDLE process, HANDLE job )
*/
NTSTATUS WINAPI NtAssignProcessToJobObject( HANDLE job, HANDLE process )
{
- FIXME( "stub: %p %p\n", job, process );
- return STATUS_SUCCESS;
+ NTSTATUS status;
+
+ TRACE( "(%p %p)\n", job, process );
+
+ SERVER_START_REQ( job_assign )
+ {
+ req->job_handle = wine_server_obj_handle( job );
+ req->process_handle = wine_server_obj_handle( process );
+ status = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return status;
}
/*
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 0712a5b..6384203 100644
--- a/server/process.c
+++ b/server/process.c
@@ -65,6 +65,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access
static struct security_descriptor *process_get_sd( struct object *obj );
static void process_poll_event( struct fd *fd, int event );
static void process_destroy( struct object *obj );
+static void terminate_process( struct process *process, struct thread *skip, int exit_code );
static const struct object_ops process_ops =
{
@@ -134,6 +135,157 @@ static const struct object_ops startup_info_ops =
startup_info_destroy /* destroy */
};
+/* job object */
+
+static void job_dump( struct object *obj, int verbose );
+static struct object_type *job_get_type( struct object *obj );
+static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
+static unsigned int job_map_access( struct object *obj, unsigned int access );
+static void job_destroy( struct object *obj );
+
+struct job
+{
+ struct object obj; /* object header */
+ struct list process_list; /* list of all processes */
+ int num_processes; /* count of running processes */
+ int limit_flags; /* limit flags */
+};
+
+static const struct object_ops job_ops =
+{
+ sizeof(struct job), /* size */
+ job_dump, /* dump */
+ job_get_type, /* get_type */
+ add_queue, /* add_queue */
+ remove_queue, /* remove_queue */
+ job_signaled, /* signaled */
+ no_satisfied, /* satisfied */
+ no_signal, /* signal */
+ no_get_fd, /* get_fd */
+ job_map_access, /* map_access */
+ default_get_sd, /* get_sd */
+ default_set_sd, /* set_sd */
+ no_lookup_name, /* lookup_name */
+ no_open_file, /* open_file */
+ no_close_handle, /* close_handle */
+ job_destroy /* destroy */
+};
+
+static struct job *create_job_object( struct directory *root, const struct unicode_str *name,
+ unsigned int attr, const struct security_descriptor *sd )
+{
+ struct job *job;
+
+ if ((job = create_named_object_dir( root, name, attr, &job_ops )))
+ {
+ if (get_error() != STATUS_OBJECT_NAME_EXISTS)
+ {
+ /* initialize it if it didn't already exist */
+ if (sd) default_set_sd( &job->obj, sd, OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION |
+ SACL_SECURITY_INFORMATION );
+ list_init( &job->process_list );
+ job->num_processes = 0;
+ job->limit_flags = 0;
+ }
+ }
+ return job;
+}
+
+static struct job *get_job_obj( struct process *process, obj_handle_t handle, unsigned int access )
+{
+ return (struct job *)get_handle_obj( process, handle, access, &job_ops );
+}
+
+static struct object_type *job_get_type( struct object *obj )
+{
+ static const WCHAR name[] = {'J','o','b'};
+ static const struct unicode_str str = { name, sizeof(name) };
+ return get_object_type( &str );
+};
+
+static unsigned int job_map_access( struct object *obj, unsigned int access )
+{
+ if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ;
+ if (access & GENERIC_WRITE) access |= STANDARD_RIGHTS_WRITE;
+ if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
+ if (access & GENERIC_ALL) access |= JOB_OBJECT_ALL_ACCESS;
+ return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
+}
+
+static int add_job_process( struct job *job, struct process *process )
+{
+ assert( job->obj.ops == &job_ops );
+
+ if (!process->running_threads)
+ {
+ set_error( STATUS_PROCESS_IS_TERMINATING );
+ return 0;
+ }
+ if (process->job)
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ return 0;
+ }
+
+ process->job = (struct job *)grab_object( job );
+ list_add_tail( &job->process_list, &process->job_entry );
+ job->num_processes++;
+
+ return 1;
+}
+
+/* called when a process has terminated, allow one additional process */
+static void release_job_process( struct process *process )
+{
+ struct job *job = process->job;
+
+ if (!job)
+ return;
+
+ assert( job->obj.ops == &job_ops );
+ assert( job->num_processes );
+ job->num_processes--;
+}
+
+static void terminate_job( struct job *job, int exit_code )
+{
+ for (;;) /* restart from the beginning of the list every time */
+ {
+ struct process *process;
+
+ /* find the first process associcated with this job and still running */
+ LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
+ {
+ if (process->running_threads) break;
+ }
+ if (&process->job_entry == &job->process_list) break; /* no process found */
+ assert( process->job == job );
+ terminate_process( process, NULL, exit_code );
+ }
+}
+
+static void job_destroy( struct object *obj )
+{
+ struct job *job = (struct job *)obj;
+ assert( obj->ops == &job_ops );
+
+ assert( !job->num_processes );
+ assert( list_empty(&job->process_list) );
+}
+
+static void job_dump( struct object *obj, int verbose )
+{
+ struct job *job = (struct job *)obj;
+ assert( obj->ops == &job_ops );
+ fprintf( stderr, "Job processes=%d\n", list_count(&job->process_list) );
+}
+
+static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
+{
+ return 0;
+}
struct ptid_entry
{
@@ -327,6 +479,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->debug_children = 0;
process->is_terminating = 0;
process->is_terminated = 0;
+ process->job = NULL;
process->console = NULL;
process->startup_state = STARTUP_IN_PROGRESS;
process->startup_info = NULL;
@@ -425,6 +578,12 @@ static void process_destroy( struct object *obj )
close_process_handles( process );
set_process_startup_state( process, STARTUP_ABORTED );
+
+ if (process->job)
+ {
+ list_remove( &process->job_entry );
+ release_object( process->job );
+ }
if (process->console) release_object( process->console );
if (process->parent) release_object( process->parent );
if (process->msg_fd) release_object( process->msg_fd );
@@ -709,6 +868,7 @@ static void process_killed( struct process *process )
remove_process_locks( process );
set_process_startup_state( process, STARTUP_ABORTED );
finish_process_tracing( process );
+ release_job_process( process );
start_sigkill_timer( process );
wake_up( &process->obj, 0 );
}
@@ -954,6 +1114,14 @@ DECL_HANDLER(new_process)
return;
}
+ if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) &&
+ !(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ close( socket_fd );
+ return;
+ }
+
if (!req->info_size) /* create an orphaned process */
{
create_process( socket_fd, NULL, 0 );
@@ -1024,6 +1192,12 @@ DECL_HANDLER(new_process)
&& !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
process->startup_info = (struct startup_info *)grab_object( info );
+ if (parent->job && !((req->create_flags & CREATE_BREAKAWAY_FROM_JOB) ||
+ (parent->job->limit_flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
+ {
+ add_job_process( parent->job, process );
+ }
+
/* connect to the window station */
connect_process_winstation( process, current );
@@ -1361,3 +1535,88 @@ DECL_HANDLER(make_process_system)
shutdown_timeout = add_timeout_user( master_socket_timeout, server_shutdown_timeout, NULL );
}
}
+
+/* create a new job object */
+DECL_HANDLER(create_job)
+{
+ struct job *job;
+ struct unicode_str name;
+ struct directory *root = NULL;
+ const struct object_attributes *objattr = get_req_data();
+ const struct security_descriptor *sd;
+
+ if (!objattr_is_valid( objattr, get_req_data_size() )) return;
+
+ sd = objattr->sd_len ? (const struct security_descriptor *)(objattr + 1) : NULL;
+ objattr_get_name( objattr, &name );
+
+ if (objattr->rootdir && !(root = get_directory_obj( current->process, objattr->rootdir, 0 ))) return;
+
+ if ((job = create_job_object( root, &name, req->attributes, sd )))
+ {
+ if (get_error() == STATUS_OBJECT_NAME_EXISTS)
+ reply->handle = alloc_handle( current->process, job, req->access, req->attributes );
+ else
+ reply->handle = alloc_handle_no_access_check( current->process, job, req->access, req->attributes );
+ release_object( job );
+ }
+ if (root) release_object( root );
+}
+
+/* assign a job object to a process */
+DECL_HANDLER(job_assign)
+{
+ struct process *process;
+ struct job *job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS );
+
+ if (job)
+ {
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_SET_QUOTA | PROCESS_TERMINATE )))
+ {
+ add_job_process( job, process );
+ release_object(process);
+ }
+ release_object(job);
+ }
+}
+
+/* check if a process is associated with a job */
+DECL_HANDLER(process_in_job)
+{
+ struct process *process;
+ struct job *job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS );
+
+ if (job)
+ {
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_QUERY_INFORMATION )))
+ {
+ set_error( (process->job == job) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
+ release_object( process );
+ }
+ release_object(job);
+ }
+}
+
+/* terminate all processes associated with the job */
+DECL_HANDLER(terminate_job)
+{
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE );
+
+ if (job)
+ {
+ terminate_job( job, req->status );
+ release_object( job );
+ }
+}
+
+/* update limits of the job object */
+DECL_HANDLER(job_set_limits)
+{
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );
+
+ if (job)
+ {
+ job->limit_flags = req->limit_flags;
+ release_object( job );
+ }
+}
diff --git a/server/process.h b/server/process.h
index da6d3da..ae83b0e 100644
--- a/server/process.h
+++ b/server/process.h
@@ -26,6 +26,7 @@
struct atom_table;
struct handle_table;
struct startup_info;
+struct job;
/* process startup state */
enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
@@ -76,6 +77,8 @@ struct process
unsigned int debug_children:1;/* also debug all child processes */
unsigned int is_terminating:1;/* is process terminating? */
unsigned int is_terminated:1; /* is process terminated? */
+ struct job *job; /* job object ascoicated with this process */
+ struct list job_entry; /* list entry for job object */
struct list locks; /* list of file locks owned by the process */
struct list classes; /* window classes owned by the process */
struct console_input*console; /* console input */
diff --git a/server/protocol.def b/server/protocol.def
index a34dde9..655a9ac 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -682,6 +682,33 @@ struct rawinput_device
obj_handle_t thandle; /* thread handle (in the current process) */
@END
+@REQ(create_job)
+ unsigned int access; /* wanted access rights */
+ unsigned int attributes; /* object attributes */
+ VARARG(objattr,object_attributes); /* object attributes */
+@REPLY
+ obj_handle_t handle; /* handle to the job */
+@END
+
+@REQ(terminate_job)
+ obj_handle_t handle;
+ int status;
+@END
+
+@REQ(process_in_job)
+ obj_handle_t job_handle;
+ obj_handle_t process_handle;
+@END
+
+@REQ(job_assign)
+ obj_handle_t job_handle;
+ obj_handle_t process_handle;
+@END
+
+@REQ(job_set_limits)
+ obj_handle_t handle;
+ unsigned int limit_flags;
+@END
/* Retrieve information about a newly started process */
@REQ(get_new_process_info)
--
2.3.3

View File

@ -0,0 +1,334 @@
From f116e9e73f00bd6c65ebd087a1f7b23ceb9064a9 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 12:25:23 +1100
Subject: server: Implement remaining wineserver calls for job objects.
---
dlls/kernel32/tests/process.c | 6 +---
dlls/ntdll/sync.c | 76 +++++++++++++++++++++++++++++++++++++++----
include/winnt.h | 4 +++
server/process.c | 59 +++++++++++++++++++++++++++++++++
server/process.h | 1 +
server/protocol.def | 14 ++++++++
6 files changed, 149 insertions(+), 11 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 1add23d..8c9a6ef 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2269,13 +2269,11 @@ static void test_TerminateJobObject(void)
ok(ret, "TerminateJobObject error %u\n", GetLastError());
dwret = WaitForSingleObject(pi.hProcess, 1000);
- todo_wine
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
ret = GetExitCodeProcess(pi.hProcess, &dwret);
ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
- todo_wine
ok(dwret == 123 || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
"wrong exitcode %u\n", dwret);
@@ -2401,6 +2399,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);
@@ -2498,7 +2497,6 @@ static void test_jobInheritance(HANDLE job)
out = FALSE;
ret = pIsProcessInJob(pi.hProcess, job, &out);
ok(ret, "IsProcessInJob error %u\n", GetLastError());
- todo_wine
ok(out, "IsProcessInJob returned out=%u\n", out);
dwret = WaitForSingleObject(pi.hProcess, 1000);
@@ -2526,9 +2524,7 @@ static void test_BreakawayOk(HANDLE job)
snprintf(buffer, MAX_PATH, "\"%s\" tests/process.c %s", selfname, "exit");
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
- todo_wine
ok(!ret, "CreateProcessA expected failure\n");
- todo_wine
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
if (ret)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index ce1a635..e001e28 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -56,6 +56,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
+#include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -613,8 +614,19 @@ NTSTATUS WINAPI NtOpenJobObject( PHANDLE handle, ACCESS_MASK access, const OBJEC
*/
NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
{
- FIXME( "stub: %p %x\n", handle, status );
- return STATUS_SUCCESS;
+ NTSTATUS ret;
+
+ TRACE( "(%p, %d)\n", handle, status );
+
+ SERVER_START_REQ( terminate_job )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->status = status;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return ret;
}
/******************************************************************************
@@ -624,8 +636,17 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
- FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
- return STATUS_NOT_IMPLEMENTED;
+ TRACE( "%p %u %p %u %p\n", handle, class, info, len, ret_len );
+
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+ default:
+ FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
+ return STATUS_NOT_IMPLEMENTED;
+ }
}
/******************************************************************************
@@ -634,8 +655,51 @@ 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;
+ JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ TRACE( "(%p, %u, %p, %u)\n", handle, class, info, len );
+
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+
+ case JobObjectExtendedLimitInformation:
+ if (len != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
+
+ basic_limit = &(((JOBOBJECT_EXTENDED_LIMIT_INFORMATION *)info)->BasicLimitInformation);
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS)
+ return STATUS_INVALID_PARAMETER;
+
+ goto set_basic_limits;
+
+ case JobObjectBasicLimitInformation:
+ if (len != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
+
+ basic_limit = info;
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS)
+ return STATUS_INVALID_PARAMETER;
+
+ set_basic_limits:
+ 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/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 f9738c0..a1ab8c7 100644
--- a/server/process.c
+++ b/server/process.c
@@ -65,6 +65,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access
static struct security_descriptor *process_get_sd( struct object *obj );
static void process_poll_event( struct fd *fd, int event );
static void process_destroy( struct object *obj );
+static void terminate_process( struct process *process, struct thread *skip, int exit_code );
static const struct object_ops process_ops =
{
@@ -147,6 +148,7 @@ struct job
struct object obj; /* object header */
struct list process_list; /* list of all processes */
int num_processes; /* count of running processes */
+ int limit_flags; /* limit flags */
};
static const struct object_ops job_ops =
@@ -185,6 +187,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;
@@ -223,6 +226,7 @@ static void add_job_process( struct job *job, struct process *process )
set_error( STATUS_ACCESS_DENIED );
return;
}
+
process->job = (struct job *)grab_object( job );
list_add_tail( &job->process_list, &process->job_entry );
job->num_processes++;
@@ -239,6 +243,23 @@ static void release_job_process( struct process *process )
job->num_processes--;
}
+static void terminate_job( struct job *job, int exit_code )
+{
+ for (;;) /* restart from the beginning of the list every time */
+ {
+ struct process *process;
+
+ /* find the first process associcated with this job and still running */
+ LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
+ {
+ if (process->running_threads) break;
+ }
+ if (&process->job_entry == &job->process_list) break; /* no process found */
+ assert( process->job == job );
+ terminate_process( process, NULL, exit_code );
+ }
+}
+
static void job_destroy( struct object *obj )
{
struct job *job = (struct job *)obj;
@@ -1087,6 +1108,14 @@ DECL_HANDLER(new_process)
return;
}
+ if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) &&
+ !(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ close( socket_fd );
+ return;
+ }
+
if (!req->info_size) /* create an orphaned process */
{
create_process( socket_fd, NULL, 0 );
@@ -1157,6 +1186,12 @@ DECL_HANDLER(new_process)
&& !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
process->startup_info = (struct startup_info *)grab_object( info );
+ if (parent->job && !((req->create_flags & CREATE_BREAKAWAY_FROM_JOB) ||
+ (parent->job->limit_flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
+ {
+ add_job_process( parent->job, process );
+ }
+
/* connect to the window station */
connect_process_winstation( process, current );
@@ -1559,3 +1594,27 @@ DECL_HANDLER(process_in_job)
}
release_object( process );
}
+
+/* terminate all processes associated with the job */
+DECL_HANDLER(terminate_job)
+{
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE );
+
+ if (job)
+ {
+ terminate_job( job, req->status );
+ release_object( job );
+ }
+}
+
+/* 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)
+ {
+ job->limit_flags = req->limit_flags;
+ release_object( job );
+ }
+}
diff --git a/server/process.h b/server/process.h
index 0cf9514..ae83b0e 100644
--- a/server/process.h
+++ b/server/process.h
@@ -26,6 +26,7 @@
struct atom_table;
struct handle_table;
struct startup_info;
+struct job;
/* process startup state */
enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
diff --git a/server/protocol.def b/server/protocol.def
index b85adca..0077aa4 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3528,3 +3528,17 @@ enum coords_relative
obj_handle_t job; /* handle to the job */
obj_handle_t process; /* handle to the process */
@END
+
+
+/* Terminate all processes associated with the job */
+@REQ(terminate_job)
+ obj_handle_t handle; /* handle to the job */
+ int status; /* exitcode of the process */
+@END
+
+
+/* Update limits of the job object */
+@REQ(set_job_limits)
+ obj_handle_t handle; /* handle to the job */
+ unsigned int limit_flags; /* limit flags */
+@END
--
2.3.3

View File

@ -1,4 +1,4 @@
From 2dc3e01bbb999ff93918375bdc5071eb9439a011 Mon Sep 17 00:00:00 2001
From 3babb8a2681bd530008b0d268cde0b5788177097 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 13:02:36 +1100
Subject: server: Implement completion messages for job objects.
@ -10,15 +10,15 @@ coding style by Sebastian Lackner <sebastian@fds-team.de>.
---
dlls/kernel32/tests/process.c | 4 ----
dlls/ntdll/sync.c | 15 +++++++++++++++
server/process.c | 44 +++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 6 ++++++
4 files changed, 65 insertions(+), 4 deletions(-)
server/process.c | 45 +++++++++++++++++++++++++++++++++++++++++++
server/protocol.def | 8 ++++++++
4 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 6c2f86d..911fad7 100644
index 8c9a6ef..a86e331 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2375,7 +2375,6 @@ static void test_CompletionPort(void)
@@ -2399,7 +2399,6 @@ static void test_CompletionPort(void)
port_info.CompletionKey = job;
port_info.CompletionPort = port;
ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
@ -26,7 +26,7 @@ index 6c2f86d..911fad7 100644
ok(ret, "SetInformationJobObject error %u\n", GetLastError());
create_process("wait", &pi);
@@ -2383,16 +2382,13 @@ static void test_CompletionPort(void)
@@ -2407,16 +2406,13 @@ static void test_CompletionPort(void)
ret = pAssignProcessToJobObject(job, pi.hProcess);
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
@ -44,7 +44,7 @@ index 6c2f86d..911fad7 100644
CloseHandle(pi.hProcess);
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index a0b8c15..c754df6 100644
index e001e28..87ff3e0 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -694,6 +694,21 @@ NTSTATUS WINAPI NtSetInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS cla
@ -55,12 +55,12 @@ index a0b8c15..c754df6 100644
+ if (len != sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT))
+ return STATUS_INVALID_PARAMETER;
+
+ SERVER_START_REQ( job_set_completion )
+ SERVER_START_REQ( set_job_completion )
+ {
+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT *port_info = info;
+ req->handle = wine_server_obj_handle( handle );
+ req->port = wine_server_obj_handle( port_info->CompletionPort );
+ req->key = wine_server_client_ptr( port_info->CompletionKey );
+ req->port = wine_server_obj_handle( port_info->CompletionPort );
+ req->key = wine_server_client_ptr( port_info->CompletionKey );
+ status = wine_server_call(req);
+ }
+ SERVER_END_REQ;
@ -70,7 +70,7 @@ index a0b8c15..c754df6 100644
FIXME( "stub: %p %u %p %u\n", handle, class, info, len );
return STATUS_NOT_IMPLEMENTED;
diff --git a/server/process.c b/server/process.c
index 6384203..e02b7af 100644
index a1ab8c7..10193ef 100644
--- a/server/process.c
+++ b/server/process.c
@@ -149,6 +149,9 @@ struct job
@ -103,19 +103,20 @@ index 6384203..e02b7af 100644
+ add_completion(job->completion_port, job->completion_key, pid, STATUS_SUCCESS, msg);
+}
+
static int add_job_process( struct job *job, struct process *process )
static void add_job_process( struct job *job, struct process *process )
{
assert( job->obj.ops == &job_ops );
@@ -233,6 +245,7 @@ static int add_job_process( struct job *job, struct process *process )
if (!process->running_threads)
@@ -230,6 +242,8 @@ static void add_job_process( struct job *job, struct process *process )
process->job = (struct job *)grab_object( job );
list_add_tail( &job->process_list, &process->job_entry );
job->num_processes++;
+
+ add_job_completion( job, JOB_OBJECT_MSG_NEW_PROCESS, get_process_id(process) );
return 1;
}
@@ -247,10 +260,20 @@ static void release_job_process( struct process *process )
assert( job->obj.ops == &job_ops );
/* called when a process has terminated, allow one additional process */
@@ -241,10 +255,20 @@ static void release_job_process( struct process *process )
assert( job->num_processes );
job->num_processes--;
+
@ -135,7 +136,7 @@ index 6384203..e02b7af 100644
for (;;) /* restart from the beginning of the list every time */
{
struct process *process;
@@ -264,6 +287,8 @@ static void terminate_job( struct job *job, int exit_code )
@@ -258,6 +282,8 @@ static void terminate_job( struct job *job, int exit_code )
assert( process->job == job );
terminate_process( process, NULL, exit_code );
}
@ -144,7 +145,7 @@ index 6384203..e02b7af 100644
}
static void job_destroy( struct object *obj )
@@ -273,6 +298,9 @@ static void job_destroy( struct object *obj )
@@ -267,6 +293,9 @@ static void job_destroy( struct object *obj )
assert( !job->num_processes );
assert( list_empty(&job->process_list) );
@ -154,12 +155,12 @@ index 6384203..e02b7af 100644
}
static void job_dump( struct object *obj, int verbose )
@@ -1620,3 +1648,19 @@ DECL_HANDLER(job_set_limits)
@@ -1618,3 +1647,19 @@ DECL_HANDLER(set_job_limits)
release_object( job );
}
}
+
+DECL_HANDLER(job_set_completion)
+DECL_HANDLER(set_job_completion)
+{
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );
+
@ -175,22 +176,21 @@ index 6384203..e02b7af 100644
+ }
+}
diff --git a/server/protocol.def b/server/protocol.def
index 655a9ac..deaaa7b 100644
index 0077aa4..c88c970 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -710,6 +710,12 @@ struct rawinput_device
unsigned int limit_flags;
@@ -3542,3 +3542,11 @@ enum coords_relative
obj_handle_t handle; /* handle to the job */
unsigned int limit_flags; /* limit flags */
@END
+@REQ(job_set_completion)
+ obj_handle_t handle;
+ obj_handle_t port;
+ client_ptr_t key;
+@END
+
/* Retrieve information about a newly started process */
@REQ(get_new_process_info)
obj_handle_t info; /* info handle returned from new_process_request */
+
+/* Set a job completion port/key */
+@REQ(set_job_completion)
+ obj_handle_t handle; /* handle to the job */
+ obj_handle_t port; /* completion port */
+ client_ptr_t key; /* completion key */
+@END
--
2.3.3

View File

@ -1,4 +1,4 @@
From 126ffd832a29072552150c335b4f3c945bce5bbe Mon Sep 17 00:00:00 2001
From 7d8fc002a6adf69f64f635d37b19ddc892283f03 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 10:51:16 +1100
Subject: server: Properly track handle count of objects.
@ -12,10 +12,10 @@ Subject: server: Properly track handle count of objects.
5 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c
index 47a2614..05f18c0 100644
index f5f75c6..b337444 100644
--- a/dlls/ntdll/om.c
+++ b/dlls/ntdll/om.c
@@ -78,7 +78,7 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
@@ -77,7 +77,7 @@ NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
memset( p, 0, sizeof(*p) );
p->GrantedAccess = reply->access;
p->PointerCount = reply->ref_count;
@ -128,10 +128,10 @@ index 3817c75..978baeb 100644
struct list wait_queue;
struct object_name *name;
diff --git a/server/protocol.def b/server/protocol.def
index 126c2a7..2c5af48 100644
index c88c970..fdebf29 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3292,6 +3292,7 @@ enum coords_relative
@@ -3269,6 +3269,7 @@ enum coords_relative
@REPLY
unsigned int access; /* granted access mask */
unsigned int ref_count; /* object ref count */
@ -140,5 +140,5 @@ index 126c2a7..2c5af48 100644
VARARG(name,unicode_str); /* object name */
@END
--
2.3.0
2.3.3

View File

@ -1,4 +1,4 @@
From dedf23f9a61a8ef5bcc23a229646d1244e859546 Mon Sep 17 00:00:00 2001
From e70c80c4f78ac6306629d79f86d8c1c5439aaa17 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 13:10:41 +1100
Subject: server: Implement JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
@ -9,10 +9,10 @@ Subject: server: Implement JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 911fad7..66e0863 100644
index a86e331..4f51cea 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2425,7 +2425,6 @@ static void test_KillOnJobClose(void)
@@ -2449,7 +2449,6 @@ static void test_KillOnJobClose(void)
CloseHandle(job);
dwret = WaitForSingleObject(pi.hProcess, 1000);
@ -21,7 +21,7 @@ index 911fad7..66e0863 100644
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
diff --git a/server/process.c b/server/process.c
index e02b7af..f36548e 100644
index 10193ef..89c029e 100644
--- a/server/process.c
+++ b/server/process.c
@@ -141,6 +141,7 @@ static void job_dump( struct object *obj, int verbose );
@ -41,7 +41,7 @@ index e02b7af..f36548e 100644
job_destroy /* destroy */
};
@@ -291,6 +292,20 @@ static void terminate_job( struct job *job, int exit_code )
@@ -286,6 +287,20 @@ static void terminate_job( struct job *job, int exit_code )
job->terminating = 0;
}

View File

@ -1,4 +1,4 @@
From f55bd1380e177f8fd48003fc3b1efae0c16b4c42 Mon Sep 17 00:00:00 2001
From c86188e18efaf5ece7b4d85ccee4089208e392fa Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 28 Feb 2015 06:09:16 +0100
Subject: kernel32/tests: Add tests for waiting on an job object.
@ -8,10 +8,10 @@ Subject: kernel32/tests: Add tests for waiting on an job object.
1 file changed, 85 insertions(+)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index e20fb92..31a4c1d 100644
index 4f51cea..aaa1a6e 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2442,6 +2442,90 @@ static void test_KillOnJobClose(void)
@@ -2456,6 +2456,90 @@ static void test_KillOnJobClose(void)
CloseHandle(pi.hThread);
}
@ -102,7 +102,7 @@ index e20fb92..31a4c1d 100644
static HANDLE test_AddSelfToJob(void)
{
HANDLE job;
@@ -2662,6 +2746,7 @@ START_TEST(process)
@@ -2676,6 +2760,7 @@ START_TEST(process)
test_QueryInformationJobObject();
test_CompletionPort();
test_KillOnJobClose();

View File

@ -1,71 +0,0 @@
From b55b5ab63248360985a6ff01e1d2c98867e05a16 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Sat, 28 Feb 2015 13:37:47 +1100
Subject: server: Support NULL job handles in IsProcessInJob.
---
dlls/kernel32/tests/process.c | 10 ++++++++++
server/process.c | 14 +++++++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 66e0863..e20fb92 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2203,6 +2203,11 @@ static void test_IsProcessInJob(void)
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(!out, "IsProcessInJob returned out=%u\n", out);
+ out = TRUE;
+ ret = pIsProcessInJob(pi.hProcess, NULL, &out);
+ ok(ret, "IsProcessInJob error %u\n", GetLastError());
+ ok(!out, "IsProcessInJob returned out=%u\n", out);
+
ret = pAssignProcessToJobObject(job, pi.hProcess);
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
@@ -2211,6 +2216,11 @@ static void test_IsProcessInJob(void)
ok(ret, "IsProcessInJob error %u\n", GetLastError());
ok(out, "IsProcessInJob returned out=%u\n", out);
+ out = FALSE;
+ ret = pIsProcessInJob(pi.hProcess, NULL, &out);
+ ok(ret, "IsProcessInJob error %u\n", GetLastError());
+ ok(out, "IsProcessInJob returned out=%u\n", out);
+
TerminateProcess(pi.hProcess, 0);
dwret = WaitForSingleObject(pi.hProcess, 1000);
diff --git a/server/process.c b/server/process.c
index f36548e..db5a3b5 100644
--- a/server/process.c
+++ b/server/process.c
@@ -1627,16 +1627,20 @@ DECL_HANDLER(job_assign)
DECL_HANDLER(process_in_job)
{
struct process *process;
- struct job *job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS );
+ struct job *job;
- if (job)
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_QUERY_INFORMATION )))
{
- if ((process = get_process_from_handle( req->process_handle, PROCESS_QUERY_INFORMATION )))
+ if (!req->job_handle)
+ {
+ set_error( (process->job) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
+ }
+ else if ((job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_QUERY )))
{
set_error( (process->job == job) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
- release_object( process );
+ release_object( job );
}
- release_object(job);
+ release_object( process );
}
}
--
2.3.3

View File

@ -1,4 +1,4 @@
From 0bd977f5878df0fbe053847aecf9ae0ed7cd110d Mon Sep 17 00:00:00 2001
From 2885683ee26ca39acc9158c804b5287da43585ac Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 28 Feb 2015 06:58:48 +0100
Subject: server: Implement waiting for job objects.
@ -9,10 +9,10 @@ Subject: server: Implement waiting for job objects.
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index e0da270..cf2c1df 100644
index aaa1a6e..c325d32 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2501,7 +2501,6 @@ static void test_WaitForJobObject(void)
@@ -2482,7 +2482,6 @@ static void test_WaitForJobObject(void)
ok(ret, "TerminateJobObject error %u\n", GetLastError());
dwret = WaitForSingleObject(job, 500);
@ -20,7 +20,7 @@ index e0da270..cf2c1df 100644
ok(dwret == WAIT_OBJECT_0 || broken(dwret == WAIT_TIMEOUT),
"WaitForSingleObject returned %u\n", dwret);
@@ -2510,7 +2509,6 @@ static void test_WaitForJobObject(void)
@@ -2491,7 +2490,6 @@ static void test_WaitForJobObject(void)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(job);
@ -29,7 +29,7 @@ index e0da270..cf2c1df 100644
return;
}
diff --git a/server/process.c b/server/process.c
index db5a3b5..673ce20 100644
index 89c029e..8c654b4 100644
--- a/server/process.c
+++ b/server/process.c
@@ -151,6 +151,7 @@ struct job
@ -48,7 +48,7 @@ index db5a3b5..673ce20 100644
job->completion_port = NULL;
job->completion_key = 0;
}
@@ -290,6 +292,8 @@ static void terminate_job( struct job *job, int exit_code )
@@ -285,6 +287,8 @@ static void terminate_job( struct job *job, int exit_code )
}
job->terminating = 0;
@ -57,7 +57,7 @@ index db5a3b5..673ce20 100644
}
static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -327,7 +331,8 @@ static void job_dump( struct object *obj, int verbose )
@@ -322,7 +326,8 @@ static void job_dump( struct object *obj, int verbose )
static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
{
@ -68,5 +68,5 @@ index db5a3b5..673ce20 100644
struct ptid_entry
--
2.3.0
2.3.3

View File

@ -1,4 +1,4 @@
From 5aaa9bb4d39cfd92b4c913aa961854657dbf944d Mon Sep 17 00:00:00 2001
From 55894316559d36c433e8aa8ae6e6957fa651d09a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 12 Mar 2015 22:19:50 +0100
Subject: ntdll: Implement NtQueryInformationJobObject stub function.
@ -8,10 +8,10 @@ Subject: ntdll: Implement NtQueryInformationJobObject stub function.
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index ef4a4cb..6f09b83 100644
index 87ff3e0..9a7a6d0 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -638,15 +638,37 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
@@ -636,15 +636,37 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
@ -51,5 +51,5 @@ index ef4a4cb..6f09b83 100644
}
}
--
2.3.1
2.3.3

View File

@ -1,18 +1,18 @@
From c45e6864494332d04e7e93be02a0ee8222bd9383 Mon Sep 17 00:00:00 2001
From bc7cb674c2b15f6dc603b9271a684d6aefe3a7d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 14 Aug 2014 03:05:52 +0200
Subject: server: Return error when opening a terminating process. (try 3)
---
server/process.c | 7 ++++++-
server/process.h | 1 +
server/process.c | 7 ++++++-
server/process.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/server/process.c b/server/process.c
index 426bcca..0574a32 100644
index 5be3b00..f9738c0 100644
--- a/server/process.c
+++ b/server/process.c
@@ -268,6 +268,7 @@ void shutdown_master_socket(void)
@@ -394,6 +394,7 @@ void shutdown_master_socket(void)
/* final cleanup once we are sure a process is really dead */
static void process_died( struct process *process )
{
@ -20,15 +20,15 @@ index 426bcca..0574a32 100644
if (debug_level) fprintf( stderr, "%04x: *process killed*\n", process->id );
if (!process->is_system)
{
@@ -324,6 +325,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
@@ -450,6 +451,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
process->is_system = 0;
process->debug_children = 0;
process->is_terminating = 0;
+ process->is_terminated = 0;
process->job = NULL;
process->console = NULL;
process->startup_state = STARTUP_IN_PROGRESS;
process->startup_info = NULL;
@@ -1129,7 +1131,10 @@ DECL_HANDLER(open_process)
@@ -1278,7 +1280,10 @@ DECL_HANDLER(open_process)
reply->handle = 0;
if (process)
{
@ -41,7 +41,7 @@ index 426bcca..0574a32 100644
}
}
diff --git a/server/process.h b/server/process.h
index a50b537..da6d3da 100644
index 58c313a..0cf9514 100644
--- a/server/process.h
+++ b/server/process.h
@@ -75,6 +75,7 @@ struct process
@ -49,9 +49,9 @@ index a50b537..da6d3da 100644
unsigned int debug_children:1;/* also debug all child processes */
unsigned int is_terminating:1;/* is process terminating? */
+ unsigned int is_terminated:1; /* is process terminated? */
struct job *job; /* job object ascoicated with this process */
struct list job_entry; /* list entry for job object */
struct list locks; /* list of file locks owned by the process */
struct list classes; /* window classes owned by the process */
struct console_input*console; /* console input */
--
1.7.9.5
2.3.3

View File

@ -1,56 +1,93 @@
From bea49452dfb1e768b03fc75fced9b733d1edd73f Mon Sep 17 00:00:00 2001
From 148550ffa4aeae7903d6654373011ad282ce59dc Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 14:01:35 -0600
Subject: server: Retrieve file security attributes with extended file
attributes. (try 7)
---
dlls/advapi32/tests/security.c | 49 ++++++++++++++++++++--------------------
server/file.c | 26 ++++++++++++++++++---
2 files changed, 47 insertions(+), 28 deletions(-)
dlls/advapi32/tests/security.c | 57 +++++++++++++++++++++++++-----------------
server/file.c | 26 ++++++++++++++++---
2 files changed, 57 insertions(+), 26 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index b44496a..02094a4 100644
index a757c22..3f97a82 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3192,24 +3192,24 @@ static void test_CreateDirectoryA(void)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
- todo_wine ok(bret, "Current User ACE != Current User SID.\n");
- todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Current User ACE has unexpected flags (0x%x != 0x03)\n",
- ((ACE_HEADER *)ace)->AceFlags);
- ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ok(bret, "Current User ACE != Current User SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
+ "Current User ACE has unexpected flags (0x%x != 0x03)\n",
+ ((ACE_HEADER *)ace)->AceFlags);
+ todo_wine ok(ace->Mask == 0x1f01ff,
+ "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
@@ -3109,7 +3109,7 @@ static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
}
static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
- BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
+ BOOL todo_count, BOOL todo_sid, BOOL todo_flags, BOOL todo_mask, int line)
{
ACL_SIZE_INFORMATION acl_size;
ACCESS_ALLOWED_ACE *ace;
@@ -3150,9 +3150,15 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD
"Current User ACE has unexpected flags (0x%x != 0x%x)\n",
((ACE_HEADER *)ace)->AceFlags, flags);
- ok_(__FILE__, line)(ace->Mask == mask,
- "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
+ if (todo_mask)
+ todo_wine
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ else
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
}
if (acl_size.AceCount > 1)
{
bret = pGetAce(pDacl, 1, (VOID **)&ace);
ok(bret, "Failed to get Administators Group ACE.\n");
bret = EqualSid(&ace->SidStart, admin_sid);
- todo_wine ok(bret, "Administators Group ACE != Administators Group SID.\n");
- todo_wine ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
- "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
- ((ACE_HEADER *)ace)->AceFlags);
- ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
- ace->Mask);
+ ok(bret, "Administators Group ACE != Administators Group SID.\n");
+ ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
+ "Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
+ ((ACE_HEADER *)ace)->AceFlags);
+ todo_wine ok(ace->Mask == 0x1f01ff,
+ "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
@@ -3176,9 +3182,15 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD
"Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
((ACE_HEADER *)ace)->AceFlags, flags);
- ok_(__FILE__, line)(ace->Mask == mask,
- "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
+ if (todo_mask)
+ todo_wine
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
+ else
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
}
}
@@ -3262,7 +3274,7 @@ static void test_CreateDirectoryA(void)
}
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
- 0x1f01ff, FALSE, TRUE, TRUE, __LINE__);
+ 0x1f01ff, FALSE, FALSE, FALSE, TRUE, __LINE__);
LocalFree(pSD);
@@ -3384,23 +3384,22 @@ static void test_GetNamedSecurityInfoA(void)
/* Test inheritance of ACLs in CreateFile without security descriptor */
@@ -3278,7 +3290,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
+ 0x1f01ff, TRUE, TRUE, TRUE, FALSE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
@@ -3352,7 +3364,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
+ 0x1f01ff, TRUE, TRUE, TRUE, FALSE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
@@ -3581,23 +3593,22 @@ static void test_GetNamedSecurityInfoA(void)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
@ -80,7 +117,7 @@ index b44496a..02094a4 100644
}
LocalFree(pSD);
HeapFree(GetProcessHeap(), 0, user);
@@ -4050,22 +4049,22 @@ static void test_GetSecurityInfo(void)
@@ -4247,22 +4258,22 @@ static void test_GetSecurityInfo(void)
bret = pGetAce(pDacl, 0, (VOID **)&ace);
ok(bret, "Failed to get Current User ACE.\n");
bret = EqualSid(&ace->SidStart, user_sid);
@ -110,10 +147,10 @@ index b44496a..02094a4 100644
LocalFree(pSD);
CloseHandle(obj);
diff --git a/server/file.c b/server/file.c
index 72d6d95..ff51b73 100644
index a1455ff..e84331d 100644
--- a/server/file.c
+++ b/server/file.c
@@ -499,6 +499,25 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
@@ -503,6 +503,25 @@ struct security_descriptor *mode_to_sd( mode_t mode, const SID *user, const SID
return sd;
}
@ -139,7 +176,7 @@ index 72d6d95..ff51b73 100644
struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
{
@@ -514,9 +533,10 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
@@ -518,9 +537,10 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
(st.st_uid == *uid))
return obj->sd;
@ -154,5 +191,5 @@ index 72d6d95..ff51b73 100644
*mode = st.st_mode;
--
1.7.9.5
2.3.3

View File

@ -1,41 +1,93 @@
From 9364028096235e2f64b9fe070170b5e4bb2311ca Mon Sep 17 00:00:00 2001
From 3779a55c15d92da1974ff1520e20bc5accc8e4b6 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Fri, 18 Apr 2014 14:05:32 -0600
Subject: server: Convert return of file security masks with generic access
mappings. (try 7)
---
dlls/advapi32/tests/security.c | 24 ++++++++++++------------
server/file.c | 22 ++++++++++++++++++++++
2 files changed, 34 insertions(+), 12 deletions(-)
dlls/advapi32/tests/security.c | 48 ++++++++++++++++--------------------------
server/file.c | 22 +++++++++++++++++++
2 files changed, 40 insertions(+), 30 deletions(-)
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 02094a4..82c0639 100644
index 3f97a82..a530a3f 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -3196,8 +3196,8 @@ static void test_CreateDirectoryA(void)
ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
"Current User ACE has unexpected flags (0x%x != 0x03)\n",
((ACE_HEADER *)ace)->AceFlags);
- todo_wine ok(ace->Mask == 0x1f01ff,
- "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
+ ok(ace->Mask == 0x1f01ff, "Current User ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+ ace->Mask);
@@ -3109,7 +3109,7 @@ static void get_nt_pathW(const char *name, UNICODE_STRING *nameW)
}
static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD flags, DWORD mask,
- BOOL todo_count, BOOL todo_sid, BOOL todo_flags, BOOL todo_mask, int line)
+ BOOL todo_count, BOOL todo_sid, BOOL todo_flags, int line)
{
ACL_SIZE_INFORMATION acl_size;
ACCESS_ALLOWED_ACE *ace;
@@ -3150,15 +3150,9 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD
"Current User ACE has unexpected flags (0x%x != 0x%x)\n",
((ACE_HEADER *)ace)->AceFlags, flags);
- if (todo_mask)
- todo_wine
- ok_(__FILE__, line)(ace->Mask == mask,
- "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
- else
- ok_(__FILE__, line)(ace->Mask == mask,
- "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Current User ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
}
if (acl_size.AceCount > 1)
{
@@ -3208,8 +3208,8 @@ static void test_CreateDirectoryA(void)
ok(((ACE_HEADER *)ace)->AceFlags == (OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE),
"Administators Group ACE has unexpected flags (0x%x != 0x03)\n",
((ACE_HEADER *)ace)->AceFlags);
- todo_wine ok(ace->Mask == 0x1f01ff,
- "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n", ace->Mask);
+ ok(ace->Mask == 0x1f01ff, "Administators Group ACE has unexpected mask (0x%x != 0x1f01ff)\n",
+ ace->Mask);
@@ -3182,15 +3176,9 @@ static void test_inherited_dacl(PACL dacl, PSID admin_sid, PSID user_sid, DWORD
"Administators Group ACE has unexpected flags (0x%x != 0x%x)\n",
((ACE_HEADER *)ace)->AceFlags, flags);
- if (todo_mask)
- todo_wine
- ok_(__FILE__, line)(ace->Mask == mask,
- "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
- else
- ok_(__FILE__, line)(ace->Mask == mask,
- "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
- ace->Mask, mask);
+ ok_(__FILE__, line)(ace->Mask == mask,
+ "Administators Group ACE has unexpected mask (0x%x != 0x%x)\n",
+ ace->Mask, mask);
}
}
@@ -3274,7 +3262,7 @@ static void test_CreateDirectoryA(void)
}
ok(!error, "GetNamedSecurityInfo failed with error %d\n", error);
test_inherited_dacl(pDacl, admin_sid, user_sid, OBJECT_INHERIT_ACE|CONTAINER_INHERIT_ACE,
- 0x1f01ff, FALSE, FALSE, FALSE, TRUE, __LINE__);
+ 0x1f01ff, FALSE, FALSE, FALSE, __LINE__);
LocalFree(pSD);
@@ -3387,8 +3387,8 @@ static void test_GetNamedSecurityInfoA(void)
/* Test inheritance of ACLs in CreateFile without security descriptor */
@@ -3290,7 +3278,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, FALSE, __LINE__);
+ 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
@@ -3364,7 +3352,7 @@ static void test_CreateDirectoryA(void)
(PSID *)&owner, NULL, &pDacl, NULL, &pSD);
ok(error == ERROR_SUCCESS, "Failed to get permissions on file\n");
test_inherited_dacl(pDacl, admin_sid, user_sid, INHERITED_ACE,
- 0x1f01ff, TRUE, TRUE, TRUE, FALSE, __LINE__);
+ 0x1f01ff, TRUE, TRUE, TRUE, __LINE__);
LocalFree(pSD);
CloseHandle(hTemp);
@@ -3596,8 +3584,8 @@ static void test_GetNamedSecurityInfoA(void)
ok(bret, "Current User ACE != Current User SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
@ -46,7 +98,7 @@ index 02094a4..82c0639 100644
}
if (acl_size.AceCount > 1)
{
@@ -3398,8 +3398,8 @@ static void test_GetNamedSecurityInfoA(void)
@@ -3607,8 +3595,8 @@ static void test_GetNamedSecurityInfoA(void)
ok(bret || broken(!bret) /* win2k */, "Administators Group ACE != Administators Group SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
@ -57,7 +109,7 @@ index 02094a4..82c0639 100644
}
LocalFree(pSD);
HeapFree(GetProcessHeap(), 0, user);
@@ -4052,8 +4052,8 @@ static void test_GetSecurityInfo(void)
@@ -4261,8 +4249,8 @@ static void test_GetSecurityInfo(void)
ok(bret, "Current User ACE != Current User SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Current User ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
@ -68,7 +120,7 @@ index 02094a4..82c0639 100644
}
if (acl_size.AceCount > 1)
{
@@ -4063,8 +4063,8 @@ static void test_GetSecurityInfo(void)
@@ -4272,8 +4260,8 @@ static void test_GetSecurityInfo(void)
ok(bret, "Administators Group ACE != Administators Group SID.\n");
ok(((ACE_HEADER *)ace)->AceFlags == 0,
"Administators Group ACE has unexpected flags (0x%x != 0x0)\n", ((ACE_HEADER *)ace)->AceFlags);
@ -80,10 +132,10 @@ index 02094a4..82c0639 100644
LocalFree(pSD);
CloseHandle(obj);
diff --git a/server/file.c b/server/file.c
index ff72273..38eda5c 100644
index e84331d..b6435d1 100644
--- a/server/file.c
+++ b/server/file.c
@@ -521,6 +521,27 @@ struct security_descriptor *get_xattr_sd( int fd )
@@ -522,6 +522,27 @@ struct security_descriptor *get_xattr_sd( int fd )
return sd;
}
@ -111,7 +163,7 @@ index ff72273..38eda5c 100644
struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode_t *mode,
uid_t *uid )
{
@@ -537,6 +558,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
@@ -538,6 +559,7 @@ struct security_descriptor *get_file_sd( struct object *obj, struct fd *fd, mode
return obj->sd;
sd = get_xattr_sd( unix_fd );
@ -120,5 +172,5 @@ index ff72273..38eda5c 100644
security_unix_uid_to_sid( st.st_uid ),
token_get_primary_group( current->process->token ));
--
1.7.9.5
2.3.3