This series' main purpose is to fix the handles' attributes of standard I/O handles in CreateProcess. Needed behavior in CreateProcess is implemented by supporting the DUPLICATE_SAME_ATTRIBUTES option in NtDuplicateObject() and DuplicateHandle(). This option is not documented in SDK, but is in DDK. Manifest constant has been added to DDK header (maybe now Wine's DUPLICATE_MAKE_GLOBAL could be moved here to).
From: Eric Pouech epouech@codeweavers.com
Adding support for protect-from-close handle flag to CreateProcess test infrastructure.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/process.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index d59074b988c..c9c3cbebbb6 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -321,8 +321,9 @@ static void WINAPIV __WINE_PRINTF_ATTR(2,3) childPrintf(HANDLE h, const char* fm #define HATTR_NULL 0x08 /* NULL handle value */ #define HATTR_INVALID 0x04 /* INVALID_HANDLE_VALUE */ #define HATTR_TYPE 0x0c /* valid handle, with type set */ -#define HATTR_INHERIT 0x10 /* inheritance flag set */ -#define HATTR_UNTOUCHED 0x20 /* Identify fields untouched by GetStartupInfoW */ +#define HATTR_UNTOUCHED 0x10 /* Identify fields untouched by GetStartupInfoW */ +#define HATTR_INHERIT 0x20 /* inheritance flag set */ +#define HATTR_PROTECT 0x40 /* protect from close flag set */
#define HANDLE_UNTOUCHEDW (HANDLE)(DWORD_PTR)(0x5050505050505050ull)
@@ -344,8 +345,13 @@ static unsigned encode_handle_attributes(HANDLE h) if (dw == FILE_TYPE_CHAR || dw == FILE_TYPE_DISK || dw == FILE_TYPE_PIPE) { DWORD info; - if (GetHandleInformation(h, &info) && (info & HANDLE_FLAG_INHERIT)) - result |= HATTR_INHERIT; + if (GetHandleInformation(h, &info)) + { + if (info & HANDLE_FLAG_INHERIT) + result |= HATTR_INHERIT; + if (info & HANDLE_FLAG_PROTECT_FROM_CLOSE) + result |= HATTR_PROTECT; + } } else dw = FILE_TYPE_UNKNOWN; @@ -3144,6 +3150,7 @@ static void copy_change_subsystem(const char* in, const char* out, DWORD subsyst #define ARG_STARTUPINFO 0x00000000 #define ARG_CP_INHERIT 0x40000000 #define ARG_HANDLE_INHERIT 0x20000000 +#define ARG_HANDLE_PROTECT 0x10000000 #define ARG_HANDLE_MASK (~0xff000000)
static BOOL check_run_child(const char *exec, DWORD flags, BOOL cp_inherit, @@ -3215,6 +3222,13 @@ static BOOL build_startupinfo( STARTUPINFOA *startup, unsigned args, HANDLE hstd ok(0, "Unsupported handle type %x\n", args & ARG_HANDLE_MASK); return FALSE; } + if ((args & ARG_HANDLE_PROTECT) && needs_close) + { + ret = SetHandleInformation(hstd[0], HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE); + ok(ret, "Couldn't set inherit flag to hstd[0]\n"); + ret = SetHandleInformation(hstd[1], HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE); + ok(ret, "Couldn't set inherit flag to hstd[1]\n"); + }
if (args & ARG_STD) { @@ -3259,6 +3273,14 @@ static void test_StdHandleInheritance(void) /* all others handles type behave as H_DISK */ {ARG_STARTUPINFO | ARG_HANDLE_INHERIT | H_DISK, HATTR_NULL, .is_broken = HATTR_TYPE | FILE_TYPE_UNKNOWN}, {ARG_STD | ARG_HANDLE_INHERIT | H_DISK, HATTR_TYPE | HATTR_INHERIT | FILE_TYPE_DISK}, + + /* all others handles type behave as H_DISK */ + {ARG_STARTUPINFO | H_DISK, HATTR_NULL, .is_broken = HATTR_TYPE | FILE_TYPE_UNKNOWN}, +/* 5*/ {ARG_STD | H_DISK, HATTR_TYPE | FILE_TYPE_DISK, .is_todo = 1}, + + /* all others handles type behave as H_DISK */ + {ARG_STARTUPINFO | ARG_HANDLE_PROTECT | H_DISK, HATTR_NULL, .is_broken = HATTR_TYPE | FILE_TYPE_UNKNOWN}, + {ARG_STD | ARG_HANDLE_PROTECT | H_DISK, HATTR_TYPE | HATTR_PROTECT | FILE_TYPE_DISK, .is_todo = 1}, }, nothing_gui[] = { @@ -3370,7 +3392,9 @@ static void test_StdHandleInheritance(void) DeleteFileA(resfile); if (needs_close) { + SetHandleInformation(hstd[0], HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); CloseHandle(hstd[0]); + SetHandleInformation(hstd[1], HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); CloseHandle(hstd[1]); } winetest_pop_context();
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/process.c | 45 +++++++++++++++++++++++++++++++++++ include/ddk/wdm.h | 5 ++++ 2 files changed, 50 insertions(+)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index c9c3cbebbb6..9ac5688e903 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -34,6 +34,7 @@ #include "winnls.h" #include "winternl.h" #include "tlhelp32.h" +#include "ddk/wdm.h"
#include "wine/test.h" #include "wine/heap.h" @@ -2547,6 +2548,50 @@ static void test_DuplicateHandle(void) ok(r, "DuplicateHandle error %lu\n", GetLastError()); ok(f == out || broken(/* Win7 */ (((ULONG_PTR)f & 3) == 3) && (f != out)), "f != out\n"); CloseHandle(out); + + /* Test DUPLICATE_SAME_ATTRIBUTES */ + f = CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); + ok(f != INVALID_HANDLE_VALUE, "Failed to open NUL %lu\n", GetLastError()); + r = GetHandleInformation(f, &info); + ok(r && info == 0, "Unexpected info %lx\n", info); + + r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out, + 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); + ok(r, "DuplicateHandle error %lu\n", GetLastError()); + r = GetHandleInformation(out, &info); + todo_wine + ok(r && info == 0, "Unexpected info %lx\n", info); + CloseHandle(out); + + r = SetHandleInformation(f, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, + HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE); + ok(r, "SetHandleInformation error %lu\n", GetLastError()); + info = 0xdeabeef; + r = GetHandleInformation(f, &info); + ok(r && info == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE), "Unexpected info %lx\n", info); + ok(r, "SetHandleInformation error %lu\n", GetLastError()); + r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out, + 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); + ok(r, "DuplicateHandle error %lu\n", GetLastError()); + info = 0xdeabeef; + r = GetHandleInformation(out, &info); + todo_wine + ok(r && info == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE), "Unexpected info %lx\n", info); + r = SetHandleInformation(out, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); + ok(r, "SetHandleInformation error %lu\n", GetLastError()); + CloseHandle(out); + r = SetHandleInformation(f, HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); + ok(r, "SetHandleInformation error %lu\n", GetLastError()); + CloseHandle(f); + + r = DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &out, + 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); + ok(r, "DuplicateHandle error %lu\n", GetLastError()); + info = 0xdeabeef; + r = GetHandleInformation(out, &info); + todo_wine + ok(r && info == 0, "Unexpected info %lx\n", info); + CloseHandle(out); }
#define test_completion(a, b, c, d, e) _test_completion(__LINE__, a, b, c, d, e) diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 7dcec028a50..414f60b5419 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -1671,6 +1671,11 @@ static inline void IoCopyCurrentIrpStackLocationToNext(IRP *irp) #define SYMBOLIC_LINK_QUERY 0x0001 #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+/* Flags for ZwDuplicateObject */ +#define DUPLICATE_CLOSE_SOURCE 0x00000001 +#define DUPLICATE_SAME_ACCESS 0x00000002 +#define DUPLICATE_SAME_ATTRIBUTES 0x00000004 + #ifndef WINE_UNIX_LIB
NTSTATUS WINAPI DbgQueryDebugFilterState(ULONG, ULONG);
From: Eric Pouech epouech@codeweavers.com
This flag is documented on MSDN in ZwDuplicateObject() but not in DuplicateHandle(). Yet functional on both.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/process.c | 3 --- server/handle.c | 7 ++++++- 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 9ac5688e903..432d770d7b7 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -2559,7 +2559,6 @@ static void test_DuplicateHandle(void) 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); ok(r, "DuplicateHandle error %lu\n", GetLastError()); r = GetHandleInformation(out, &info); - todo_wine ok(r && info == 0, "Unexpected info %lx\n", info); CloseHandle(out);
@@ -2575,7 +2574,6 @@ static void test_DuplicateHandle(void) ok(r, "DuplicateHandle error %lu\n", GetLastError()); info = 0xdeabeef; r = GetHandleInformation(out, &info); - todo_wine ok(r && info == (HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE), "Unexpected info %lx\n", info); r = SetHandleInformation(out, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0); ok(r, "SetHandleInformation error %lu\n", GetLastError()); @@ -2589,7 +2587,6 @@ static void test_DuplicateHandle(void) ok(r, "DuplicateHandle error %lu\n", GetLastError()); info = 0xdeabeef; r = GetHandleInformation(out, &info); - todo_wine ok(r && info == 0, "Unexpected info %lx\n", info); CloseHandle(out); } diff --git a/server/handle.c b/server/handle.c index 0595fdb403b..69f42970912 100644 --- a/server/handle.c +++ b/server/handle.c @@ -32,6 +32,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h"
#include "handle.h" #include "process.h" @@ -566,7 +567,7 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str { obj_handle_t res; struct handle_entry *entry; - unsigned int src_access; + unsigned int src_access, src_flags; struct object *obj = get_handle_obj( src, src_handle, 0, NULL );
if (!obj) return 0; @@ -574,6 +575,7 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str src_access = entry->access; else /* pseudo-handle, give it full access */ src_access = obj->ops->map_access( obj, GENERIC_ALL ); + src_flags = src_access >> RESERVED_SHIFT; src_access &= ~RESERVED_ALL;
if (options & DUPLICATE_SAME_ACCESS) @@ -611,6 +613,9 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str res = alloc_handle_entry( dst, obj, access, attr ); }
+ if (res && (options & DUPLICATE_SAME_ATTRIBUTES)) + set_handle_flags( dst, res, ~0u, src_flags ); + release_object( obj ); return res; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernel32/tests/process.c | 4 ++-- server/process.c | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c index 432d770d7b7..4f7e52d0e26 100644 --- a/dlls/kernel32/tests/process.c +++ b/dlls/kernel32/tests/process.c @@ -3318,11 +3318,11 @@ static void test_StdHandleInheritance(void)
/* all others handles type behave as H_DISK */ {ARG_STARTUPINFO | H_DISK, HATTR_NULL, .is_broken = HATTR_TYPE | FILE_TYPE_UNKNOWN}, -/* 5*/ {ARG_STD | H_DISK, HATTR_TYPE | FILE_TYPE_DISK, .is_todo = 1}, +/* 5*/ {ARG_STD | H_DISK, HATTR_TYPE | FILE_TYPE_DISK},
/* all others handles type behave as H_DISK */ {ARG_STARTUPINFO | ARG_HANDLE_PROTECT | H_DISK, HATTR_NULL, .is_broken = HATTR_TYPE | FILE_TYPE_UNKNOWN}, - {ARG_STD | ARG_HANDLE_PROTECT | H_DISK, HATTR_TYPE | HATTR_PROTECT | FILE_TYPE_DISK, .is_todo = 1}, + {ARG_STD | ARG_HANDLE_PROTECT | H_DISK, HATTR_TYPE | HATTR_PROTECT | FILE_TYPE_DISK}, }, nothing_gui[] = { diff --git a/server/process.c b/server/process.c index a0d5ea64d97..39b24e33f8c 100644 --- a/server/process.c +++ b/server/process.c @@ -55,6 +55,7 @@ #include "ntstatus.h" #define WIN32_NO_STATUS #include "winternl.h" +#include "ddk/wdm.h"
#include "file.h" #include "handle.h" @@ -1336,11 +1337,11 @@ DECL_HANDLER(new_process) if (!(req->flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES) && info->data->console != 1) { info->data->hstdin = duplicate_handle( parent, info->data->hstdin, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); info->data->hstdout = duplicate_handle( parent, info->data->hstdout, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); info->data->hstderr = duplicate_handle( parent, info->data->hstderr, process, - 0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS ); + 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); /* some handles above may have been invalid; this is not an error */ if (get_error() == STATUS_INVALID_HANDLE || get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
Alexandre Julliard (@julliard) commented about include/ddk/wdm.h:
#define SYMBOLIC_LINK_QUERY 0x0001 #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1)
+/* Flags for ZwDuplicateObject */ +#define DUPLICATE_CLOSE_SOURCE 0x00000001 +#define DUPLICATE_SAME_ACCESS 0x00000002 +#define DUPLICATE_SAME_ATTRIBUTES 0x00000004
This can go in winnt.h.
V2: moved manifest constants to include/winnt.h
@julliard: what's the status of this MR?
It seems you never pushed V2.