A hook function must accept the following three parameters in these specific registers: A0 - Pointer to the hook structure. A2 - Pointer to an object to manipulate. The object is context specific. A1 - Pointer to a message packet. This is also context specific. For a callback function written in C, the parameters should appear in this order: myCallbackFunction(Pointer to Hook (A0), Pointer to Object (A2), Pointer to message (A1)); This is because the standard C stub pushes the parameters onto the stack in the following order: A1, A2, A0. The following assembly language routine is a callback stub for C: INCLUDE 'exec/types.i' INCLUDE 'utility/hooks.i' xdef _hookEntry _hookEntry: move.l a1,-(sp) ; push message packet pointer move.l a2,-(sp) ; push object pointer move.l a0,-(sp) ; push hook pointer move.l h_SubEntry(a0),a0 ; fetch actual Hook entry point ... jsr (a0) ; and call it lea 12(sp),sp ; fix stack rts If your C compiler supports registerized parameters, your callback functions can get the parameters directly from the CPU registers instead of having to use a stub to push them on the stack. The following C language routine uses registerized parameters to put parameters in the right registers. This routine requires a C compiler that supports registerized parameters. #include <exec/types.h> #include <utility/hooks.h> #define ASM __asm #define REG(x) register __ ## x /* This function converts register-parameter hook calling * convention into standard C conventions. It requires a C * compiler that supports registerized parameters, such as * SAS/C 5.xx or greater. */ ULONG ASM hookEntry(REG(a0) struct Hook *h, REG(a2) VOID *o, REG(a1) VOID *msg) { return ((*h->h_SubEntry)(h, o, msg)); } A callback function is executed on the context of the module that invoked it. This usually means that callback functions cannot call functions that need to look at environment specific data. For example, printf() needs to look at the current process's input and output stream. Entities like Intuition have no input and output stream. This also means that in order for the function to access any of its global data, it needs to make sure the CPU can find the function's data segment. It does this by forcing the function to load the offset for the program's data segment into CPU register A4. See your compiler documentation for details. The following is a simple function that can be used in a callback hook. ULONG MyFunction (struct Hook *h, VOID *o, VOID *msg) { /* A SASC and Manx function that obtains access to the global data segment */ geta4(); /* Debugging function to send a string to the serial port */ KPrintF("Inside MyFunction()\n"); return (1); } The next step is to initialize the hook for use. this basically means that the fields of the Hook structure must be filled with appropriate values. The following simple function initializes a hook structure. /* This simple function is used to initialize a Hook */ VOID InitHook (struct Hook *h, ULONG (*func)(), VOID *data) { /* Make sure a pointer was passed */ if (h) { /* Fill in the hook fields */ h->h_Entry = (ULONG (*)()) hookEntry; h->h_SubEntry = func; h->h_Data = data; } } The following is a simple example of a callback hook function. hooks1.c