home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 10 / amigaformatcd10.iso / -look_here_1st!- / handy_tools / toolalias / source / talias.c < prev    next >
C/C++ Source or Header  |  1993-03-15  |  11KB  |  461 lines

  1. /*
  2.  * ToolAlias
  3.  * 
  4.  * Commodity that patches loadseg to substitute specific programs
  5.  * with others. With settings window and hotkey. Patches may be
  6.  * disabled and re-enabled via Commodities Exchange.
  7.  * 
  8.  * Martin W. Scott,  5 February 1993
  9.  */
  10. #include <exec/types.h>
  11. #include <exec/execbase.h>
  12. #include <exec/memory.h>
  13. #include <exec/semaphores.h>
  14. #include <dos/dos.h>
  15. #include <libraries/commodities.h>
  16. #include <string.h>
  17. #include <clib/alib_protos.h>
  18. #include <proto/dos.h>
  19. #include <proto/exec.h>
  20. #include <proto/commodities.h>
  21.  
  22. #include "icon.h"
  23. #include "list.h"
  24. #include "file.h"
  25. #include "window.h"
  26.  
  27. #define ASM __asm __saveds
  28. #define REG(x) register __## x
  29.  
  30. /* Local protos */
  31. BOOL OpenLibs(void);
  32. VOID CloseLibs(void);
  33. VOID _main(VOID);
  34. LONG ProcessMsg(void);
  35. BOOL InstallWedge(VOID);
  36. BOOL RemoveWedge(VOID);
  37. struct JumpTable *GetJumpTable(UBYTE *);
  38.  
  39. /* Libraries etc. */
  40. extern struct WBStartup *WBenchMsg;
  41. extern struct DosLibrary *DOSBase;
  42. struct IntuitionBase *IntuitionBase;
  43. struct Library *CxBase, *IconBase, *GadToolsBase;
  44. struct GfxBase *GfxBase;
  45.  
  46. /* The number of 'replacement' functions */
  47. #define NUMBEROFFUNCTIONS (1)
  48.  
  49. /* prototypes for the functions to be SetFunction()'ed. */
  50. #define DEC_LVO(lvoname)   extern lvoname
  51.  
  52. /* declare stuff for standard dos one-parameter function */
  53. /* UBYTE * in d1 */
  54. #define DEC11_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(a6) struct Library *base)
  55. #define DEC11_NEW(newname) LONG ASM newname(REG(d1) UBYTE *, REG(a6) struct Library *base)
  56. #define DEC11(name) DEC11_OLD(old## name); DEC11_NEW(new## name); DEC_LVO(LVO## name)
  57.  
  58. /* the patched functions themselves */
  59. DEC11(LoadSeg);
  60.  
  61. /* Use a table and an array to make it a little more generic and easier to
  62.  * add functions.
  63.  */
  64. struct LVOTable
  65. {
  66.     LONG lt_LVO;
  67.     struct Library *lt_LibBase;
  68.     ULONG lt_oldFunction;
  69.     ULONG lt_newFunction;
  70. };
  71.  
  72. struct LVOTable LVOArray[] =
  73. {
  74.     {&LVOLoadSeg, (struct Library *) & DOSBase, &oldLoadSeg, &newLoadSeg}
  75. };
  76.  
  77. struct JumpTable
  78. {
  79.     struct SignalSemaphore jt_Semaphore;
  80.     UWORD pad_word;
  81.     struct Task *jt_Owner;
  82.     UBYTE jt_Function[NUMBEROFFUNCTIONS * 6];
  83. };
  84.  
  85. /* Strings */
  86. /* The name this JumpTable/Semaphore will get. */
  87. static UBYTE *JTName = "ToolAlias-JT";
  88. static UBYTE *VersTag = "\0$VER: ToolAlias 1.02";
  89.  
  90. /* Commodity globals */
  91. CxObj *broker, *popobj;
  92. struct MsgPort *broker_mp;
  93.  
  94. struct NewBroker newbroker =
  95. {
  96.     NB_VERSION,
  97.     "ToolAlias",
  98.     "ToolAlias 1.02",
  99.     "Name substitution facility",
  100.     NBU_UNIQUE | NBU_NOTIFY,
  101.     COF_SHOW_HIDE
  102. };
  103.  
  104. #define EVT_POPKEY 1L
  105. ULONG cxsigflag, wndsigflag;
  106. UBYTE popstr[100];
  107. int wedged = 1;            /* initially, wedges will be in place */
  108.  
  109. /* close what we opened */
  110. VOID
  111. CloseLibs()
  112. {
  113.     if (IntuitionBase)
  114.     CloseLibrary(IntuitionBase);
  115.     if (IconBase)
  116.     CloseLibrary(IconBase);
  117.     if (GfxBase)
  118.     CloseLibrary(GfxBase);
  119.     if (GadToolsBase)
  120.     CloseLibrary(GadToolsBase);
  121.     if (CxBase)
  122.     CloseLibrary(CxBase);
  123. }
  124.  
  125. /* open libraries, devices that we need */
  126. BOOL
  127. OpenLibs()
  128. {
  129.     if ((IntuitionBase = (void *) OpenLibrary("intuition.library", 37L)) &&
  130.     (IconBase = (void *) OpenLibrary("icon.library", 37L)) &&
  131.     (GfxBase = (void *) OpenLibrary("graphics.library", 37L)) &&
  132.     (GadToolsBase = OpenLibrary("gadtools.library", 37L)) &&
  133.     (CxBase = OpenLibrary("commodities.library", 37L)))
  134.     {
  135.     return TRUE;
  136.     }
  137.     CloseLibs();
  138.     return FALSE;
  139. }
  140.  
  141. /* pop up a requester */
  142. void
  143. EasyEasyRequest(char *str)
  144. {
  145.     struct EasyStruct es;
  146.  
  147.     es.es_StructSize = sizeof(struct EasyStruct);
  148.  
  149.     es.es_Flags = 0L;
  150.     es.es_Title = "ToolAlias Message";
  151.     es.es_TextFormat = str;
  152.     es.es_GadgetFormat = "OK";
  153.     EasyRequestArgs(NULL, &es, NULL, NULL);
  154. }
  155.  
  156. #define Msg(s) EasyEasyRequest(s)
  157.  
  158. VOID
  159. _main(VOID)
  160. {
  161.     if (OpenLibs())
  162.     {
  163.     if (get_config(DEF_CONFIG))
  164.     {
  165.         if (broker_mp = CreateMsgPort())
  166.         {
  167.         GetOurIcon(WBenchMsg);
  168.         newbroker.nb_Pri = (BYTE) TTInt("CX_PRIORITY", 0);
  169.         strcpy(popstr, TTString("CX_POPKEY", "control alt t"));
  170.  
  171.         newbroker.nb_Port = broker_mp;
  172.         if (broker = CxBroker(&newbroker, NULL))
  173.         {
  174.             if (popobj = HotKey(popstr, broker_mp, EVT_POPKEY))
  175.             {
  176.             AttachCxObj(broker, popobj);
  177.             cxsigflag = 1L << broker_mp->mp_SigBit;
  178.             ActivateCxObj(broker, 1L);
  179.  
  180.             if (TTBool("CX_POPUP", TRUE))
  181.                 ShowWindow();
  182.             FreeOurIcon();
  183.             if (InstallWedge())
  184.                 while (ProcessMsg());
  185.             else
  186.                 Msg("Couldn't install patches");
  187.  
  188.             HideWindow();
  189.             if (wedged)
  190.                 RemoveWedge();
  191.             }
  192.             else
  193.             Msg("Couldn't create HotKey");
  194.             DeleteCxObjAll(broker);
  195.         }
  196.         FreeOurIcon();    /* can be called twice avec no probs */
  197.  
  198.         DeleteMsgPort(broker_mp);
  199.  
  200.         }
  201.         else
  202.         Msg("Couldn't create port");
  203.  
  204.         free_list();    /* free memory */
  205.     }
  206.     CloseLibs();
  207.     }
  208. }
  209.  
  210. LONG
  211. ProcessMsg(void)
  212. {
  213.     CxMsg *msg;
  214.     ULONG sigrcvd, msgid, msgtype;
  215.     LONG returnvalue = 1L;
  216.     LONG gui_rc;
  217.  
  218.     /* wait for something to happen */
  219.     sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag | wndsigflag);
  220.  
  221.     if (sigrcvd & wndsigflag)    /* settings change */
  222.     if (gui_rc = HandleIDCMP())
  223.     {
  224.         returnvalue = 0;
  225.         if (gui_rc == GUI_ABEND)
  226.         Msg("No memory - terminating");
  227.     }
  228.  
  229.     /* process any messages */
  230.     while (msg = (CxMsg *) GetMsg(broker_mp))
  231.     {
  232.     /* Extract necessary information from the CxMessage and return it */
  233.     msgid = CxMsgID(msg);
  234.     msgtype = CxMsgType(msg);
  235.     ReplyMsg((struct Message *) msg);
  236.  
  237.     if (msgtype == CXM_IEVENT)    /* popkey */
  238.     {
  239.         if (msgid == EVT_POPKEY)
  240.         ShowWindow();
  241.     }
  242.     else if (msgtype == CXM_COMMAND)    /* std commodity message */
  243.     {
  244.         switch (msgid)
  245.         {
  246.         case CXCMD_UNIQUE:
  247.         case CXCMD_APPEAR:
  248.         ShowWindow();    /* check error return? */
  249.         break;
  250.  
  251.         case CXCMD_DISAPPEAR:
  252.         HideWindow();
  253.         break;
  254.  
  255.         case CXCMD_DISABLE:
  256.         if (wedged)
  257.         {
  258.             RemoveWedge();
  259.             wedged = 0;
  260.         }
  261.         ActivateCxObj(broker, 0L);
  262.         break;
  263.  
  264.         case CXCMD_ENABLE:
  265.         if (!wedged)
  266.         {
  267.             InstallWedge();
  268.             wedged = 1;
  269.         }
  270.         ActivateCxObj(broker, 1L);
  271.         break;
  272.  
  273.         case CXCMD_KILL:
  274.         returnvalue = 0L;
  275.         break;
  276.         }
  277.     }
  278.     }
  279.  
  280.     /* Test to see if user tried to break */
  281.     if (sigrcvd & SIGBREAKF_CTRL_C)
  282.     returnvalue = 0L;
  283.  
  284.     return (returnvalue);
  285. }
  286.  
  287. BOOL
  288. InstallWedge(VOID)
  289. {
  290.     struct JumpTable *jumptable;
  291.     ULONG *addressptr;
  292.     UCOUNT i, j;
  293.  
  294.     Forbid();
  295.  
  296.     /* Get pointer to JumpTable. Create it if necessary */
  297.     if (jumptable = GetJumpTable(JTName))
  298.     {
  299.     /* Try to get exclusive lock on semaphore, in case it already existed. */
  300.     if (AttemptSemaphore((struct SignalSemaphore *) jumptable))
  301.     {
  302.         /* Make sure nobody else has function addresses in the jumptable */
  303.         if (jumptable->jt_Owner == NULL)
  304.         {
  305.         jumptable->jt_Owner = FindTask(0);
  306.         /* Don't want to disable any longer than necessary */
  307.         Disable();
  308.  
  309.         for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
  310.         {
  311.             /* Replace addresses in the jumptable with my own. */
  312.             addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
  313.             (*((ULONG *) LVOArray[j].lt_oldFunction)) = (ULONG) * addressptr;
  314.             *addressptr = (ULONG) LVOArray[j].lt_newFunction;
  315.         }
  316.         CacheClearU();
  317.         Enable();
  318.         }
  319.         else
  320.         Msg("Already running.\n");
  321.         ReleaseSemaphore((struct SignalSemaphore *) jumptable);
  322.     }
  323.     else
  324.         Msg("Can't lock table.\n");
  325.     }
  326.     else
  327.     Msg("Can't create jumptable\n");
  328.     Permit();
  329.     return ((BOOL) jumptable);
  330. }
  331.  
  332. BOOL
  333. RemoveWedge(VOID)
  334. {
  335.     struct JumpTable *jumptable;
  336.     ULONG *addressptr;
  337.     UCOUNT i, j;
  338.  
  339.     Forbid();
  340.  
  341.     if (jumptable = GetJumpTable(JTName))
  342.     {
  343.     /* Check if this task owns this jumptable */
  344.     if (jumptable->jt_Owner == FindTask(0))
  345.     {
  346.  
  347.         /* Get the semaphore exclusively.
  348.              * Depending on what got SetFunction()'ed this could take some time.
  349.              * Also note that shared locks are used to indicate the code is
  350.              * being executed and that shared locks can jump ahead of queue'ed
  351.              * exclusive locks, adding to the waittime.
  352.              */
  353.         ObtainSemaphore((struct SignalSemaphore *) jumptable);
  354.  
  355.         Disable();
  356.  
  357.         /* Restore old pointers in jumptable */
  358.  
  359.         for (i = 2, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
  360.         {
  361.         addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i);
  362.         *addressptr = (*((ULONG *) LVOArray[j].lt_oldFunction));
  363.         }
  364.         CacheClearU();
  365.         Enable();
  366.  
  367.         jumptable->jt_Owner = NULL;
  368.         ReleaseSemaphore((struct SignalSemaphore *) jumptable);
  369.     }
  370.     }
  371.     Permit();
  372.  
  373.     return (TRUE);
  374. }
  375.  
  376. struct JumpTable *
  377. GetJumpTable(UBYTE * name)
  378. {
  379.     struct JumpTable *jumptable;
  380.     ULONG *addressptr;
  381.     UWORD *jmpinstr;
  382.     UBYTE *jtname;
  383.     UCOUNT i, j;
  384.  
  385.     /* Not really necessary to forbid again, just to indicate that I don't
  386.      * want another task to create the semaphore while I'm trying to do the
  387.      * same. Here GetJumpTable() is only called from InstallWedge(), so it
  388.      * will just bump the forbid count.
  389.      */
  390.     Forbid();
  391.  
  392.     if (!(jumptable = (struct JumpTable *) FindSemaphore(name)))
  393.     {
  394.     if (jumptable = AllocMem(sizeof(struct JumpTable), MEMF_PUBLIC | MEMF_CLEAR))
  395.     {
  396.         if (jtname = AllocMem(strlen(name) + 1, MEMF_PUBLIC | MEMF_CLEAR))
  397.         {
  398.  
  399.         for (i = 0, j = 0; i < NUMBEROFFUNCTIONS * 6; i += 6, j++)
  400.         {
  401.             jmpinstr = (UWORD *) ((UBYTE *) jumptable->jt_Function + i);
  402.             *jmpinstr = 0x4EF9;
  403.  
  404.             addressptr = (ULONG *) ((UBYTE *) jumptable->jt_Function + i + 2);
  405.             *addressptr = (ULONG) SetFunction(
  406.             (struct Library *) (*((ULONG *) LVOArray[j].lt_LibBase)),
  407.                              LVOArray[j].lt_LVO,
  408.                (VOID *) ((UBYTE *) jumptable->jt_Function + i));
  409.         }
  410.  
  411.         jumptable->jt_Semaphore.ss_Link.ln_Pri = 0;
  412.  
  413.         strcpy(jtname, name);
  414.         jumptable->jt_Semaphore.ss_Link.ln_Name = jtname;
  415.         AddSemaphore((struct SignalSemaphore *) jumptable);
  416.         }
  417.         else
  418.         {
  419.         FreeMem(jumptable, sizeof(struct JumpTable));
  420.  
  421.         jumptable = NULL;
  422.         }
  423.     }
  424.     }
  425.     Permit();
  426.  
  427.     /* If succeeded, you now have a jumptable which entries point to the original
  428.      * library functions. If another task SetFunction()'ed one or more of those
  429.      * already, that task can never go away anymore.
  430.      */
  431.     return (jumptable);
  432. }
  433.  
  434.  
  435. /******************************************************************************/
  436. /*******************                                 **************************/
  437. /*******************   NEW DOS ROUTINES START HERE   **************************/
  438. /*******************                                 **************************/
  439. /******************************************************************************/
  440.  
  441. LONG ASM
  442. newLoadSeg(REG(d1) UBYTE * name, REG(a6) struct Library * base)
  443. {
  444.     struct SignalSemaphore *jt;
  445.     char *newname;
  446.     LONG rc = 0;
  447.  
  448.     if (jt = FindSemaphore(JTName))
  449.     {
  450.     ObtainSemaphoreShared(jt);
  451.  
  452.     if (name && (newname = find_tool(name)))
  453.         rc = oldLoadSeg(newname, DOSBase);
  454.     else
  455.         rc = oldLoadSeg(name, DOSBase);
  456.  
  457.     ReleaseSemaphore(jt);
  458.     }
  459.     return rc;
  460. }
  461.