From ac93445a827d3eacfbe2fa3f284cd2c86e184aad Mon Sep 17 00:00:00 2001 From: Trung <57174311+trungnt2910@users.noreply.github.com> Date: Sun, 3 Nov 2024 01:06:01 +1100 Subject: [PATCH] fix: `CreateThread` on RS2-RS3 RS2 actually already contains the ABI break for `CreateThread` similar to RS4. This commit fixes the names and dispatching to reflect this discovery. --- lxmonika/include/pico.h | 6 +++--- lxmonika/src/monika.cpp | 13 ++++++++++++- lxmonika/src/monika_dispatcher.cpp | 19 +++++++++---------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/lxmonika/include/pico.h b/lxmonika/include/pico.h index 5406c54..d1de8de 100644 --- a/lxmonika/include/pico.h +++ b/lxmonika/include/pico.h @@ -321,14 +321,14 @@ typedef NTSTATUS PS_PICO_CREATE_THREAD_TH1( _In_ PPS_PICO_THREAD_ATTRIBUTES ThreadAttributes, _Outptr_ PHANDLE ThreadHandle ); -typedef NTSTATUS PS_PICO_CREATE_THREAD_RS4( +typedef NTSTATUS PS_PICO_CREATE_THREAD_RS2( _In_ PPS_PICO_THREAD_ATTRIBUTES ThreadAttributes, _In_opt_ PPS_PICO_CREATE_INFO CreateInfo, _Outptr_ PHANDLE ThreadHandle ); -#if (NTDDI_VERSION >= NTDDI_RS4) -typedef PS_PICO_CREATE_THREAD_RS4 PS_PICO_CREATE_THREAD; +#if (NTDDI_VERSION >= NTDDI_RS2) +typedef PS_PICO_CREATE_THREAD_RS2 PS_PICO_CREATE_THREAD; #else typedef PS_PICO_CREATE_THREAD_TH1 PS_PICO_CREATE_THREAD; #endif diff --git a/lxmonika/src/monika.cpp b/lxmonika/src/monika.cpp index 54dc39a..5708677 100644 --- a/lxmonika/src/monika.cpp +++ b/lxmonika/src/monika.cpp @@ -366,9 +366,20 @@ MaRegisterPicoProviderEx( // Keep the potentially larger size, hoping that some drivers // might know that they are outdated. - if (dwAbiVersion >= NTDDI_WIN10_RS4) + if (dwAbiVersion >= NTDDI_WIN10_RS2) { + // This is the ABI for RS4. memcpy(PicoRoutines, &MapRoutines[uProviderIndex], PicoRoutines->Size); + // RS3 or lower still uses the CreateProcess callback from TH1. + if (dwAbiVersion < NTDDI_WIN10_RS4) + { + if (PicoRoutines->Size >= + (FIELD_OFFSET(PS_PICO_ROUTINES, CreateProcess) + + sizeof(PS_PICO_ROUTINES::CreateProcess))) + { + PicoRoutines->CreateProcess = MapRoutinesTh1[uProviderIndex].CreateProcess; + } + } } else // NTDDI_WIN10 { diff --git a/lxmonika/src/monika_dispatcher.cpp b/lxmonika/src/monika_dispatcher.cpp index 36b19e6..059bf0b 100644 --- a/lxmonika/src/monika_dispatcher.cpp +++ b/lxmonika/src/monika_dispatcher.cpp @@ -260,17 +260,16 @@ MapCreateProcess( { MapRanAbiCheck = TRUE; - Logger::LogTrace("Running ABI check before initial dispatch."); + Logger::LogTrace("Running ABI check before initial CreateProcess dispatch."); // It would be nice if we could run this during initialization. // However, starting processes when the system has not finished initializing // is not a fun thing to do and has caused BSODs during testing. // Instead, we wait until everything is ready and a provider starts requesting // Pico processes. - // We are not doing anything similar for the threads, since one would need - // a working Pico process to create a Pico thread (theoretically). - // By the time the thread callbacks are called, we should have established - // our version. + // + // For threads, the ABI change occurred at RS2 instead of RS4. + // Fortunately, we can detect RS2 through parameter struct sizes alone. // Still use the RS4 callback. PS_PICO_CREATE_INFO psTempInfo = CreateInfo != NULL ? @@ -286,7 +285,7 @@ MapCreateProcess( if (hdlProcess == NULL) { Logger::LogTrace("Call succeeded but output parameter is wrong."); - Logger::LogTrace("Old ABI detected.", (PVOID)status); + Logger::LogTrace("Old ABI detected."); // This is actually RS3 or lower. // The handle is in psTempInfo. @@ -315,12 +314,12 @@ MapCreateProcess( if (!NT_SUCCESS(status)) { Logger::LogTrace("TH1 variant also failed, status=", (PVOID)status); - Logger::LogTrace("Invalidating ABI check results.", (PVOID)status); + Logger::LogTrace("Invalidating ABI check results."); MapRanAbiCheck = FALSE; } else { - Logger::LogTrace("Old ABI detected.", (PVOID)status); + Logger::LogTrace("Old ABI detected."); } } } @@ -466,9 +465,9 @@ MapCreateThread( NTSTATUS status; HANDLE hdlThread = NULL; - if (MA_SYSTEM_AT_LEAST(NTDDI_WIN10_RS4)) + if (MA_SYSTEM_AT_LEAST(NTDDI_WIN10_RS2)) { - status = ((PS_PICO_CREATE_THREAD_RS4*)MapOriginalRoutines.CreateThread)( + status = ((PS_PICO_CREATE_THREAD_RS2*)MapOriginalRoutines.CreateThread)( ThreadAttributes, CreateInfo, &hdlThread); } else // TH1