102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
pcdogs_symbols.c
Go to the documentation of this file.
1#include <dttr_pcdogs.h>
2
3#include "core_internal.h"
4
5// DTTR_PCDOGS_T_Patch_Report shares DTTR_Core_TargetReport's layout, so the core
6// helpers populate it directly.
10
13 size_t index,
14 DTTR_Result result
15) {
16 dttr_core_report_fail((DTTR_Core_TargetReport *)report, index, result);
17}
18
19static uintptr_t function_address_at(uint32_t index) {
21 return fn ? fn->address : 0;
22}
23
24static uintptr_t global_address_at(uint32_t index) {
26 return global ? global->address : 0;
27}
28
31 uint32_t id,
32 uint32_t count,
33 uintptr_t (*address_at)(uint32_t index),
34 uintptr_t *out_addr,
35 const char *invalid_message,
36 const char *not_found_message
37) {
38 if (!ctx || !out_addr || id >= count) {
39 return dttr_core_result(DTTR_ERR_INVALID_ARGUMENT, invalid_message);
40 }
41
42 *out_addr = 0;
44 const uintptr_t addr = address_at(id);
45 if (!addr) {
46 return dttr_core_result(DTTR_ERR_NOT_FOUND, not_found_message);
47 }
48
49 *out_addr = addr;
50 return dttr_core_result(DTTR_OK, "ok");
51}
52
56 uintptr_t *out_addr
57) {
58 return resolve_symbol(
59 ctx,
60 (uint32_t)id,
63 out_addr,
64 "invalid PCDOGS symbol function resolve arguments",
65 "PCDOGS symbol function was not resolved"
66 );
67}
68
72 uintptr_t *out_addr
73) {
75 if (!DTTR_PCDOGS_FunctionSymbolID(id, &symbol_id)) {
76 return dttr_core_result(
78 "invalid PCDOGS function resolve arguments"
79 );
80 }
81
82 return DTTR_PCDOGS_SymbolFunctionResolve(ctx, symbol_id, out_addr);
83}
84
88 uintptr_t *out_addr
89) {
90 return resolve_symbol(
91 ctx,
92 (uint32_t)id,
95 out_addr,
96 "invalid PCDOGS symbol global resolve arguments",
97 "PCDOGS symbol global was not resolved"
98 );
99}
100
102 const DTTR_Core_Context *ctx,
104 uintptr_t *out_addr
105) {
107 if (!DTTR_PCDOGS_DataSymbolID(id, &symbol_id)) {
108 return dttr_core_result(
110 "invalid PCDOGS global resolve arguments"
111 );
112 }
113
114 return DTTR_PCDOGS_SymbolDataResolve(ctx, symbol_id, out_addr);
115}
116
118 const DTTR_Core_Context *ctx,
120 void *new_value,
121 void **out_original,
122 DTTR_Core_Hook **out_hook
123) {
124 if (out_hook) {
125 *out_hook = NULL;
126 }
127
128 if (!ctx || !out_hook) {
129 return dttr_core_result(
131 "invalid PCDOGS global pointer hook arguments"
132 );
133 }
134
135 uintptr_t address = 0;
136 DTTR_Result resolved = DTTR_PCDOGS_DataResolve(ctx, id, &address);
137 if (!DTTR_ResultOK(resolved)) {
138 return resolved;
139 }
140
141 return DTTR_Core_HookPointer(ctx, address, new_value, out_original, out_hook);
142}
143
147 void *detour,
148 void **out_original
149) {
150 if (!group || !detour) {
151 return dttr_core_result(
153 "invalid PCDOGS patch group symbol function hook arguments"
154 );
155 }
156
158 if (!fn || fn->hook_kind != DTTR_PCDOGS_HOOK_REL32 || !fn->callable) {
159 return dttr_core_result(
161 "PCDOGS symbol function is not hookable"
162 );
163 }
164
166 uintptr_t address = 0;
167 DTTR_Result resolved = DTTR_PCDOGS_SymbolFunctionResolve(ctx, id, &address);
168 if (!DTTR_ResultOK(resolved)) {
169 return resolved;
170 }
171
173 group,
174 address,
175 (int)fn->patch_size,
176 detour,
177 out_original,
178 NULL
179 );
180}
181
185 void *detour,
186 void **out_original
187) {
189 if (!DTTR_PCDOGS_FunctionSymbolID(id, &symbol_id)) {
190 return dttr_core_result(
192 "invalid PCDOGS patch group function hook arguments"
193 );
194 }
195
196 return patch_group_hook_symbol_function(group, symbol_id, detour, out_original);
197}
198
202 void *new_value,
203 void **out_original
204) {
205 if (!group) {
206 return dttr_core_result(
208 "invalid PCDOGS patch group global pointer hook arguments"
209 );
210 }
211
213 uintptr_t address = 0;
214 DTTR_Result resolved = DTTR_PCDOGS_DataResolve(ctx, id, &address);
215 if (!DTTR_ResultOK(resolved)) {
216 return resolved;
217 }
218
219 return DTTR_Core_PatchGroupHookPointer(group, address, new_value, out_original, NULL);
220}
221
223 const DTTR_PCDOGS_T_Patch_Spec *spec,
224 DTTR_Core_TargetSpec *out_target
225) {
226 if (!spec || !out_target) {
227 return dttr_core_result(
229 "invalid PCDOGS patch spec target"
230 );
231 }
232
234 target.required = spec->required || target.required;
235 switch (spec->kind) {
237 break;
240 target.address = spec->address;
241 target.patch_bytes = spec->patch_bytes;
242 target.patch_size = spec->patch_size;
243 break;
246 target.aob = spec->aob;
247 target.offset = spec->offset;
248 target.patch_bytes = spec->patch_bytes;
249 target.patch_size = spec->patch_size;
250 break;
253 target.aob = spec->aob;
254 target.offset = spec->offset;
255 target.detour = spec->detour;
256 break;
257 default:
258 return dttr_core_result(
260 "unsupported PCDOGS patch spec kind"
261 );
262 }
263
264 *out_target = target;
265 return dttr_core_result(DTTR_OK, "ok");
266}
267
270 const DTTR_PCDOGS_T_Patch_Spec *spec
271) {
272 switch (spec->kind) {
274 return dttr_core_result(
276 "unsupported PCDOGS patch spec kind"
277 );
280 group,
281 spec->function,
282 spec->detour,
283 spec->out_original
284 );
287 group,
288 spec->global,
289 spec->new_value,
290 spec->out_original
291 );
297 DTTR_Result result = patch_spec_target(spec, &target);
298 if (!DTTR_ResultOK(result)) {
299 return result;
300 }
301
302 DTTR_Core_TargetReport target_report = {0};
303 result = DTTR_Core_PatchGroupInstallTargets(group, &target, 1u, &target_report);
304 if (!DTTR_ResultOK(result)) {
305 return result;
306 }
307
308 if (target_report.skipped_optional) {
309 return dttr_core_result(
311 "optional PCDOGS patch spec skipped"
312 );
313 }
314
315 return dttr_core_result(DTTR_OK, "ok");
316 }
317 default:
318 return dttr_core_result(
320 "unsupported PCDOGS patch spec kind"
321 );
322 }
323}
324
326 const DTTR_Core_Context *ctx,
327 const DTTR_PCDOGS_T_Patch_Spec *specs,
328 size_t spec_count,
329 DTTR_Core_PatchGroup **out_group,
331) {
332 patch_report_init(out_report);
333 if (!out_group || (!specs && spec_count)) {
336 "invalid PCDOGS patch spec install arguments"
337 );
338 patch_report_fail(out_report, 0, result);
339 return result;
340 }
341
342 if (*out_group) {
345 "PCDOGS patch group output is already set"
346 );
347 patch_report_fail(out_report, 0, result);
348 return result;
349 }
350
351 DTTR_Core_PatchGroup *group = NULL;
353 if (!DTTR_ResultOK(result)) {
354 patch_report_fail(out_report, 0, result);
355 return result;
356 }
357
358 for (size_t i = 0; i < spec_count; i++) {
359 if (out_report) {
360 out_report->attempted++;
361 }
362
363 result = patch_spec_install(group, &specs[i]);
364 if (!DTTR_ResultOK(result)) {
365 if (!specs[i].required
366 && (result.status == DTTR_ERR_NOT_FOUND
367 || result.status == DTTR_ERR_UNSUPPORTED)) {
368 if (out_report) {
369 out_report->skipped_optional++;
370 }
371
372 continue;
373 }
374
376 if (!DTTR_ResultOK(cleanup)) {
377 *out_group = group;
378 patch_report_fail(out_report, i, cleanup);
379 return cleanup;
380 }
381
382 patch_report_fail(out_report, i, result);
383 return result;
384 }
385
386 if (out_report) {
387 out_report->installed++;
388 }
389 }
390
391 *out_group = group;
392 return dttr_core_result(DTTR_OK, "ok");
393}
static void cleanup(DTTR_BackendState *state)
DTTR_Graphics_COM_Direct3DDevice7 void DWORD flags DWORD count
void void * ctx
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
DTTR_Graphics_COM_DirectDrawSurface7 DWORD DWORD void void DWORD flags DTTR_Graphics_COM_DirectDrawSurface7 void void *cb void * target
static DTTR_Result dttr_core_result(DTTR_Status status, const char *message)
DTTR_Result DTTR_Core_PatchGroupCreate(const DTTR_Core_Context *ctx, DTTR_Core_PatchGroup **out_group)
Definition core.c:607
DTTR_Result DTTR_Core_PatchGroupHookPointer(DTTR_Core_PatchGroup *group, uintptr_t address, void *new_value, void **out_original, DTTR_Core_Hook **out_hook)
Definition core.c:757
DTTR_Result DTTR_Core_PatchGroupRelease(DTTR_Core_PatchGroup **group)
Definition core.c:657
DTTR_Result DTTR_Core_HookPointer(const DTTR_Core_Context *ctx, uintptr_t address, void *new_value, void **out_original, DTTR_Core_Hook **out_hook)
Definition core.c:472
DTTR_Result DTTR_Core_PatchGroupHookFunction(DTTR_Core_PatchGroup *group, uintptr_t address, int prologue_size, void *detour, void **out_original, DTTR_Core_Hook **out_hook)
Definition core.c:726
@ DTTR_TARGET_ADDRESS_PATCH
Definition dttr_core.h:29
@ DTTR_TARGET_AOB_PATCH
Definition dttr_core.h:30
@ DTTR_TARGET_AOB_REL32_JMP
Definition dttr_core.h:35
DTTR_Result DTTR_Core_PatchGroupInstallTargets(DTTR_Core_PatchGroup *group, const DTTR_Core_TargetSpec *targets, size_t target_count, DTTR_Core_TargetReport *out_report)
Definition core.c:826
struct DTTR_Core_PatchGroup DTTR_Core_PatchGroup
Definition dttr_core.h:25
DTTR_PCDOGS_T_Symbol_Function_ID
Function symbol identifiers.
DTTR_PCDOGS_T_Data_ID
Stable global identifiers for the public SDK facade.
DTTR_PCDOGS_API const DTTR_PCDOGS_T_Symbol_Function * DTTR_PCDOGS_SymbolFunctionAt(uint32_t index)
#define DTTR_PCDOGS_SYMBOL_DATA_COUNT
@ DTTR_PCDOGS_PATCH_DATA_POINTER_HOOK
@ DTTR_PCDOGS_PATCH_TARGET
@ DTTR_PCDOGS_PATCH_AOB_REL32_JMP
@ DTTR_PCDOGS_PATCH_UNSUPPORTED
@ DTTR_PCDOGS_PATCH_AOB_BYTES
@ DTTR_PCDOGS_PATCH_FUNCTION_HOOK
@ DTTR_PCDOGS_PATCH_ADDRESS_BYTES
bool DTTR_PCDOGS_FunctionSymbolID(DTTR_PCDOGS_T_Function_ID id, DTTR_PCDOGS_T_Symbol_Function_ID *out_symbol_id)
DTTR_PCDOGS_API bool DTTR_PCDOGS_ResolveAll(const DTTR_Core_Context *ctx)
#define DTTR_PCDOGS_SYMBOL_FUNCTION_COUNT
DTTR_PCDOGS_T_Function_ID
Function identifiers for the public SDK facade.
bool DTTR_PCDOGS_DataSymbolID(DTTR_PCDOGS_T_Data_ID id, DTTR_PCDOGS_T_Symbol_Data_ID *out_symbol_id)
DTTR_PCDOGS_T_Symbol_Data_ID
Data symbol identifiers.
DTTR_PCDOGS_API const DTTR_PCDOGS_T_Symbol_Data * DTTR_PCDOGS_SymbolDataAt(uint32_t index)
@ DTTR_PCDOGS_HOOK_REL32
bool DTTR_ResultOK(DTTR_Result result)
Definition core.c:78
@ DTTR_ERR_INVALID_ARGUMENT
Definition dttr_result.h:15
@ DTTR_ERR_NOT_FOUND
Definition dttr_result.h:16
@ DTTR_OK
Definition dttr_result.h:14
@ DTTR_ERR_ALREADY_INSTALLED
Definition dttr_result.h:18
@ DTTR_ERR_UNSUPPORTED
Definition dttr_result.h:17
static void patch_report_fail(DTTR_PCDOGS_T_Patch_Report *report, size_t index, DTTR_Result result)
static DTTR_Result patch_spec_target(const DTTR_PCDOGS_T_Patch_Spec *spec, DTTR_Core_TargetSpec *out_target)
DTTR_Result DTTR_PCDOGS_Hook_DataPointer(const DTTR_Core_Context *ctx, DTTR_PCDOGS_T_Data_ID id, void *new_value, void **out_original, DTTR_Core_Hook **out_hook)
DTTR_Result DTTR_PCDOGS_PatchGroup_Install(const DTTR_Core_Context *ctx, const DTTR_PCDOGS_T_Patch_Spec *specs, size_t spec_count, DTTR_Core_PatchGroup **out_group, DTTR_PCDOGS_T_Patch_Report *out_report)
DTTR_Result DTTR_PCDOGS_DataResolve(const DTTR_Core_Context *ctx, DTTR_PCDOGS_T_Data_ID id, uintptr_t *out_addr)
static DTTR_Result patch_group_hook_symbol_function(DTTR_Core_PatchGroup *group, DTTR_PCDOGS_T_Symbol_Function_ID id, void *detour, void **out_original)
static uintptr_t global_address_at(uint32_t index)
DTTR_Result DTTR_PCDOGS_FunctionResolve(const DTTR_Core_Context *ctx, DTTR_PCDOGS_T_Function_ID id, uintptr_t *out_addr)
DTTR_Result DTTR_PCDOGS_PatchGroup_HookDataPointer(DTTR_Core_PatchGroup *group, DTTR_PCDOGS_T_Data_ID id, void *new_value, void **out_original)
static uintptr_t function_address_at(uint32_t index)
DTTR_Result DTTR_PCDOGS_SymbolDataResolve(const DTTR_Core_Context *ctx, DTTR_PCDOGS_T_Symbol_Data_ID id, uintptr_t *out_addr)
static DTTR_Result resolve_symbol(const DTTR_Core_Context *ctx, uint32_t id, uint32_t count, uintptr_t(*address_at)(uint32_t index), uintptr_t *out_addr, const char *invalid_message, const char *not_found_message)
DTTR_Result DTTR_PCDOGS_PatchGroup_HookFunction(DTTR_Core_PatchGroup *group, DTTR_PCDOGS_T_Function_ID id, void *detour, void **out_original)
static DTTR_Result patch_spec_install(DTTR_Core_PatchGroup *group, const DTTR_PCDOGS_T_Patch_Spec *spec)
DTTR_Result DTTR_PCDOGS_SymbolFunctionResolve(const DTTR_Core_Context *ctx, DTTR_PCDOGS_T_Symbol_Function_ID id, uintptr_t *out_addr)
static void patch_report_init(DTTR_PCDOGS_T_Patch_Report *report)
const DTTR_Core_Context * dttr_core_patch_group_context(const DTTR_Core_PatchGroup *group)
Definition core.c:672
void dttr_core_report_fail(DTTR_Core_TargetReport *report, size_t index, DTTR_Result result)
Definition core.c:912
void dttr_core_report_init(DTTR_Core_TargetReport *report)
Definition core.c:898
const uint8_t * patch_bytes
DTTR_PCDOGS_T_Data_ID global
DTTR_Core_TargetSpec target
DTTR_PCDOGS_T_Function_ID function
DTTR_PCDOGS_T_Patch_Kind kind
DTTR_PCDOGS_T_Hook_Kind hook_kind
DTTR_Status status
Definition dttr_result.h:37