home *** CD-ROM | disk | FTP | other *** search
- /*
- * ToolAlias
- *
- * Commodity that patches loadseg to substitute specific programs
- * with others. With settings window and hotkey. Patches may be
- * disabled and re-enabled via Commodities Exchange.
- *
- * Martin W. Scott, 5 February 1993
- */
- #include <exec/types.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <exec/semaphores.h>
- #include <dos/dos.h>
- #include <libraries/commodities.h>
- #include <string.h>
- #include <clib/alib_protos.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/commodities.h>
-
- #include "icon.h"
- #include "list.h"
- #include "file.h"
- #include "window.h"
-
- #define ASM __asm __saveds
- #define REG(x) register __## x
-
- /* Local protos */
- BOOL OpenLibs(void);
- VOID CloseLibs(void);
- VOID _main(VOID);
- LONG ProcessMsg(void);
- BOOL InstallWedge(VOID);
- BOOL RemoveWedge(VOID);
- struct JumpTable *GetJumpTable(UBYTE *);
-
- /* Libraries etc. */
- extern struct WBStartup *WBenchMsg;
- extern struct DosLibrary *DOSBase;
- struct IntuitionBase *IntuitionBase;
- struct Library *CxBase, *IconBase, *GadToolsBase;
- struct GfxBase *GfxBase;
-
- /* The number of 'replacement' functions */
- #define NUMBEROFFUNCTIONS (1)
-
- /* prototypes for the functions to be SetFunction()'ed. */
- #define DEC_LVO(lvoname) extern lvoname
-
- /* declare stuff for standard dos one-parameter function */
- /* UBYTE * in d1 */
- #define DEC11_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(a6) struct Library *base)
- #define DEC11_NEW(newname) LONG ASM newname(REG(d1) UBYTE *, REG(a6) struct Library *base)
- #define DEC11(name) DEC11_OLD(old## name); DEC11_NEW(new## name); DEC_LVO(LVO## name)
-
- /* the patched functions themselves */
- DEC11(LoadSeg);
-
- /* Use a table and an array to make it a little more generic and easier to
- * add functions.
- */
- struct LVOTable
- {
- LONG lt_LVO;
- struct Library *lt_LibBase;
- ULONG lt_oldFunction;
- ULONG lt_newFunction;
- };
-
- struct LVOTable LVOArray[] =
- {
- {&LVOLoadSeg, (struct Library *) & DOSBase, &oldLoadSeg, &newLoadSeg}
- };
-
- struct JumpTable
- {
- struct SignalSemaphore jt_Semaphore;
- UWORD pad_word;
- struct Task *jt_Owner;
- UBYTE jt_Function[NUMBEROFFUNCTIONS * 6];
- };
-
- /* Strings */
- /* The name this JumpTable/Semaphore will get. */
- static UBYTE *JTName = "ToolAlias-JT";
- static UBYTE *VersTag = "\0$VER: ToolAlias 1.02";
-
- /* Commodity globals */
- CxObj *broker, *popobj;
- struct MsgPort *broker_mp;
-
- struct NewBroker newbroker =
- {
- NB_VERSION,
- "ToolAlias",
- "ToolAlias 1.02",
- "Name substitution facility",
- NBU_UNIQUE | NBU_NOTIFY,
- COF_SHOW_HIDE
- };
-
- #define EVT_POPKEY 1L
- ULONG cxsigflag, wndsigflag;
- UBYTE popstr[100];
- int wedged = 1; /* initially, wedges will be in place */
-
- /* close what we opened */
- VOID
- CloseLibs()
- {
- if (IntuitionBase)
- CloseLibrary(IntuitionBase);
- if (IconBase)
- CloseLibrary(IconBase);
- if (GfxBase)
- CloseLibrary(GfxBase);
- if (GadToolsBase)
- CloseLibrary(GadToolsBase);
- if (CxBase)
- CloseLibrary(CxBase);
- }
-
- /* open libraries, devices that we need */
- BOOL
- OpenLibs()
- {
- if ((IntuitionBase = (void *) OpenLibrary("intuition.library", 37L)) &&
- (IconBase = (void *) OpenLibrary("icon.library", 37L)) &&
- (GfxBase = (void *) OpenLibrary("graphics.library", 37L)) &&
- (GadToolsBase = OpenLibrary("gadtools.library", 37L)) &&
- (CxBase = OpenLibrary("commodities.library", 37L)))
- {
- return TRUE;
- }
- CloseLibs();
- return FALSE;
- }
-
- /* pop up a requester */
- void
- EasyEasyRequest(char *str)
- {
- struct EasyStruct es;
-
- es.es_StructSize = sizeof(struct EasyStruct);
-
- es.es_Flags = 0L;
- es.es_Title = "ToolAlias Message";
- es.es_TextFormat = str;
- es.es_GadgetFormat = "OK";
- EasyRequestArgs(NULL, &es, NULL, NULL);
- }
-
- #define Msg(s) EasyEasyRequest(s)
-
- VOID
- _main(VOID)
- {
- if (OpenLibs())
- {
- if (get_config(DEF_CONFIG))
- {
- if (broker_mp = CreateMsgPort())
- {
- GetOurIcon(WBenchMsg);
- newbroker.nb_Pri = (BYTE) TTInt("CX_PRIORITY", 0);
- strcpy(popstr, TTString("CX_POPKEY", "control alt t"));
-
- newbroker.nb_Port = broker_mp;
- if (broker = CxBroker(&newbroker, NULL))
- {
- if (popobj = HotKey(popstr, broker_mp, EVT_POPKEY))
- {
- AttachCxObj(broker, popobj);
- cxsigflag = 1L << broker_mp->mp_SigBit;
- ActivateCxObj(broker, 1L);
-
- if (TTBool("CX_POPUP", TRUE))
- ShowWindow();
- FreeOurIcon();
- if (InstallWedge())
- while (ProcessMsg());
- else
- Msg("Couldn't install patches");
-
- HideWindow();
- if (wedged)
- RemoveWedge();
- }
- else
- Msg("Couldn't create HotKey");
- DeleteCxObjAll(broker);
- }
- FreeOurIcon(); /* can be called twice avec no probs */
-
- DeleteMsgPort(broker_mp);
-
- }
- else
- Msg("Couldn't create port");
-
- free_list(); /* free memory */
- }
- CloseLibs();
- }
- }
-
- LONG
- ProcessMsg(void)
- {
- CxMsg *msg;
- ULONG sigrcvd, msgid, msgtype;
- LONG returnvalue = 1L;
- LONG gui_rc;
-
- /* wait for something to happen */
- sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag | wndsigflag);
-
- if (sigrcvd & wndsigflag) /* settings change */
- if (gui_rc = HandleIDCMP())
- {
- returnvalue = 0;
- if (gui_rc == GUI_ABEND)
- Msg("No memory - terminating");
- }
-
- /* process any messages */
- while (msg = (CxMsg *) GetMsg(broker_mp))
- {
- /* Extract necessary information from the CxMessage and return it */
- msgid = CxMsgID(msg);
- msgtype = CxMsgType(msg);
- ReplyMsg((struct Message *) msg);
-
- if (msgtype == CXM_IEVENT) /* popkey */
- {
- if (msgid == EVT_POPKEY)
- ShowWindow();
- }
- else if (msgtype == CXM_COMMAND) /* std commodity message */
- {
- switch (msgid)
- {
- case CXCMD_UNIQUE:
- case CXCMD_APPEAR:
- ShowWindow(); /* check error return? */
- break;
-
- case CXCMD_DISAPPEAR:
- HideWindow();
- break;
-
- case CXCMD_DISABLE:
- if (wedged)
- {
- RemoveWedge();
- wedged = 0;
- }
- ActivateCxObj(broker, 0L);
- break;
-
- case CXCMD_ENABLE:
- if (!wedged)
- {
- InstallWedge();
- wedged = 1;
- }
- ActivateCxObj(broker, 1L);
- break;
-
- case CXCMD_KILL:
- returnvalue = 0L;
- break;
- }
- }
- }
-
- /* Test to see if user tried to break */
- if (sigrcvd & SIGBREAKF_CTRL_C)
- returnvalue = 0L;
-
- return (returnvalue);
- }
-
- BOOL
- InstallWedge(VOID)
- {
- struct JumpTable *jumptable;
- ULONG *addressptr;
- UCOUNT i, j;
-
- Forbid();
-
- /* Get pointer to JumpTable. Create it if necessary */
- if (jumptable = GetJumpTable(JTName))
- {
- /* Try to get exclusive lock on semaphore, in case it already existed. */
- if (AttemptSemaphore((struct SignalSemaphore *) jumptable))
- {
- /* Make sure nobody else has function addresses in the jumptable */
- if (jumptable->jt_Owner == NULL)
- {
- jumptable->jt_Owner = FindTask(0);
- /* Don't want to disable any longer than necessary */
- Disable();
-
- for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
- {
- /* Replace addresses in the jumptable with my own. */
- addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
- (*((ULONG *) LVOArray[j].lt_oldFunction)) = (ULONG) * addressptr;
- *addressptr = (ULONG) LVOArray[j].lt_newFunction;
- }
- CacheClearU();
- Enable();
- }
- else
- Msg("Already running.\n");
- ReleaseSemaphore((struct SignalSemaphore *) jumptable);
- }
- else
- Msg("Can't lock table.\n");
- }
- else
- Msg("Can't create jumptable\n");
- Permit();
- return ((BOOL) jumptable);
- }
-
- BOOL
- RemoveWedge(VOID)
- {
- struct JumpTable *jumptable;
- ULONG *addressptr;
- UCOUNT i, j;
-
- Forbid();
-
- if (jumptable = GetJumpTable(JTName))
- {
- /* Check if this task owns this jumptable */
- if (jumptable->jt_Owner == FindTask(0))
- {
-
- /* Get the semaphore exclusively.
- * Depending on what got SetFunction()'ed this could take some time.
- * Also note that shared locks are used to indicate the code is
- * being executed and that shared locks can jump ahead of queue'ed
- * exclusive locks, adding to the waittime.
- */
- ObtainSemaphore((struct SignalSemaphore *) jumptable);
-
- Disable();
-
- /* Restore old pointers in jumptable */
-
- for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
- {
- addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
- *addressptr = (*((ULONG *) LVOArray[j].lt_oldFunction));
- }
- CacheClearU();
- Enable();
-
- jumptable->jt_Owner = NULL;
- ReleaseSemaphore((struct SignalSemaphore *) jumptable);
- }
- }
- Permit();
-
- return (TRUE);
- }
-
- struct JumpTable *
- GetJumpTable(UBYTE * name)
- {
- struct JumpTable *jumptable;
- ULONG *addressptr;
- UWORD *jmpinstr;
- UBYTE *jtname;
- UCOUNT i, j;
-
- /* Not really necessary to forbid again, just to indicate that I don't
- * want another task to create the semaphore while I'm trying to do the
- * same. Here GetJumpTable() is only called from InstallWedge(), so it
- * will just bump the forbid count.
- */
- Forbid();
-
- if (!(jumptable = (struct JumpTable *) FindSemaphore(name)))
- {
- if (jumptable = AllocMem(sizeof(struct JumpTable), MEMF_PUBLIC | MEMF_CLEAR))
- {
- if (jtname = AllocMem(strlen(name) + 1, MEMF_PUBLIC | MEMF_CLEAR))
- {
-
- for (i = 0, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
- {
- jmpinstr = (UWORD *) ((UBYTE *) jumptable->jt_Function + i);
- *jmpinstr = 0x4EF9;
-
- addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i + 2);
- *addressptr = (ULONG) SetFunction(
- (struct Library *) (*((ULONG *) LVOArray[j].lt_LibBase)),
- LVOArray[j].lt_LVO,
- (VOID *) ((UBYTE *) jumptable->jt_Function + i));
- }
-
- jumptable->jt_Semaphore.ss_Link.ln_Pri = 0;
-
- strcpy(jtname, name);
- jumptable->jt_Semaphore.ss_Link.ln_Name = jtname;
- AddSemaphore((struct SignalSemaphore *) jumptable);
- }
- else
- {
- FreeMem(jumptable, sizeof(struct JumpTable));
-
- jumptable = NULL;
- }
- }
- }
- Permit();
-
- /* If succeeded, you now have a jumptable which entries point to the original
- * library functions. If another task SetFunction()'ed one or more of those
- * already, that task can never go away anymore.
- */
- return (jumptable);
- }
-
-
- /******************************************************************************/
- /******************* **************************/
- /******************* NEW DOS ROUTINES START HERE **************************/
- /******************* **************************/
- /******************************************************************************/
-
- LONG ASM
- newLoadSeg(REG(d1) UBYTE * name, REG(a6) struct Library * base)
- {
- struct SignalSemaphore *jt;
- char *newname;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (name && (newname = find_tool(name)))
- rc = oldLoadSeg(newname, DOSBase);
- else
- rc = oldLoadSeg(name, DOSBase);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-