[PATCH v2 4/4] kernel32/tests: Test std handle inheritance in test_parent_process_attribute().
Paul Gofman
gofmanp at gmail.com
Mon Dec 9 15:51:14 CST 2019
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v2:
- added test.
dlls/kernel32/tests/process.c | 55 ++++++++++++++++++++++++++++-------
1 file changed, 45 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 4b18b70882..7ca38c63e9 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -92,6 +92,7 @@ static SIZE_T (WINAPI *pGetLargePageMinimum)(void);
static BOOL (WINAPI *pInitializeProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD, SIZE_T*);
static BOOL (WINAPI *pUpdateProcThreadAttribute)(struct _PROC_THREAD_ATTRIBUTE_LIST*, DWORD, DWORD_PTR, void *,SIZE_T,void*,SIZE_T*);
static void (WINAPI *pDeleteProcThreadAttributeList)(struct _PROC_THREAD_ATTRIBUTE_LIST*);
+static DWORD (WINAPI *pGetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
/* ############################### */
static char base[MAX_PATH];
@@ -259,6 +260,7 @@ static BOOL init(void)
pInitializeProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "InitializeProcThreadAttributeList");
pUpdateProcThreadAttribute = (void *)GetProcAddress(hkernel32, "UpdateProcThreadAttribute");
pDeleteProcThreadAttributeList = (void *)GetProcAddress(hkernel32, "DeleteProcThreadAttributeList");
+ pGetFinalPathNameByHandleA = (void *)GetProcAddress(hkernel32, "GetFinalPathNameByHandleA");
return TRUE;
}
@@ -3827,7 +3829,7 @@ static void test_ProcThreadAttributeList(void)
* level 2: Process created by level 1 process with handle inheritance and level 0
* process parent substitute.
* level 255: Process created by level 1 process during invalid parent handles testing. */
-void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
+void test_parent_process_attribute(unsigned int level, HANDLE read_pipe, HANDLE creator_stdhandle)
{
PROCESS_BASIC_INFORMATION pbi;
char buffer[MAX_PATH + 64];
@@ -3837,7 +3839,9 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
STARTUPINFOEXA si;
DWORD parent_id;
NTSTATUS status;
+ DWORD exit_code;
ULONG pbi_size;
+ HANDLE hstderr;
HANDLE parent;
DWORD size;
BOOL ret;
@@ -3885,8 +3889,24 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
if (level == 2)
{
+ char file_path[MAX_PATH];
+
ok(parent_id == parent_data.parent_id, "Got parent id %u, parent_data.parent_id %u.\n",
parent_id, parent_data.parent_id);
+
+ GetStartupInfoA(&si.StartupInfo);
+ hstderr = si.StartupInfo.hStdError;
+
+ /* On Windows, std handle values are copied from creator process but seems not to be inherited from it.
+ * Some operation on such handle may sometimes succeed, but various way of quering information
+ * from such handle suggest that the handle refers to some other object.
+ * Windows seem to just keep the handle value, even for invalid handle. It does not always work exacly
+ * like that in Wine now due to special handling of console handles in kernelbase/process.c:create_process_params()
+ * and initialization in dlls/msvcrt: msvcrt_init_io(). */
+ ok(hstderr == creator_stdhandle, "Unexpected hstderr %p, creator_hstdhandle %p.\n",
+ hstderr, creator_stdhandle);
+ size = pGetFinalPathNameByHandleA(hstderr, file_path, sizeof(file_path), FILE_NAME_NORMALIZED);
+ ok(!size, "Got unexpected size %u.\n", size);
return;
}
@@ -3902,7 +3922,7 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
"Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
- sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, 255, read_pipe);
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p %p", selfname, 255, read_pipe, NULL);
#if 0
/* Crashes on some Windows installations, otherwise successfully creates process. */
@@ -3990,9 +4010,17 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
ret = pUpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
&parent, sizeof(parent), NULL, NULL);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
+
+ hstderr = CreateFileA("stderr_1.tmp", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ ok(hstderr != INVALID_HANDLE_VALUE, "Could not create file, GetLastError() %u.\n", GetLastError());
+ si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ si.StartupInfo.hStdError = hstderr;
+ si.StartupInfo.hStdOutput = creator_stdhandle;
}
- sprintf(buffer, "\"%s\" tests/process.c parent %u %p", selfname, level + 1, read_pipe);
+ sprintf(buffer, "\"%s\" tests/process.c parent %u %p %p", selfname, level + 1, read_pipe,
+ level ? hstderr : GetStdHandle(STD_OUTPUT_HANDLE));
ret = CreateProcessA(NULL, buffer, NULL, NULL, level == 1, level == 1 ? EXTENDED_STARTUPINFO_PRESENT : 0,
NULL, NULL, (STARTUPINFOA *)&si, &info);
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
@@ -4010,10 +4038,16 @@ void test_parent_process_attribute(unsigned int level, HANDLE read_pipe)
/* wait for child to terminate */
ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
+ GetExitCodeProcess(info.hProcess, &exit_code);
+ ok(!exit_code, "Child test failed, exit_code %#x.\n", exit_code);
+
CloseHandle(info.hThread);
CloseHandle(info.hProcess);
-
- if (!level)
+ if (level)
+ {
+ CloseHandle(hstderr);
+ }
+ else
{
CloseHandle(read_pipe);
CloseHandle(write_pipe);
@@ -4064,12 +4098,13 @@ START_TEST(process)
CloseHandle(info.hThread);
return;
}
- else if (!strcmp(myARGV[2], "parent") && myARGC >= 5)
+ else if (!strcmp(myARGV[2], "parent") && myARGC >= 6)
{
- HANDLE h;
+ HANDLE h1, h2;
- sscanf(myARGV[4], "%p", &h);
- test_parent_process_attribute(atoi(myARGV[3]), h);
+ sscanf(myARGV[4], "%p", &h1);
+ sscanf(myARGV[5], "%p", &h2);
+ test_parent_process_attribute(atoi(myARGV[3]), h1, h2);
return;
}
@@ -4138,5 +4173,5 @@ START_TEST(process)
test_jobInheritance(job);
test_BreakawayOk(job);
CloseHandle(job);
- test_parent_process_attribute(0, NULL);
+ test_parent_process_attribute(0, NULL, NULL);
}
--
2.23.0
More information about the wine-devel
mailing list