| |
| |
| |
| |
| |
| |
| #include <psxtypes/psxtypes.h> |
| #include <ntapi/nt_object.h> |
| #include <ntapi/nt_debug.h> |
| #include "ntapi_impl.h" |
| |
| static int32_t __tt_debug_break_process_fail(void * hthread, int32_t status) |
| { |
| __ntapi->zw_terminate_thread( |
| hthread,status); |
| |
| return status; |
| } |
| |
| struct __dbg_hoppla { |
| void * caller; |
| void * cx; |
| intptr_t dx; |
| intptr_t r9; |
| intptr_t r8; |
| }; |
| |
| int32_t __stdcall __ntapi_tt_debug_break_process( |
| __in void * hprocess, |
| __out void ** hthread, |
| __out nt_cid * cid) |
| { |
| int32_t status; |
| nt_thread_params tparams; |
| nt_thread_context context; |
| nt_user_stack spinfo; |
| struct __dbg_hoppla hoppla; |
| uintptr_t sptop; |
| uintptr_t spreg; |
| int32_t (*dbg_break_point)(void *); |
| |
| |
| dbg_break_point = pe_get_procedure_address( |
| pe_get_ntdll_module_handle(), |
| "DbgBreakPoint"); |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| &tparams,0, |
| sizeof(tparams)); |
| |
| __ntapi->tt_aligned_block_memset( |
| &spinfo,0, |
| sizeof(spinfo)); |
| |
| tparams.start = dbg_break_point; |
| tparams.hprocess = hprocess; |
| tparams.stack_size_commit = 0x1000; |
| tparams.stack_size_reserve = 0x1000; |
| tparams.stack_info = &spinfo; |
| tparams.creation_flags = NT_CREATE_SUSPENDED; |
| |
| if ((status = __ntapi->tt_create_thread(&tparams))) |
| return status; |
| |
| |
| __ntapi->tt_aligned_block_memset( |
| &context,0, |
| sizeof(context)); |
| |
| context.uc_context_flags = NT_CONTEXT_JUST_EVERYTHING; |
| |
| if ((status = __ntapi->zw_get_context_thread( |
| tparams.hthread, |
| &context))) |
| return __tt_debug_break_process_fail( |
| tparams.hthread, |
| status); |
| |
| |
| hoppla.caller = __ntapi->zw_terminate_thread; |
| hoppla.cx = NT_CURRENT_THREAD_HANDLE; |
| hoppla.dx = NT_STATUS_BREAKPOINT; |
| hoppla.r8 = 0; |
| hoppla.r9 = 0; |
| |
| sptop = (uintptr_t)tparams.stack_info->expandable_stack_base; |
| spreg = context.STACK_POINTER_REGISTER; |
| |
| if (sptop - spreg < sizeof(hoppla)) |
| spreg -= sizeof(hoppla); |
| |
| if ((status = __ntapi->zw_write_virtual_memory( |
| hprocess, |
| (void *)spreg, |
| (char *)&hoppla, |
| sizeof(hoppla),0))) |
| return __tt_debug_break_process_fail( |
| tparams.hthread, |
| status); |
| |
| |
| context.STACK_POINTER_REGISTER = spreg; |
| context.FAST_CALL_ARG0 = (uintptr_t)hoppla.cx; |
| context.FAST_CALL_ARG1 = hoppla.dx; |
| |
| if ((status = __ntapi->zw_set_context_thread( |
| tparams.hthread, |
| &context))) |
| return __tt_debug_break_process_fail( |
| tparams.hthread, |
| status); |
| |
| |
| if ((status = __ntapi->zw_resume_thread(tparams.hthread,0))) |
| return __tt_debug_break_process_fail( |
| tparams.hthread, |
| status); |
| |
| |
| *hthread = tparams.hthread; |
| cid->thread_id = tparams.cid.thread_id; |
| cid->process_id = tparams.cid.process_id; |
| |
| return NT_STATUS_SUCCESS; |
| } |