home *** CD-ROM | disk | FTP | other *** search
- /*
- ** PatchUtil.c von Patrick Ohly
- ** unterstützende Funktionen für Patches
- ** © 1994 Patrick Ohly
- */
-
- #include <dos/dosextens.h>
-
- #ifdef _DCC
- #include <clib/exec_protos.h>
- #else
- #include <proto/exec.h>
- #endif
-
- #include <exec/memory.h>
- #include <exec/execbase.h>
- #include "PatchUtil.h"
-
- extern struct ExecBase *SysBase;
-
- /* Werte des Assembler-Befehls JMP */
- #define JMP_CMD 0x4EF9
-
- /* Aufbau der Assembler-Sprungbefehle: */
- #define JMP 0
- #define JMP_ADDR 1 /* ULONG */
- /* nur bei alter dos.library verwendet:
- ** erst D0 auf Funktions-abhängigen Wert setzen,
- ** dann DOS-dispatcher anspringen
- */
- #define MOVEQ 3
- #define JMP_DOS 4
- #define JMP_DOS_ADDR 5 /* ULONG */
- #define BUFFER_SIZE 7
-
- /*
- ** SafeSetFunction():
- ** Funktion: änderte einen Library-Vektor auf neue Funktion um
- **
- ** Argumente: library_base - zu patchende Library
- ** lvo - Offset der zu patchenden Funktion
- ** new_function - die eigene Funktion
- ** handle - Zeiger auf Langwort
- ** Ergebnis: old_function - Zeiger auf alte Funktion oder NULL für Fehler
- ** handle - wird für RemoveFunction() auf Zeiger
- ** des Sprungbefehls gesetzt
- */
-
- APTR SafeSetFunction(
- struct Library *library_base,
- LONG offset,
- APTR new_function,
- APTR *handle)
- {
- UWORD *asm_buffer;
- APTR result = NULL;
-
- if(asm_buffer = AllocMem(2 * BUFFER_SIZE, MEMF_CLEAR|MEMF_PUBLIC))
- {
- ULONG current_function;
- UWORD *vector;
- BOOL standard_lvo;
-
- *handle = asm_buffer;
-
- Disable();
-
- vector = (UWORD *)(((ULONG)library_base) + offset);
-
- /* Standard- und DOS-Format unterstützen */
- standard_lvo = (vector[0] == JMP_CMD);
-
- /* JMP- bzw. BRA-Zieladresse ermitteln */
- if(standard_lvo)
- current_function = *((ULONG *)&vector[1]);
- else
- current_function = (ULONG)vector +
- vector[2] + 4;
-
- /* eigene Funktion in asm_buffer eintragen */
- asm_buffer[JMP] = JMP_CMD;
- *((APTR *)&asm_buffer[JMP_ADDR]) = new_function;
- /* alten Inhalt retten */
- if(standard_lvo)
- result = (APTR)current_function;
- else
- {
- /* alten DOS-Aufruf nachstellen */
- /* moveq #?,d0 */
- asm_buffer[MOVEQ] = vector[0];
- asm_buffer[JMP_DOS] = JMP_CMD;
- *((ULONG *)&asm_buffer[JMP_DOS_ADDR]) =
- current_function;
- result = &asm_buffer[MOVEQ];
- }
-
- /* neuen Zeiger in LVO eintragen */
- vector[0] = JMP_CMD;
- *((ULONG *)&vector[1]) = (ULONG)asm_buffer;
-
- if(SysBase->LibNode.lib_Version >= 36)
- CacheClearU();
-
- /* Library neu berechnen */
- library_base->lib_Flags |= LIBF_CHANGED;
- SumLibrary(library_base);
-
- Enable();
- }
-
- return(result);
- }
-
- /*
- ** RemoveFunction()
- ** Funktion: macht SafeSetFunction() rückgängig
- **
- ** Argumente: old_function - der Funktionswert, der zurückgeschrieben wird
- ** handle - der von SafeSetFunction() gesetzte Wert
- */
-
- VOID RemoveFunction(APTR old_function, APTR handle)
- {
- Disable();
-
- /* alten Wert zurückschreiben */
- *((APTR *)&(((UWORD *)handle)[JMP_ADDR])) = old_function;
-
- if(SysBase->LibNode.lib_Version >= 36)
- CacheClearU();
-
- Enable();
- }
-
- /*
- ** IsProcess:
- ** Funktion: testet auf Process
- ** Ergebnis: TRUE zurück, wenn von einem Prozeß aufgerufen,
- ** ansonsten FALSE
- */
- BOOL IsProcess(VOID)
- {
- struct Task *my_task;
-
- my_task = FindTask(NULL);
- return((BOOL)
- (my_task->tc_Node.ln_Type == NT_PROCESS));
- }
-