home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-12 | 12.5 KB | 555 lines | [TEXT/R*ch] |
- /* NAME:
- InstallCode.c
-
- WRITTEN BY:
- Dair Grant
-
- DESCRIPTION:
- Routines for installing various code resources.
-
- ___________________________________________________________________________
- */
- //=============================================================================
- // Include files
- //-----------------------------------------------------------------------------
- #include <Memory.h>
- #include <Gestalt.h>
- #include <Errors.h>
- #include <Resources.h>
- #include <Shutdown.h>
- #include <Timer.h>
- #include "ES.h"
- #include "ES Address Table.h"
- #include "InstallCode.h"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // Private function prototypes
- //-----------------------------------------------------------------------------
- OSErr InstallTrapPatch(short i, Ptr theCode);
- OSErr InstallGestaltSelector(short i, Ptr theCode);
- OSErr InstallShutdownTask(short i, Ptr theCode);
- OSErr InstallVBLTask(short i, Ptr theCode);
- OSErr InstallLowMemFilter(short i, Ptr theCode);
- OSErr InstallCodeBlock(short i, Ptr theCode);
- OSErr InstallTimeManagerTask(short i, Ptr theCode);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // Global variables
- //-----------------------------------------------------------------------------
- extern ESParamBlock gTheParamBlock;
- extern ESAddressTable *gTheESAddressTable;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallCode : Install a code resource depending on its type.
- //-----------------------------------------------------------------------------
- // Note : We get the index of something in gTheParamBlock.theCodeResources
- // and case out on its type to do the installation. If any error
- // occurs, we return the error code - our caller fills in the
- // details in gTheParamBlock.
- //-----------------------------------------------------------------------------
- OSErr InstallCode(short i)
- { Handle theHnd;
- OSErr theErr;
- Ptr theCode;
-
-
-
-
- // Get the code resource we're after, and return if it wasn't there.
- theHnd = Get1Resource(gTheParamBlock.theCodeResources[i].resType,
- gTheParamBlock.theCodeResources[i].resID);
- if (theHnd == nil)
- return(resNotFound);
-
-
-
- // Unlock the resource, compact the heap, then lock it down. We then
- // detach it so it stays around after Extension Shell is gone.
- HUnlock(theHnd);
- ResrvMem(GetHandleSize(theHnd));
- HLock(theHnd);
- DetachResource(theHnd);
-
-
-
- // Get a clean address from the handle
- theCode = (Ptr) StripAddress(*theHnd);
-
-
-
- // Now case out on the type of the code, and call the install routine
- switch(gTheParamBlock.theCodeResources[i].codeType) {
- case kTrapPatchType:
- theErr = InstallTrapPatch(i, theCode);
- break;
-
- case kGestaltSelectorType:
- theErr = InstallGestaltSelector(i, theCode);
- break;
-
- case kShutdownTaskType:
- theErr = InstallShutdownTask(i, theCode);
- break;
-
- case kVBLTaskType:
- theErr = InstallVBLTask(i, theCode);
- break;
-
- case kLowMemFilterType:
- theErr = InstallLowMemFilter(i, theCode);
- break;
-
- case kCodeBlockType:
- theErr = InstallCodeBlock(i, theCode);
- break;
-
- case kTimeManagerTaskType:
- theErr = InstallTimeManagerTask(i, theCode);
- break;
-
- default:
- theErr = noErr;
- }
-
-
- // Return any errors that occurred
- return(theErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallESAddressTable : Install an address table.
- //-----------------------------------------------------------------------------
- // Note : We install the Gestalt selector, call Gestalt to obtain the
- // address of the address table, and leave the result in
- // gTheESAddressTable.
- //
- // Because the address table is so fundamental, any failure
- // to load, install, or call it drops us into MacsBug.
- //
- // We also initialse the magicNumber and versionNumber fields.
- //-----------------------------------------------------------------------------
- void InstallESAddressTable(void)
- { Handle theHnd;
- OSErr theErr;
- ProcPtr theCode;
-
-
-
- // Load the AddressTable Gestalt selector, and install it with NewGestalt.
- theHnd = GetResource(kAddrsTableCodeType, kAddrsTableCodeID);
- if (theHnd == nil)
- DebugStr("\pExtension Shell - couldn't find Address Table resource");
-
-
- // We have it, so lock it in place
- HUnlock(theHnd);
- ResrvMem(GetHandleSize(theHnd));
- HLock(theHnd);
- DetachResource(theHnd);
-
-
- // Get a clean address from the handle
- theCode = (ProcPtr) StripAddress(*theHnd);
-
-
- // Install the address table as a Gestalt selector
- theErr = NewGestalt(gTheParamBlock.addressTableSelector,
- NewSelectorFunctionProc(theCode));
- if (theErr != noErr)
- DebugStr("\pExtension Shell - couldn't install AddressTable");
-
-
- // Call Gestalt to get the address of the address table and initialise
- // the magicNumber and versionNumber fields.
- theErr = Gestalt(gTheParamBlock.addressTableSelector, (long *) &gTheESAddressTable);
- if (theErr != noErr)
- DebugStr("\pExtension Shell - couldn't call AddressTable");
- else
- {
- gTheESAddressTable->magicNumber = 0xDEADBEEF;
- gTheESAddressTable->versionNumber = 0xFEEDFACE;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallTrapPatch : Install a trap patch.
- //-----------------------------------------------------------------------------
- // Note : Given a trap word and a pointer to the new routine, we save
- // the original entry in the dispatch table and insert the new
- // one.
- //
- // We assume that the trap *is* implemented. If globalPatch is
- // true, the patch is applied to all applications (this is the
- // default behaviour). If globalPatch is false, the patch only
- // takes affect in the application appName. (THIS FEATURE IS
- // NOT IMPLEMENTED YET)
- //-----------------------------------------------------------------------------
- OSErr InstallTrapPatch(short i, Ptr theCode)
- { short trapWord;
- TrapType trapType;
- ProcPtr oldCodeAddress;
-
-
-
- // Find out what we need to know
- trapWord = gTheParamBlock.theCodeResources[i].theCodeThing.theTrapPatch.trapWord;
- trapType = (trapWord & 0x0800) ? ToolTrap : OSTrap;
-
-
- // Replace the old value in the dispatch table with the new value.
- oldCodeAddress = (ProcPtr) StripAddress((Ptr) NGetTrapAddress(trapWord, trapType));
- NSetTrapAddress((UniversalProcPtr) theCode, trapWord, trapType);
-
-
-
- // Handle globalPatch and appName
- //
- // THIS FEATURE IS NOT IMPLEMENTED YET - IT WOULD NEED SOME KIND OF
- // GENERIC EXTENSION SHELL PATCH TO SOMETHING LIKE _INITALLPACKS OR
- // _INITGRAF, AND THEN THE APPLICATION OF PATCHES DEPENDING ON
- // THE APPLICATION BEING EXECUTED.
- //
- //
-
-
-
- // Fill in the entry in the address table and save the address of the new code.
- gTheESAddressTable->theTable[i] = oldCodeAddress;
- gTheParamBlock.theCodeResources[i].theAddress = theCode;
-
-
- // Return any errors
- return(noErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallGestaltSelector : Install a Gestalt Selector.
- //-----------------------------------------------------------------------------
- OSErr InstallGestaltSelector(short i, Ptr theCode)
- { OSErr theErr;
- SelectorFunctionUPP theUPP;
- AGestaltSelector *theGestaltInfo;
-
-
-
-
- // Find out what we need to know
- theGestaltInfo = &gTheParamBlock.theCodeResources[i].theCodeThing.theGestaltSelector;
- theUPP = NewSelectorFunctionProc(theCode);
-
-
-
- // Try and install the routine
- theErr = NewGestalt(theGestaltInfo->theSelector, theUPP);
-
-
-
- // If the selector exists, replace it if we're allowed to, and save
- // the address of the old routine in the address table
- if (theErr == gestaltDupSelectorErr && theGestaltInfo->overwriteExistingSelector)
- theErr = ReplaceGestalt(theGestaltInfo->theSelector, theUPP,
- (SelectorFunctionUPP *) &gTheESAddressTable->theTable[i]);
-
-
-
- // If there wasn't a problem, save the address of the new code. The address
- // table is only used if we need to get access to the old Gestalt routine.
- if (theErr == noErr)
- gTheParamBlock.theCodeResources[i].theAddress = theCode;
-
-
-
- // Return any errors
- return(theErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallShutdownTask : Install a Shutdown Task.
- //-----------------------------------------------------------------------------
- OSErr InstallShutdownTask(short i, Ptr theCode)
- {
-
-
- // Install the task with its flags and save the address in gTheParamBlock.
- // We don't use the address table at all.
- ShutDwnInstall(NewShutDwnProc(theCode),
- gTheParamBlock.theCodeResources[i].theCodeThing.theShutdownTask.theFlags);
- gTheParamBlock.theCodeResources[i].theAddress = theCode;
-
-
- // Return any errors
- return(noErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallVBLTask : Install a VBL task.
- //-----------------------------------------------------------------------------
- OSErr InstallVBLTask(short i, Ptr theCode)
- { VBLTask *theVblPtr;
- OSErr theErr;
-
-
-
-
- // Allocate a little block of memory in the System Heap for the task information
- theVblPtr = (VBLTask*) NewPtrSys(sizeof(VBLTask));
-
-
-
- // Fill in the fields, and install it as a VBL task
- theVblPtr->qType = vType;
- theVblPtr->vblAddr = NewVBLProc(theCode);
- theVblPtr->vblCount = gTheParamBlock.theCodeResources[i].theCodeThing.theVBLTask.vblCount;
- theVblPtr->vblPhase = gTheParamBlock.theCodeResources[i].theCodeThing.theVBLTask.vblPhase;
- theErr = VInstall((QElemPtr) theVblPtr);
-
-
-
- // Save the address of the VBLTask structure in the address table and the param block
- if (theErr == noErr)
- {
- gTheESAddressTable->theTable[i] = (ProcPtr) theVblPtr;
- gTheParamBlock.theCodeResources[i].theAddress = (Ptr) theVblPtr;
- }
-
-
- // Return any errors
- return(theErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallLowMemFilter : Install a low-memory filter.
- //-----------------------------------------------------------------------------
- OSErr InstallLowMemFilter(short i, Ptr theCode)
- { ProcPtr theEntryPoint;
-
-
-
-
- // Get the address of the filter chain.
- theEntryPoint = (ProcPtr) gTheParamBlock.theCodeResources[i].theCodeThing.theLowMemFilter.theEntryPoint;
-
-
-
- // Save the address currently at the front of the chain in the address table
- // and save ourselves in the param block.
- gTheESAddressTable->theTable[i] = (ProcPtr) *((void **) theEntryPoint);
- gTheParamBlock.theCodeResources[i].theAddress = theCode;
-
-
- // Insert ourselves into the front of the chain
- *((long *) theEntryPoint) = (long) theCode;
-
-
- // Return any errors
- return(noErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallCodeBlock : Install a block of code.
- //-----------------------------------------------------------------------------
- OSErr InstallCodeBlock(short i, Ptr theCode)
- {
-
-
- // Set the reserved field to some value
- gTheParamBlock.theCodeResources[i].theCodeThing.theCodeBlock.refCon = 0xDEADBEEF;
-
-
- // Save the address of the code block in the address table and the param block
- gTheESAddressTable->theTable[i] = (ProcPtr) theCode;
- gTheParamBlock.theCodeResources[i].theAddress = theCode;
-
-
- // Return any errors
- return(noErr);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- //=============================================================================
- // InstallTimeManagerTask : Install a Time Manager task.
- //-----------------------------------------------------------------------------
- OSErr InstallTimeManagerTask(short i, Ptr theCode)
- { TMTask *theTaskPtr;
-
-
-
-
- // Allocate a little block of memory in the System Heap for the task information
- theTaskPtr = (TMTask*) NewPtrSys(sizeof(TMTask));
-
-
-
- // Fill in the fields, and install it as an Time Manager task. We don't install
- // it as with InsXTime because we probably won't need that accurate timing.
- theTaskPtr->tmAddr = (TimerUPP) theCode;
- theTaskPtr->tmCount = 0;
- InsTime((QElemPtr) theTaskPtr);
- PrimeTime((QElemPtr) theTaskPtr,
- gTheParamBlock.theCodeResources[i].theCodeThing.theTimeManagerTask.theDelay);
-
-
-
- // Save the address of the TMTask structure in the address table and the param block
- gTheESAddressTable->theTable[i] = (ProcPtr) theTaskPtr;
- gTheParamBlock.theCodeResources[i].theAddress = (Ptr) theTaskPtr;
-
-
-
- // Return any errors
- return(noErr);
- }
-