From 98327378433da5ce48ffb14a66c9f626ebcc44a2 Mon Sep 17 00:00:00 2001 From: Serge Gautherie <32623169+SergeGautherie@users.noreply.github.com> Date: Thu, 19 Jun 2025 18:47:31 +0200 Subject: [PATCH] [NTDLL_WINETEST][NTOS:PS] Fix a few NtQueryInformationProcess(Process*) handling cases (#8136) * [NTDLL_WINETEST] `test_query_process_debug_object_handle()`: one WINESYNC Cherry-pick WineTest part of: https://gitlab.winehq.org/wine/wine/-/commit/52d733b5c4876276d7a2dfc8d9a9bb72a853dfd0 server: Implement retrieving the debug object of a process. by: Alexandre Julliard * [NTOS:PS] Fix `NtQueryInformationProcess(ProcessDebugObjectHandle)` Close the retrieved `DebugPort` on failure. Addendum to commit 1e172203a (r55734). * [NTOS:PS] Optimize `NtQueryInformationProcess(ProcessWow64Information)` on 32-bit. No need to do the ExAcquire/ReleaseRundownProtection rigamarole since we aren't retrieving the `Process->Wow64Process` on 32-bit builds. Addendum to commit 1e172203a (r55734). * [NTOS:PS] Fix `NtQueryInformationProcess(ProcessExecuteFlags)` s/return/break/ on a failure case. Addendum to commit 1e172203a (r55734). * [NTOS:PS] NtQueryInformationProcess(): Optimize `*ReturnLength` assignment Enter the SEH block only if we know we'll have to set `*ReturnLength` on return. Addendum to commit 2278c2914 (r23175). --- modules/rostests/winetests/ntdll/info.c | 8 ++++ ntoskrnl/ps/query.c | 51 ++++++++++++++----------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/modules/rostests/winetests/ntdll/info.c b/modules/rostests/winetests/ntdll/info.c index a1a131e41c6..55f6c3875c6 100644 --- a/modules/rostests/winetests/ntdll/info.c +++ b/modules/rostests/winetests/ntdll/info.c @@ -1582,12 +1582,20 @@ static void test_query_process_debug_object_handle(int argc, char **argv) debug_object = (HANDLE)0xdeadbeef; status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle, &debug_object, sizeof(debug_object), NULL); +#ifndef __REACTOS__ todo_wine +#endif ok(status == STATUS_SUCCESS, "Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status); +#ifndef __REACTOS__ todo_wine +#endif ok(debug_object != NULL, "Expected debug object handle to be non-NULL, got %p\n", debug_object); +#ifdef __REACTOS__ + status = NtClose( debug_object ); + ok( !status, "NtClose failed %x\n", status ); +#endif for (;;) { diff --git a/ntoskrnl/ps/query.c b/ntoskrnl/ps/query.c index 2c344e9441b..72fa309d0c8 100644 --- a/ntoskrnl/ps/query.c +++ b/ntoskrnl/ps/query.c @@ -907,7 +907,7 @@ NtQueryInformationProcess( case ProcessDebugObjectHandle: { - HANDLE DebugPort = 0; + HANDLE DebugPort = NULL; if (ProcessInformationLength != sizeof(HANDLE)) { @@ -927,7 +927,7 @@ NtQueryInformationProcess( NULL); if (!NT_SUCCESS(Status)) break; - /* Get the debug port */ + /* Get the debug port. Continue even if this fails. */ Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort); /* Let go of the process */ @@ -941,7 +941,11 @@ NtQueryInformationProcess( } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - /* Get the exception code */ + if (DebugPort) + ObCloseHandle(DebugPort, PreviousMode); + + /* Get the exception code. + * Note: This overwrites any previous failure status. */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; @@ -1040,23 +1044,24 @@ NtQueryInformationProcess( NULL); if (!NT_SUCCESS(Status)) break; +#ifdef _WIN64 /* Make sure the process isn't dying */ if (ExAcquireRundownProtection(&Process->RundownProtect)) { /* Get the WOW64 process structure */ -#ifdef _WIN64 Wow64 = (ULONG_PTR)Process->Wow64Process; -#else - Wow64 = 0; -#endif /* Release the lock */ ExReleaseRundownProtection(&Process->RundownProtect); } +#endif + + /* Dereference the process */ + ObDereferenceObject(Process); /* Protect write with SEH */ _SEH2_TRY { - /* Return whether or not we have a debug port */ + /* Return the Wow64 process information */ *(PULONG_PTR)ProcessInformation = Wow64; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -1065,9 +1070,6 @@ NtQueryInformationProcess( Status = _SEH2_GetExceptionCode(); } _SEH2_END; - - /* Dereference the process */ - ObDereferenceObject(Process); break; } @@ -1086,7 +1088,8 @@ NtQueryInformationProcess( if (ProcessHandle != NtCurrentProcess()) { - return STATUS_INVALID_PARAMETER; + Status = STATUS_INVALID_PARAMETER; + break; } /* Get the options */ @@ -1130,18 +1133,22 @@ NtQueryInformationProcess( Status = STATUS_INVALID_INFO_CLASS; } - /* Protect write with SEH */ - _SEH2_TRY + /* Check if caller wants the return length and if there is one */ + if (ReturnLength != NULL && Length != 0) { - /* Check if caller wanted return length */ - if ((ReturnLength) && (Length)) *ReturnLength = Length; + /* Protect write with SEH */ + _SEH2_TRY + { + *ReturnLength = Length; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code. + * Note: This overwrites any previous failure status. */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Get exception code */ - Status = _SEH2_GetExceptionCode(); - } - _SEH2_END; return Status; }