home *** CD-ROM | disk | FTP | other *** search
- #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 <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/commodities.h>
-
- #define ASM __asm __saveds
- #define REG(x) register __## x
-
- /*#define DEBUG*/
-
- #ifdef DEBUG
- #define BEEP DisplayBeep(NULL);
- #else
- #define BEEP
- #endif
-
- /* Local protos */
- VOID _main(VOID);
- LONG ProcessMsg(void);
- BOOL InstallWedge(VOID);
- BOOL RemoveWedge(VOID);
- struct JumpTable *GetJumpTable(UBYTE *);
-
- /* Libraries */
- extern struct ExecBase *SysBase;
- extern struct DosLibrary *DOSBase;
- struct Library *CxBase;
- #ifdef DEBUG
- struct IntuitionBase *IntuitionBase;
- #endif
- /* The number of 'replacement' functions */
- #define NUMBEROFFUNCTIONS (15)
-
- /* prototypes for the functions to be SetFunction()'ed. */
- #define DEC_LVO(lvoname) extern lvoname
-
- /* declare stuff for standard 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)
-
- /* declare stuff for standard two-parameter function */
- /* UBYTE * in d1 */
- #define DEC21_OLD(oldname) LONG (*ASM oldname) (REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
- #define DEC21_NEW(newname) LONG ASM newname(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *base)
- #define DEC21(name) DEC21_OLD(old## name); DEC21_NEW(new## name); DEC_LVO(LVO## name)
-
- /* declare stuff for standard two-parameter function */
- /* UBYTE * in d2 */
- #define DEC22_OLD(oldname) LONG (*ASM oldname) (REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
- #define DEC22_NEW(newname) LONG ASM newname(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *base)
- #define DEC22(name) DEC22_OLD(old## name); DEC22_NEW(new## name); DEC_LVO(LVO## name)
-
- /* the patched functions themselves */
- DEC11(CreateDir);
- DEC11(DeleteFile);
- DEC11(LoadSeg);
- DEC21(Lock);
- DEC21(NewLoadSeg);
- DEC21(Open);
- DEC21(SetComment);
- DEC21(SetFileDate);
- DEC21(SetFileSize);
- DEC21(SetProtection);
- DEC22(AssignLate);
- DEC22(AssignPath);
- DEC21(MatchFirst);
-
- /* manually decalred, because different from standard */
- LONG (*ASM oldRename) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
- LONG ASM newRename(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(a6) struct Library *);
- extern LVORename;
-
- LONG (*ASM oldParsePattern) (REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
- LONG ASM newParsePattern(REG(d1) UBYTE *, REG(d2) UBYTE *, REG(d3) LONG, REG(a6) struct Library *);
- extern LVOParsePattern;
-
- /* 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[] =
- {
- {&LVOCreateDir, (struct Library *) & DOSBase, &oldCreateDir, &newCreateDir },
- {&LVODeleteFile, (struct Library *) & DOSBase, &oldDeleteFile, &newDeleteFile },
- {&LVOLoadSeg, (struct Library *) & DOSBase, &oldLoadSeg, &newLoadSeg },
-
- {&LVOLock, (struct Library *) & DOSBase, &oldLock, &newLock },
- {&LVONewLoadSeg, (struct Library *) & DOSBase, &oldNewLoadSeg, &newNewLoadSeg },
- {&LVOOpen, (struct Library *) & DOSBase, &oldOpen, &newOpen },
-
- {&LVOSetComment, (struct Library *) & DOSBase, &oldSetComment, &newSetComment },
- {&LVOSetFileDate, (struct Library *) & DOSBase, &oldSetFileDate, &newSetFileDate },
- {&LVOSetFileSize, (struct Library *) & DOSBase, &oldSetFileSize, &newSetFileSize },
-
- {&LVOSetProtection, (struct Library *) & DOSBase, &oldSetProtection, &newSetProtection },
- {&LVOAssignLate, (struct Library *) & DOSBase, &oldAssignLate, &newAssignLate },
- {&LVOAssignPath, (struct Library *) & DOSBase, &oldAssignPath, &newAssignPath },
-
- {&LVOMatchFirst, (struct Library *) & DOSBase, &oldMatchFirst, &newMatchFirst },
- {&LVORename, (struct Library *) & DOSBase, &oldRename, &newRename },
- {&LVOParsePattern, (struct Library *) & DOSBase, &oldParsePattern, &newParsePattern },
-
- /* {&LVO, (struct Library *) & DOSBase, &old, &new }*/
- };
-
- 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 = "UnixDirsII-JT";
- static UBYTE *VersTag = "\0$VER: UnixDirsII 1.0";
-
- /* Commodity globals */
- CxObj *broker;
- struct MsgPort *broker_mp;
-
- struct NewBroker newbroker =
- {
- NB_VERSION,
- "UnixDirsII",
- "UnixDirsII v1.0, © Martin Scott, 1993",
- "Patch DOS to use Unix-style paths",
- NBU_UNIQUE | NBU_NOTIFY
- };
-
- ULONG cxsigflag;
-
- int wedged = 1; /* initially, wedges will be in place */
-
- VOID
- _main(VOID)
- {
- #ifdef DEBUG
- if (IntuitionBase = OpenLibrary("intuition.library", 37L))
- {
- #endif
- if (CxBase = OpenLibrary("commodities.library", 37L))
- {
- if (broker_mp = CreateMsgPort())
- {
- newbroker.nb_Port = broker_mp;
- if (broker = CxBroker(&newbroker, NULL))
- {
- cxsigflag = 1L << broker_mp->mp_SigBit;
- ActivateCxObj(broker, 1L);
-
- if (InstallWedge())
- while (ProcessMsg());
- DeleteCxObj(broker);
-
- if (wedged)
- RemoveWedge();
- }
- DeleteMsgPort(broker_mp);
- }
- CloseLibrary(CxBase);
- }
- #ifdef DEBUG
- CloseLibrary(IntuitionBase);
- }
- #endif
- }
-
- LONG
- ProcessMsg(void)
- {
- CxMsg *msg;
-
- ULONG sigrcvd, msgid, msgtype;
- LONG returnvalue = 1L;
-
- /* wait for something to happen */
- sigrcvd = Wait(SIGBREAKF_CTRL_C | cxsigflag);
-
- /* 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_COMMAND) /* all we care about */
- {
- switch (msgid)
- {
- 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_UNIQUE:
- 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;
- }
- Enable();
- } else
- PutStr("Already running.\n");
- ReleaseSemaphore((struct SignalSemaphore *) jumptable);
- } else
- PutStr("Can't lock table.\n");
- } else
- PutStr("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));
- }
-
- 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 **************************/
- /******************* **************************/
- /******************************************************************************/
-
- /*
- * These are the generic patch routines.
- * They handle most patches automatically.
- */
-
- extern BOOL adjustpath(UBYTE *path, UBYTE *newpath, LONG len);
- #define PATHSIZE 512L /* enough for most purposes? */
-
- /* 1 args, convert arg in d1 */
- LONG ASM Wedge11(REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(a6) struct Library *),
- REG(d1) UBYTE *);
-
- LONG ASM
- Wedge11(REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(a6) struct Library *),
- REG(d1) UBYTE *arg1)
- {
- struct SignalSemaphore *jt;
- UBYTE *newpath;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (newpath = AllocVec(PATHSIZE, 0L))
- {
- if (adjustpath(arg1, newpath, PATHSIZE))
- rc = dosroutine(newpath, DOSBase);
- else
- rc = dosroutine(arg1, DOSBase);
-
- FreeVec(newpath);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-
- /* 2 args, convert arg in d1 */
- LONG ASM Wedge21(REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *),
- REG(d1) UBYTE *, REG(d2) LONG);
-
- LONG ASM
- Wedge21(REG(a0) LONG (*ASM dosroutine)(REG(d1) UBYTE *, REG(d2) LONG, REG(a6) struct Library *),
- REG(d1) UBYTE *arg1, REG(d2) LONG arg2)
- {
- struct SignalSemaphore *jt;
- UBYTE *newpath;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (newpath = AllocVec(PATHSIZE, 0L))
- {
- if (adjustpath(arg1, newpath, PATHSIZE))
- rc = dosroutine(newpath, arg2, DOSBase);
- else
- rc = dosroutine(arg1, arg2, DOSBase);
- FreeVec(newpath);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-
- /* 2 args, convert arg in d2 */
- LONG ASM Wedge22(REG(a0) LONG (*ASM dosroutine)(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *),
- REG(d1) LONG, REG(d2) UBYTE *);
-
- LONG ASM
- Wedge22(REG(a0) LONG (*ASM dosroutine)(REG(d1) LONG, REG(d2) UBYTE *, REG(a6) struct Library *),
- REG(d1) LONG arg1, REG(d2) UBYTE *arg2)
- {
- struct SignalSemaphore *jt;
- UBYTE *newpath;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (newpath = AllocVec(PATHSIZE, 0L))
- {
- if (adjustpath(arg2, newpath, PATHSIZE))
- rc = dosroutine(arg1, newpath, DOSBase);
- else
- rc = dosroutine(arg1, arg2, DOSBase);
-
- FreeVec(newpath);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-
- #define PATCH11(name) \
- LONG ASM \
- new## name(REG(d1) UBYTE *arg1, \
- REG(a6) struct Library *base) \
- { return Wedge11(old## name, arg1); }
-
- #define PATCH21(name) \
- LONG ASM \
- new## name(REG(d1) UBYTE *arg1, REG(d2) LONG arg2, \
- REG(a6) struct Library *base) \
- { return Wedge21(old## name, arg1, arg2); }
-
- #define PATCH22(name) \
- LONG ASM \
- new## name(REG(d1) LONG arg1, REG(d2) UBYTE *arg2, \
- REG(a6) struct Library *base) \
- { return Wedge22(old## name, arg1, arg2); }
-
- PATCH11(CreateDir)
- PATCH11(DeleteFile)
- PATCH11(LoadSeg)
- PATCH21(Lock)
- PATCH21(NewLoadSeg)
- PATCH21(Open)
- PATCH21(SetComment)
- PATCH21(SetFileDate)
- PATCH21(SetFileSize)
- PATCH21(SetProtection)
- PATCH22(AssignLate)
- PATCH22(AssignPath)
- PATCH21(MatchFirst)
-
- /*** And the following routines are handmade ***/
-
- /* two to do here... */
- LONG ASM
- newRename(REG(d1) UBYTE *oldname, REG(d2) UBYTE *newname,
- REG(a6) struct Library *base)
- {
- struct SignalSemaphore *jt;
- UBYTE *from, *to;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (from = AllocVec(PATHSIZE, 0L))
- {
- adjustpath(oldname, from, PATHSIZE);
- if (to = AllocVec(PATHSIZE, 0L))
- {
- adjustpath(newname, to, PATHSIZE);
- rc = oldRename(from, to, DOSBase);
- FreeVec(to);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
- FreeVec(from);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-
- /* a bit more suspect this; will buflen be big enough given a . substitution? */
- LONG ASM
- newParsePattern(REG(d1) UBYTE *pat, REG(d2) UBYTE *buf, REG(d3) LONG buflen,
- REG(a6) struct Library *base)
- {
- struct SignalSemaphore *jt;
- UBYTE *newpat;
- LONG rc = 0;
-
- if (jt = FindSemaphore(JTName))
- {
- ObtainSemaphoreShared(jt);
-
- if (newpat = AllocVec(PATHSIZE, 0L))
- {
- adjustpath(pat, newpat, PATHSIZE);
- rc = oldParsePattern(newpat, buf, buflen, DOSBase);
- FreeVec(newpat);
- }
- else SetIoErr(ERROR_NO_FREE_STORE);
-
- ReleaseSemaphore(jt);
- }
- return rc;
- }
-
- /*
- LONG ASM
- new(REG(d1) LONG arg1, REG(d2) LONG arg2,
- REG(a6) struct Library *base)
- {
- return old(arg1, arg2, base);
- }
- */
-