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