mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Rebase against upstream changes, partially removed patches for job objects (accepted upstream).
This commit is contained in:
parent
2aadb491e9
commit
c6b84caa19
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 },';
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user