mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added first set of patches for job objects (by Andrew Cook).
This commit is contained in:
parent
ec1b9737d0
commit
870feed3e2
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -10,6 +10,7 @@ wine-staging (1.7.38) UNRELEASED; urgency=low
|
||||
* Added patch to fallback to global key state for threads without a queue.
|
||||
* Added patch to implement SetFileInformationByHandle.
|
||||
* Added patch for CopyFileEx progress callback and cancellation support.
|
||||
* Added first set of patches for job objects (by Andrew Cook).
|
||||
* Removed patch to properly call DriverUnload when unloading device drivers (accepted upstream).
|
||||
* Removed patch to allow Accept-Encoding for HTTP/1.0 in wininet (accepted upstream).
|
||||
* Removed patch to declare pDirectInputCreateEx in a MSVC compatible way (accepted upstream).
|
||||
|
@ -0,0 +1,271 @@
|
||||
From d52b506ca35c8807fbb61b1059b09a507d2e2db9 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Thu, 26 Feb 2015 05:18:09 +0100
|
||||
Subject: kernel32/tests: Allow multiple subprocess commands in process tests.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 74 +++++++++++++++++++++++--------------------
|
||||
1 file changed, 40 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 99185fb..32d57c2 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -550,7 +550,7 @@ static void test_Startup(void)
|
||||
startup.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -588,7 +588,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -626,7 +626,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -664,7 +664,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -702,7 +702,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -742,7 +742,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -780,7 +780,7 @@ static void test_Startup(void)
|
||||
startup.dwFillAttribute = 0xA55A;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -820,16 +820,16 @@ static void test_CommandLine(void)
|
||||
|
||||
/* the basics */
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
|
||||
- okChildInt("Arguments", "argcA", 4);
|
||||
- okChildString("Arguments", "argvA3", "C:\\Program Files\\my nice app.exe");
|
||||
- okChildString("Arguments", "argvA4", NULL);
|
||||
+ okChildInt("Arguments", "argcA", 5);
|
||||
+ okChildString("Arguments", "argvA4", "C:\\Program Files\\my nice app.exe");
|
||||
+ okChildString("Arguments", "argvA5", NULL);
|
||||
okChildString("Arguments", "CommandLineA", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
@@ -841,18 +841,18 @@ static void test_CommandLine(void)
|
||||
|
||||
/* from François */
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
|
||||
- okChildInt("Arguments", "argcA", 6);
|
||||
- okChildString("Arguments", "argvA3", "a\"b\\");
|
||||
- okChildString("Arguments", "argvA4", "c\"");
|
||||
- okChildString("Arguments", "argvA5", "d");
|
||||
- okChildString("Arguments", "argvA6", NULL);
|
||||
+ okChildInt("Arguments", "argcA", 7);
|
||||
+ okChildString("Arguments", "argvA4", "a\"b\\");
|
||||
+ okChildString("Arguments", "argvA5", "c\"");
|
||||
+ okChildString("Arguments", "argvA6", "d");
|
||||
+ okChildString("Arguments", "argvA7", NULL);
|
||||
okChildString("Arguments", "CommandLineA", buffer);
|
||||
release_memory();
|
||||
assert(DeleteFileA(resfile) != 0);
|
||||
@@ -860,7 +860,7 @@ static void test_CommandLine(void)
|
||||
/* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
|
||||
get_file_name(resfile);
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
- sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
+ sprintf(buffer, "./%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
@@ -875,7 +875,7 @@ static void test_CommandLine(void)
|
||||
|
||||
get_file_name(resfile);
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
- sprintf(buffer, ".\\%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
+ sprintf(buffer, ".\\%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
@@ -894,8 +894,8 @@ static void test_CommandLine(void)
|
||||
*(lpFilePart -1 ) = 0;
|
||||
p = strrchr(fullpath, '\\');
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
- if (p) sprintf(buffer, "..%s/%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
|
||||
- else sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
+ if (p) sprintf(buffer, "..%s/%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
|
||||
+ else sprintf(buffer, "./%s tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
@@ -918,7 +918,7 @@ static void test_CommandLine(void)
|
||||
/* Use exename to avoid buffer containing things like 'C:' */
|
||||
if (p) sprintf(buffer, "..%s/%s", p, exename);
|
||||
else sprintf(buffer, "./%s", exename);
|
||||
- sprintf(buffer2, "dummy tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
|
||||
+ sprintf(buffer2, "dummy tests/process.c dump \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
||||
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
||||
@@ -926,7 +926,7 @@ static void test_CommandLine(void)
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
/* child process has changed result file, so let profile functions know about it */
|
||||
WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
|
||||
- sprintf(buffer, "tests/process.c %s", resfile);
|
||||
+ sprintf(buffer, "tests/process.c dump %s", resfile);
|
||||
okChildString("Arguments", "argvA0", "dummy");
|
||||
okChildString("Arguments", "CommandLineA", buffer2);
|
||||
okChildStringWA("Arguments", "CommandLineW", buffer2);
|
||||
@@ -1016,7 +1016,7 @@ static void test_Directory(void)
|
||||
|
||||
/* the basics */
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
GetWindowsDirectoryA( windir, sizeof(windir) );
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
@@ -1123,7 +1123,7 @@ static void test_Environment(void)
|
||||
|
||||
/* the basics */
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
/* wait for child to terminate */
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -1142,7 +1142,7 @@ static void test_Environment(void)
|
||||
|
||||
/* the basics */
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
|
||||
child_env_len = 0;
|
||||
ptr = env;
|
||||
@@ -1210,7 +1210,7 @@ static void test_SuspendFlag(void)
|
||||
startup.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
|
||||
ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
|
||||
@@ -1260,7 +1260,7 @@ static void test_DebuggingFlag(void)
|
||||
startup.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
|
||||
/* get all startup events up to the entry point break exception */
|
||||
@@ -1358,7 +1358,7 @@ static void test_Console(void)
|
||||
cpOut = GetConsoleOutputCP();
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\" console", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" console", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
|
||||
/* wait for child to terminate */
|
||||
@@ -1472,7 +1472,7 @@ static void test_Console(void)
|
||||
startup.hStdError = hChildOutInh;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\" stdhandle", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" stdhandle", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
ok(CloseHandle(hChildInInh), "Closing handle\n");
|
||||
ok(CloseHandle(hChildOutInh), "Closing handle\n");
|
||||
@@ -1509,7 +1509,7 @@ static void test_ExitCode(void)
|
||||
startup.wShowWindow = SW_SHOWNORMAL;
|
||||
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\" exit_code", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\" exit_code", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
|
||||
|
||||
/* wait for child to terminate */
|
||||
@@ -2151,7 +2151,7 @@ void test_StartupNoConsole(void)
|
||||
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup.wShowWindow = SW_SHOWNORMAL;
|
||||
get_file_name(resfile);
|
||||
- sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
||||
+ sprintf(buffer, "\"%s\" tests/process.c dump \"%s\"", selfname, resfile);
|
||||
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup,
|
||||
&info), "CreateProcess\n");
|
||||
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
|
||||
@@ -2174,9 +2174,15 @@ START_TEST(process)
|
||||
ok(b, "Basic init of CreateProcess test\n");
|
||||
if (!b) return;
|
||||
|
||||
- if (myARGC >= 3)
|
||||
+ if (myARGC >= 4)
|
||||
{
|
||||
- doChild(myARGV[2], (myARGC == 3) ? NULL : myARGV[3]);
|
||||
+ if (!strcmp(myARGV[2], "dump"))
|
||||
+ {
|
||||
+ doChild(myARGV[3], (myARGC >= 5) ? myARGV[4] : NULL);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ok(0, "Unexpected command %s\n", myARGV[2]);
|
||||
return;
|
||||
}
|
||||
test_TerminateProcess();
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
From ae2a35cff8966a6754e6f2a8a3b5b92371324a25 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 11:15:03 +1100
|
||||
Subject: kernel32/tests: Add tests for IsProcessInJob.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 86 ++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 84 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 32d57c2..d0d5f46 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -67,6 +67,9 @@ static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFla
|
||||
static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
|
||||
static DWORD (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
|
||||
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||
+static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name);
|
||||
+static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
|
||||
+static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
|
||||
|
||||
/* ############################### */
|
||||
static char base[MAX_PATH];
|
||||
@@ -213,6 +216,9 @@ static BOOL init(void)
|
||||
pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
|
||||
pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
|
||||
pNtCurrentTeb = (void *)GetProcAddress( hntdll, "NtCurrentTeb" );
|
||||
+ pCreateJobObjectW = (void *)GetProcAddress(hkernel32, "CreateJobObjectW");
|
||||
+ pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
|
||||
+ pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2168,19 +2174,87 @@ void test_StartupNoConsole(void)
|
||||
|
||||
}
|
||||
|
||||
+#define create_process(cmd, pi) _create_process(__LINE__, cmd, pi)
|
||||
+static void _create_process(int line, const char *command, LPPROCESS_INFORMATION pi)
|
||||
+{
|
||||
+ BOOL ret;
|
||||
+ char buffer[MAX_PATH] = "";
|
||||
+ STARTUPINFOA si = {0};
|
||||
+
|
||||
+ snprintf(buffer, MAX_PATH, "\"%s\" tests/process.c %s", selfname, command);
|
||||
+
|
||||
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, pi);
|
||||
+ ok_(__FILE__, line)(ret, "CreateProcess error %u\n", GetLastError());
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void test_IsProcessInJob(void)
|
||||
+{
|
||||
+ HANDLE job;
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ BOOL ret, out;
|
||||
+ DWORD dwret;
|
||||
+
|
||||
+ if (!pIsProcessInJob)
|
||||
+ {
|
||||
+ win_skip("IsProcessInJob not available.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ create_process("wait", &pi);
|
||||
+
|
||||
+ out = TRUE;
|
||||
+ ret = pIsProcessInJob(pi.hProcess, job, &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());
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ 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);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+ CloseHandle(job);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
ok(b, "Basic init of CreateProcess test\n");
|
||||
if (!b) return;
|
||||
|
||||
- if (myARGC >= 4)
|
||||
+ if (myARGC >= 3)
|
||||
{
|
||||
- if (!strcmp(myARGV[2], "dump"))
|
||||
+ if (!strcmp(myARGV[2], "dump") && myARGC >= 4)
|
||||
{
|
||||
doChild(myARGV[3], (myARGC >= 5) ? myARGV[4] : NULL);
|
||||
return;
|
||||
}
|
||||
+ else if (!strcmp(myARGV[2], "wait"))
|
||||
+ {
|
||||
+ Sleep(30000);
|
||||
+ ok(0, "Child process not killed\n");
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
ok(0, "Unexpected command %s\n", myARGV[2]);
|
||||
return;
|
||||
@@ -2210,4 +2284,12 @@ START_TEST(process)
|
||||
* handles: check the handle inheritance stuff (+sec options)
|
||||
* console: check if console creation parameters work
|
||||
*/
|
||||
+
|
||||
+ if (!pCreateJobObjectW)
|
||||
+ {
|
||||
+ win_skip("No job object support\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ test_IsProcessInJob();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,80 @@
|
||||
From 6d3ab61226d2b6439edf14e67570adfca9ae02dd Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 08:13:08 +0100
|
||||
Subject: kernel32/tests: Add tests for TerminateJobObject.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 37 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index d0d5f46..bb9053a 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -70,6 +70,7 @@ static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
|
||||
static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name);
|
||||
static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
|
||||
static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
|
||||
+static BOOL (WINAPI *pTerminateJobObject)(HANDLE job, UINT exit_code);
|
||||
|
||||
/* ############################### */
|
||||
static char base[MAX_PATH];
|
||||
@@ -219,6 +220,7 @@ static BOOL init(void)
|
||||
pCreateJobObjectW = (void *)GetProcAddress(hkernel32, "CreateJobObjectW");
|
||||
pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
|
||||
pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
|
||||
+ pTerminateJobObject = (void *)GetProcAddress(hkernel32, "TerminateJobObject");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2236,6 +2238,40 @@ static void test_IsProcessInJob(void)
|
||||
CloseHandle(job);
|
||||
}
|
||||
|
||||
+static void test_TerminateJobObject(void)
|
||||
+{
|
||||
+ HANDLE job;
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ BOOL ret;
|
||||
+ DWORD dwret;
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ create_process("wait", &pi);
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = pTerminateJobObject(job, 123);
|
||||
+ ok(ret, "TerminateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ 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);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+ CloseHandle(job);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
@@ -2292,4 +2328,5 @@ START_TEST(process)
|
||||
}
|
||||
|
||||
test_IsProcessInJob();
|
||||
+ test_TerminateJobObject();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
From 4392400817c45978dc18fd239cceaca0afeb8429 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 08:19:59 +0100
|
||||
Subject: kernel32/tests: Add tests for QueryInformationJobObject
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 90 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 90 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index bb9053a..9a44ca2 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -71,6 +71,7 @@ static HANDLE (WINAPI *pCreateJobObjectW)(LPSECURITY_ATTRIBUTES sa, LPCWSTR name
|
||||
static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
|
||||
static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
|
||||
static BOOL (WINAPI *pTerminateJobObject)(HANDLE job, UINT exit_code);
|
||||
+static BOOL (WINAPI *pQueryInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len, LPDWORD ret_len);
|
||||
|
||||
/* ############################### */
|
||||
static char base[MAX_PATH];
|
||||
@@ -221,6 +222,7 @@ static BOOL init(void)
|
||||
pAssignProcessToJobObject = (void *)GetProcAddress(hkernel32, "AssignProcessToJobObject");
|
||||
pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
|
||||
pTerminateJobObject = (void *)GetProcAddress(hkernel32, "TerminateJobObject");
|
||||
+ pQueryInformationJobObject = (void *)GetProcAddress(hkernel32, "QueryInformationJobObject");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2272,6 +2274,89 @@ static void test_TerminateJobObject(void)
|
||||
CloseHandle(job);
|
||||
}
|
||||
|
||||
+static void test_QueryInformationJobObject(void)
|
||||
+{
|
||||
+ char buf[FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[5])];
|
||||
+ PJOBOBJECT_BASIC_PROCESS_ID_LIST pid_list = (JOBOBJECT_BASIC_PROCESS_ID_LIST *)buf;
|
||||
+ DWORD dwret, ret_len;
|
||||
+ PROCESS_INFORMATION pi[2];
|
||||
+ HANDLE job;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ /* Only active processes are returned */
|
||||
+ create_process("exit", &pi[0]);
|
||||
+ ret = pAssignProcessToJobObject(job, pi[0].hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+ dwret = WaitForSingleObject(pi[0].hProcess, 1000);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi[0].hProcess);
|
||||
+ CloseHandle(pi[0].hThread);
|
||||
+
|
||||
+ create_process("wait", &pi[0]);
|
||||
+ ret = pAssignProcessToJobObject(job, pi[0].hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ create_process("wait", &pi[1]);
|
||||
+ ret = pAssignProcessToJobObject(job, pi[1].hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ret = QueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list,
|
||||
+ FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList), &ret_len);
|
||||
+ ok(!ret, "QueryInformationJobObject expected failure\n");
|
||||
+ todo_wine
|
||||
+ expect_eq_d(ERROR_BAD_LENGTH, GetLastError());
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ memset(buf, 0, sizeof(buf));
|
||||
+ pid_list->NumberOfAssignedProcesses = 42;
|
||||
+ pid_list->NumberOfProcessIdsInList = 42;
|
||||
+ ret = QueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list,
|
||||
+ FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[1]), &ret_len);
|
||||
+ ok(!ret, "QueryInformationJobObject expected failure\n");
|
||||
+ todo_wine
|
||||
+ expect_eq_d(ERROR_MORE_DATA, GetLastError());
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ expect_eq_d(42, pid_list->NumberOfAssignedProcesses);
|
||||
+ expect_eq_d(42, pid_list->NumberOfProcessIdsInList);
|
||||
+ }
|
||||
+
|
||||
+ memset(buf, 0, sizeof(buf));
|
||||
+ ret = pQueryInformationJobObject(job, JobObjectBasicProcessIdList, pid_list, sizeof(buf), &ret_len);
|
||||
+ todo_wine
|
||||
+ ok(ret, "QueryInformationJobObject error %u\n", GetLastError());
|
||||
+ if(ret)
|
||||
+ {
|
||||
+ if (pid_list->NumberOfAssignedProcesses == 3) /* Win 8 */
|
||||
+ win_skip("Number of assigned processes broken on Win 8\n");
|
||||
+ else
|
||||
+ {
|
||||
+ ok(ret_len == FIELD_OFFSET(JOBOBJECT_BASIC_PROCESS_ID_LIST, ProcessIdList[2]),
|
||||
+ "QueryInformationJobObject returned ret_len=%u\n", ret_len);
|
||||
+
|
||||
+ expect_eq_d(2, pid_list->NumberOfAssignedProcesses);
|
||||
+ expect_eq_d(2, pid_list->NumberOfProcessIdsInList);
|
||||
+ expect_eq_d(pi[0].dwProcessId, pid_list->ProcessIdList[0]);
|
||||
+ expect_eq_d(pi[1].dwProcessId, pid_list->ProcessIdList[1]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ TerminateProcess(pi[0].hProcess, 0);
|
||||
+ CloseHandle(pi[0].hProcess);
|
||||
+ CloseHandle(pi[0].hThread);
|
||||
+
|
||||
+ TerminateProcess(pi[1].hProcess, 0);
|
||||
+ CloseHandle(pi[1].hProcess);
|
||||
+ CloseHandle(pi[1].hThread);
|
||||
+
|
||||
+ CloseHandle(job);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
@@ -2291,6 +2376,10 @@ START_TEST(process)
|
||||
ok(0, "Child process not killed\n");
|
||||
return;
|
||||
}
|
||||
+ else if (!strcmp(myARGV[2], "exit"))
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
ok(0, "Unexpected command %s\n", myARGV[2]);
|
||||
return;
|
||||
@@ -2329,4 +2418,5 @@ START_TEST(process)
|
||||
|
||||
test_IsProcessInJob();
|
||||
test_TerminateJobObject();
|
||||
+ test_QueryInformationJobObject();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,116 @@
|
||||
From 8cbb381bd0c9e3ea085dc4a8d139adbb76115ca4 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 13:23:35 +0100
|
||||
Subject: kernel32/tests: Add tests for job object completion ports.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 66 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 66 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 9a44ca2..89a0b05 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -72,6 +72,8 @@ static BOOL (WINAPI *pAssignProcessToJobObject)(HANDLE job, HANDLE process);
|
||||
static BOOL (WINAPI *pIsProcessInJob)(HANDLE process, HANDLE job, PBOOL result);
|
||||
static BOOL (WINAPI *pTerminateJobObject)(HANDLE job, UINT exit_code);
|
||||
static BOOL (WINAPI *pQueryInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len, LPDWORD ret_len);
|
||||
+static BOOL (WINAPI *pSetInformationJobObject)(HANDLE job, JOBOBJECTINFOCLASS class, LPVOID info, DWORD len);
|
||||
+static HANDLE (WINAPI *pCreateIoCompletionPort)(HANDLE file, HANDLE existing_port, ULONG_PTR key, DWORD threads);
|
||||
|
||||
/* ############################### */
|
||||
static char base[MAX_PATH];
|
||||
@@ -223,6 +225,8 @@ static BOOL init(void)
|
||||
pIsProcessInJob = (void *)GetProcAddress(hkernel32, "IsProcessInJob");
|
||||
pTerminateJobObject = (void *)GetProcAddress(hkernel32, "TerminateJobObject");
|
||||
pQueryInformationJobObject = (void *)GetProcAddress(hkernel32, "QueryInformationJobObject");
|
||||
+ pSetInformationJobObject = (void *)GetProcAddress(hkernel32, "SetInformationJobObject");
|
||||
+ pCreateIoCompletionPort = (void *)GetProcAddress(hkernel32, "CreateIoCompletionPort");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2178,6 +2182,25 @@ void test_StartupNoConsole(void)
|
||||
|
||||
}
|
||||
|
||||
+#define test_completion(a, b, c, d, e) _test_completion(__LINE__, a, b, c, d, e)
|
||||
+static void _test_completion(int line, HANDLE port, DWORD ekey, ULONG_PTR evalue, LPOVERLAPPED eoverlapped, DWORD wait)
|
||||
+{
|
||||
+ LPOVERLAPPED overlapped;
|
||||
+ ULONG_PTR value;
|
||||
+ DWORD key;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ ret = GetQueuedCompletionStatus(port, &key, &value, &overlapped, wait);
|
||||
+
|
||||
+ ok_(__FILE__, line)(ret, "GetQueuedCompletionStatus: %x\n", GetLastError());
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ ok_(__FILE__, line)(key == ekey, "unexpected key %x\n", key);
|
||||
+ ok_(__FILE__, line)(value == evalue, "unexpected value %p\n", (void *)value);
|
||||
+ ok_(__FILE__, line)(overlapped == eoverlapped, "unexpected overlapped %p\n", (void *)overlapped);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#define create_process(cmd, pi) _create_process(__LINE__, cmd, pi)
|
||||
static void _create_process(int line, const char *command, LPPROCESS_INFORMATION pi)
|
||||
{
|
||||
@@ -2357,6 +2380,48 @@ static void test_QueryInformationJobObject(void)
|
||||
CloseHandle(job);
|
||||
}
|
||||
|
||||
+static void test_CompletionPort(void)
|
||||
+{
|
||||
+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT port_info;
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ HANDLE job, port;
|
||||
+ DWORD dwret;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ port = pCreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
|
||||
+ ok(port != NULL, "CreateIoCompletionPort error %u\n", GetLastError());
|
||||
+
|
||||
+ port_info.CompletionKey = job;
|
||||
+ port_info.CompletionPort = port;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ create_process("wait", &pi);
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ todo_wine
|
||||
+ test_completion(port, JOB_OBJECT_MSG_NEW_PROCESS, (DWORD_PTR)job, (LPOVERLAPPED)pi.dwProcessId, 0);
|
||||
+
|
||||
+ TerminateProcess(pi.hProcess, 0);
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ todo_wine
|
||||
+ test_completion(port, JOB_OBJECT_MSG_EXIT_PROCESS, (DWORD_PTR)job, (LPOVERLAPPED)pi.dwProcessId, 0);
|
||||
+ todo_wine
|
||||
+ test_completion(port, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, (DWORD_PTR)job, NULL, 100);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+ CloseHandle(job);
|
||||
+ CloseHandle(port);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
@@ -2419,4 +2484,5 @@ START_TEST(process)
|
||||
test_IsProcessInJob();
|
||||
test_TerminateJobObject();
|
||||
test_QueryInformationJobObject();
|
||||
+ test_CompletionPort();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 8f95a75edbefe3c181d8513784b6c46efcc3ebbc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 18:06:59 +0100
|
||||
Subject: kernel32/tests: Add tests for JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 37 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 37 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 89a0b05..1779c81 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2422,6 +2422,42 @@ static void test_CompletionPort(void)
|
||||
CloseHandle(port);
|
||||
}
|
||||
|
||||
+static void test_KillOnJobClose(void)
|
||||
+{
|
||||
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info;
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ DWORD dwret;
|
||||
+ HANDLE job;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
|
||||
+ {
|
||||
+ win_skip("Kill on job close limit not available\n");
|
||||
+ return;
|
||||
+ }
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ create_process("wait", &pi);
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ CloseHandle(job);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ todo_wine
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+ if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
@@ -2485,4 +2521,5 @@ START_TEST(process)
|
||||
test_TerminateJobObject();
|
||||
test_QueryInformationJobObject();
|
||||
test_CompletionPort();
|
||||
+ test_KillOnJobClose();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,122 @@
|
||||
From 7f44ee4aff40ef69667739e3de65d3f0964b2f68 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 18:50:14 +0100
|
||||
Subject: kernel32/tests: Add tests for JOB_OBJECT_LIMIT_ACTIVE_PROCESS.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 93 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 93 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 1779c81..fc69ec8 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2458,6 +2458,98 @@ static void test_KillOnJobClose(void)
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
+static void test_LimitActiveProcesses(void)
|
||||
+{
|
||||
+ JOBOBJECT_BASIC_LIMIT_INFORMATION limit_info;
|
||||
+ PROCESS_INFORMATION pi[2];
|
||||
+ STARTUPINFOA si = {0};
|
||||
+ char buffer[MAX_PATH] = "";
|
||||
+ DWORD dwret;
|
||||
+ HANDLE job;
|
||||
+ BOOL ret;
|
||||
+
|
||||
+ job = pCreateJobObjectW(NULL, NULL);
|
||||
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ limit_info.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
|
||||
+ limit_info.ActiveProcessLimit = 1;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectBasicLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ /* Only active processes count toward the limit */
|
||||
+ create_process("exit", &pi[0]);
|
||||
+ dwret = WaitForSingleObject(pi[0].hProcess, 1000);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+ CloseHandle(pi[0].hProcess);
|
||||
+ CloseHandle(pi[0].hThread);
|
||||
+
|
||||
+ create_process("wait", &pi[0]);
|
||||
+ create_process("wait", &pi[1]);
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, pi[0].hProcess);
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, pi[1].hProcess);
|
||||
+ todo_wine
|
||||
+ ok(!ret, "AssignProcessToJobObject expected failure\n");
|
||||
+ todo_wine
|
||||
+ expect_eq_d(ERROR_NOT_ENOUGH_QUOTA, GetLastError());
|
||||
+
|
||||
+ /* Fails randomly on 2000 and xp */
|
||||
+ dwret = WaitForSingleObject(pi[1].hProcess, 500);
|
||||
+ todo_wine
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+ if (dwret == WAIT_OBJECT_0)
|
||||
+ {
|
||||
+ dwret = 0xdeadbeef;
|
||||
+ ret = GetExitCodeProcess(pi[1].hProcess, &dwret);
|
||||
+ ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
|
||||
+ ok(dwret == ERROR_NOT_ENOUGH_QUOTA || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
|
||||
+ "wrong exitcode %u\n", dwret);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ TerminateProcess(pi[1].hProcess, 0);
|
||||
+ }
|
||||
+
|
||||
+ CloseHandle(pi[1].hProcess);
|
||||
+ CloseHandle(pi[1].hThread);
|
||||
+
|
||||
+ limit_info.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
|
||||
+ limit_info.ActiveProcessLimit = 2;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectBasicLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = pAssignProcessToJobObject(job, GetCurrentProcess());
|
||||
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ snprintf(buffer, MAX_PATH, "\"%s\" tests/process.c %s", selfname, "exit");
|
||||
+
|
||||
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[1]);
|
||||
+ todo_wine
|
||||
+ ok(!ret, "CreateProcessA expected failure\n");
|
||||
+ todo_wine
|
||||
+ expect_eq_d(ERROR_NOT_ENOUGH_QUOTA, GetLastError());
|
||||
+
|
||||
+ if (ret)
|
||||
+ {
|
||||
+ TerminateProcess(pi[1].hProcess, 0);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi[1].hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi[1].hProcess);
|
||||
+ CloseHandle(pi[1].hThread);
|
||||
+ }
|
||||
+
|
||||
+ TerminateProcess(pi[0].hProcess, 0);
|
||||
+
|
||||
+ CloseHandle(pi[0].hProcess);
|
||||
+ CloseHandle(pi[0].hThread);
|
||||
+
|
||||
+ CloseHandle(job);
|
||||
+}
|
||||
+
|
||||
START_TEST(process)
|
||||
{
|
||||
BOOL b = init();
|
||||
@@ -2522,4 +2614,5 @@ START_TEST(process)
|
||||
test_QueryInformationJobObject();
|
||||
test_CompletionPort();
|
||||
test_KillOnJobClose();
|
||||
+ test_LimitActiveProcesses();
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,123 @@
|
||||
From a9c5a8cc61d479997b30565da77ca7232f7533bc Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 19:03:00 +0100
|
||||
Subject: kernel32/tests: Add tests for JOB_OBJECT_LIMIT_BREAKAWAY_OK.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 83 +++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 80 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index fc69ec8..1cd591e 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2458,7 +2458,7 @@ static void test_KillOnJobClose(void)
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
-static void test_LimitActiveProcesses(void)
|
||||
+static HANDLE test_LimitActiveProcesses(void)
|
||||
{
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION limit_info;
|
||||
PROCESS_INFORMATION pi[2];
|
||||
@@ -2547,11 +2547,86 @@ static void test_LimitActiveProcesses(void)
|
||||
CloseHandle(pi[0].hProcess);
|
||||
CloseHandle(pi[0].hThread);
|
||||
|
||||
- CloseHandle(job);
|
||||
+ return job;
|
||||
+}
|
||||
+
|
||||
+static void test_BreakawayOk(HANDLE job)
|
||||
+{
|
||||
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info;
|
||||
+ PROCESS_INFORMATION pi;
|
||||
+ STARTUPINFOA si = {0};
|
||||
+ char buffer[MAX_PATH];
|
||||
+ BOOL ret, out;
|
||||
+ DWORD dwret;
|
||||
+
|
||||
+ if (!pIsProcessInJob)
|
||||
+ {
|
||||
+ win_skip("IsProcessInJob not available.\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ 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)
|
||||
+ {
|
||||
+ TerminateProcess(pi.hProcess, 0);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+ }
|
||||
+
|
||||
+ limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
|
||||
+ ok(ret, "CreateProcessA error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = pIsProcessInJob(pi.hProcess, job, &out);
|
||||
+ ok(ret, "IsProcessInJob error %u\n", GetLastError());
|
||||
+ ok(!out, "IsProcessInJob returned out=%u\n", out);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+
|
||||
+ limit_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
||||
+ ok(ret, "CreateProcess error %u\n", GetLastError());
|
||||
+
|
||||
+ ret = pIsProcessInJob(pi.hProcess, job, &out);
|
||||
+ ok(ret, "IsProcessInJob error %u\n", GetLastError());
|
||||
+ ok(!out, "IsProcessInJob returned out=%u\n", out);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi.hProcess);
|
||||
+ CloseHandle(pi.hThread);
|
||||
+
|
||||
+ /* unset breakaway ok */
|
||||
+ limit_info.BasicLimitInformation.LimitFlags = 0;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(process)
|
||||
{
|
||||
+ HANDLE job;
|
||||
BOOL b = init();
|
||||
ok(b, "Basic init of CreateProcess test\n");
|
||||
if (!b) return;
|
||||
@@ -2614,5 +2689,7 @@ START_TEST(process)
|
||||
test_QueryInformationJobObject();
|
||||
test_CompletionPort();
|
||||
test_KillOnJobClose();
|
||||
- test_LimitActiveProcesses();
|
||||
+ job = test_LimitActiveProcesses();
|
||||
+ test_BreakawayOk(job);
|
||||
+ CloseHandle(job);
|
||||
}
|
||||
--
|
||||
2.3.0
|
||||
|
@ -0,0 +1,60 @@
|
||||
From c8ee9251f15aa6e60fe2d4972e4eae2bddf1c849 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 22:30:28 +0100
|
||||
Subject: kernel32/tests: Add tests for job inheritance.
|
||||
|
||||
Cleanup and improvements by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 29 ++++++++++++++++++++++++++++-
|
||||
1 file changed, 28 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 1cd591e..9d7d8b8 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2466,7 +2466,7 @@ static HANDLE test_LimitActiveProcesses(void)
|
||||
char buffer[MAX_PATH] = "";
|
||||
DWORD dwret;
|
||||
HANDLE job;
|
||||
- BOOL ret;
|
||||
+ BOOL ret, out;
|
||||
|
||||
job = pCreateJobObjectW(NULL, NULL);
|
||||
ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
|
||||
@@ -2547,6 +2547,33 @@ static HANDLE test_LimitActiveProcesses(void)
|
||||
CloseHandle(pi[0].hProcess);
|
||||
CloseHandle(pi[0].hThread);
|
||||
|
||||
+ /* remove quota again */
|
||||
+ limit_info.LimitFlags = 0;
|
||||
+ ret = pSetInformationJobObject(job, JobObjectBasicLimitInformation, &limit_info, sizeof(limit_info));
|
||||
+ ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
+
|
||||
+ if (!pIsProcessInJob)
|
||||
+ {
|
||||
+ win_skip("IsProcessInJob not available.\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[0]);
|
||||
+ ok(ret, "CreateProcessA error %u\n", GetLastError());
|
||||
+
|
||||
+ out = FALSE;
|
||||
+ ret = pIsProcessInJob(pi[0].hProcess, job, &out);
|
||||
+ ok(ret, "IsProcessInJob error %u\n", GetLastError());
|
||||
+ todo_wine
|
||||
+ ok(out, "IsProcessInJob returned out=%u\n", out);
|
||||
+
|
||||
+ dwret = WaitForSingleObject(pi[0].hProcess, 500);
|
||||
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
+
|
||||
+ CloseHandle(pi[0].hProcess);
|
||||
+ CloseHandle(pi[0].hThread);
|
||||
+
|
||||
+out:
|
||||
return job;
|
||||
}
|
||||
|
||||
--
|
||||
2.3.0
|
||||
|
1
patches/kernel32-JobObjects/definition
Normal file
1
patches/kernel32-JobObjects/definition
Normal file
@ -0,0 +1 @@
|
||||
Depends: kernel32-Console_Handles
|
@ -102,6 +102,7 @@ patch_enable_all ()
|
||||
enable_kernel32_GetStringTypeW="$1"
|
||||
enable_kernel32_GetSystemTimes="$1"
|
||||
enable_kernel32_GetVolumePathName="$1"
|
||||
enable_kernel32_JobObjects="$1"
|
||||
enable_kernel32_Named_Pipe="$1"
|
||||
enable_kernel32_NeedCurrentDirectoryForExePath="$1"
|
||||
enable_kernel32_Profile="$1"
|
||||
@ -337,6 +338,9 @@ patch_enable ()
|
||||
kernel32-GetVolumePathName)
|
||||
enable_kernel32_GetVolumePathName="$2"
|
||||
;;
|
||||
kernel32-JobObjects)
|
||||
enable_kernel32_JobObjects="$2"
|
||||
;;
|
||||
kernel32-Named_Pipe)
|
||||
enable_kernel32_Named_Pipe="$2"
|
||||
;;
|
||||
@ -948,6 +952,13 @@ if test "$enable_ntdll_Junction_Points" -eq 1; then
|
||||
enable_ntdll_Fix_Free=1
|
||||
fi
|
||||
|
||||
if test "$enable_kernel32_JobObjects" -eq 1; then
|
||||
if test "$enable_kernel32_Console_Handles" -gt 1; then
|
||||
abort "Patchset kernel32-Console_Handles disabled, but kernel32-JobObjects depends on that."
|
||||
fi
|
||||
enable_kernel32_Console_Handles=1
|
||||
fi
|
||||
|
||||
if test "$enable_kernel32_CopyFileEx" -eq 1; then
|
||||
if test "$enable_kernel32_SetFileInformationByHandle" -gt 1; then
|
||||
abort "Patchset kernel32-SetFileInformationByHandle disabled, but kernel32-CopyFileEx depends on that."
|
||||
@ -2274,6 +2285,34 @@ if test "$enable_kernel32_GetVolumePathName" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset kernel32-JobObjects
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/tests/process.c
|
||||
# |
|
||||
if test "$enable_kernel32_JobObjects" -eq 1; then
|
||||
patch_apply kernel32-JobObjects/0001-kernel32-tests-Allow-multiple-subprocess-commands-in.patch
|
||||
patch_apply kernel32-JobObjects/0002-kernel32-tests-Add-tests-for-IsProcessInJob.patch
|
||||
patch_apply kernel32-JobObjects/0003-kernel32-tests-Add-tests-for-TerminateJobObject.patch
|
||||
patch_apply kernel32-JobObjects/0004-kernel32-tests-Add-tests-for-QueryInformationJobObje.patch
|
||||
patch_apply kernel32-JobObjects/0005-kernel32-tests-Add-tests-for-job-object-completion-p.patch
|
||||
patch_apply kernel32-JobObjects/0006-kernel32-tests-Add-tests-for-JOB_OBJECT_LIMIT_KILL_O.patch
|
||||
patch_apply kernel32-JobObjects/0007-kernel32-tests-Add-tests-for-JOB_OBJECT_LIMIT_ACTIVE.patch
|
||||
patch_apply kernel32-JobObjects/0008-kernel32-tests-Add-tests-for-JOB_OBJECT_LIMIT_BREAKA.patch
|
||||
patch_apply kernel32-JobObjects/0009-kernel32-tests-Add-tests-for-job-inheritance.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Allow multiple subprocess commands in process tests.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for IsProcessInJob.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for TerminateJobObject.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for QueryInformationJobObject.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for job object completion ports.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for JOB_OBJECT_LIMIT_ACTIVE_PROCESS.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for JOB_OBJECT_LIMIT_BREAKAWAY_OK.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for job inheritance.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset kernel32-Named_Pipe
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user