mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
5.1 KiB
241 lines
5.1 KiB
/***
|
|
* runtime.c - Runtime() function
|
|
*
|
|
* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* This is the run-time interface to 32-bit everything LoadSeg.
|
|
* The implementation is based on Apple's MPW 3.2 specs.
|
|
* Runtime() hooks LoadSeg and UnloadSeg through the use of a jump
|
|
* table provided by the 32-bit LoadSeg patch. The pointer to this
|
|
* table is at offset $0C into the thunk table, i.e. the long reserved
|
|
* value in the flag thunk.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <cruntime.h>
|
|
#include <internal.h>
|
|
#include <stdlib.h>
|
|
#include <macos\types.h>
|
|
#include <macos\memory.h>
|
|
#include <macos\lowmem.h>
|
|
#include <rtlib.h> //use our special version of rtlib.h
|
|
|
|
|
|
// helper routine in loadseg.a
|
|
|
|
void __RTUnloadSegSn(short int, unsigned long pseg);
|
|
|
|
|
|
// 32-bit everything format thunk table entry
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short sn;
|
|
unsigned short op;
|
|
long lOffset;
|
|
} THUNK;
|
|
|
|
#define opLoadSeg 0xA9F0
|
|
#define opMoveWImm 0x3F3C
|
|
|
|
|
|
// Segment Loader Handler Table (pointed to by flag thunk)
|
|
|
|
typedef struct
|
|
{
|
|
long reserved0;
|
|
SegLoadHdlrPtr pfnPreLoad;
|
|
SegLoadHdlrPtr pfnPostLoad;
|
|
SegLoadHdlrPtr pfnPreUnload;
|
|
SegLoadHdlrPtr pfnSegLoadErr;
|
|
long reserved5;
|
|
long reserved6;
|
|
long reserved7;
|
|
long reserved8;
|
|
long reserved9;
|
|
long reserved10;
|
|
long reserved11;
|
|
} SLHT;
|
|
|
|
|
|
// minimum and maximum kRT values that are accepted
|
|
|
|
#define kRTMin (kRTGetVersion)
|
|
#define kRTMac (kRTPostLaunch+2)
|
|
|
|
|
|
|
|
/***
|
|
*
|
|
* Runtime(RTPB* prtpb)
|
|
*
|
|
* Purpose:
|
|
* This routine does the interface to the 32-bit LoadSeg.
|
|
* See Apple's "MPW 3.2 Run-Time Architecture Enhancements" document.
|
|
*
|
|
* Entry:
|
|
* prtpb - pointer to runtime parameter block
|
|
*
|
|
* Exit:
|
|
* eRTNoErr, eRTBadVersion, eRTInvalidOp, eRTInvalidJTPtr
|
|
*
|
|
*******************************************************************************/
|
|
|
|
|
|
OSErr __pascal Runtime (
|
|
RTPB *prtpb
|
|
)
|
|
{
|
|
THUNK *pthunk;
|
|
Boolean f32Bit;
|
|
SLHT *pslht;
|
|
|
|
// filter out invalid or trivial operations
|
|
|
|
switch(prtpb->fOperation)
|
|
{
|
|
default:
|
|
return eRTInvalidOp;
|
|
break;
|
|
|
|
case kRTPreLaunch:
|
|
case kRTPostLaunch:
|
|
|
|
// these are NOPs in our implementation
|
|
|
|
return eRTNoErr;
|
|
|
|
case kRTGetVersion:
|
|
case kRTGetJTAddress:
|
|
case kRTSetPreLoad:
|
|
case kRTSetSegLoadErr:
|
|
case kRTSetPostLoad:
|
|
case kRTSetPreUnload:
|
|
case kRTUnloadSeg:
|
|
|
|
// use the current value of A5
|
|
|
|
pthunk = (THUNK *)LMGetCurrentA5();
|
|
break;
|
|
|
|
case kRTGetVersionA5:
|
|
case kRTGetJTAddressA5:
|
|
case kRTSetPreLoadA5:
|
|
case kRTSetSegLoadErrA5:
|
|
case kRTSetPostLoadA5:
|
|
case kRTSetPreUnloadA5:
|
|
|
|
// use the value of A5 passed to us
|
|
|
|
pthunk = prtpb->fA5;
|
|
break;
|
|
}
|
|
|
|
// Determine if the app is 32-bit everything by looking for the flag entry
|
|
// in the thunk table. If it's there, then also grab the pointer to the
|
|
// RTI (runtime interface) used to communicate with LoadSeg.
|
|
|
|
(char *)pthunk += LMGetCurJTOffset();
|
|
|
|
if (f32Bit = ((++pthunk)->op == kVersion32bit))
|
|
{
|
|
// it is a 32-bit everything thunk table
|
|
|
|
pslht = (SLHT *)pthunk->lOffset;
|
|
}
|
|
else
|
|
{
|
|
// kRTSet* and kRTUnloadSeg can't be used with "classic" thunks
|
|
|
|
if (prtpb->fOperation >= kRTSetPreLoad)
|
|
return eRTBadVersion;
|
|
}
|
|
|
|
// process each operation
|
|
|
|
switch(prtpb->fOperation)
|
|
{
|
|
case kRTGetVersion:
|
|
case kRTGetVersionA5:
|
|
|
|
// return thunk table version
|
|
|
|
prtpb->fRTParam.fVersionParam.fVersion =
|
|
f32Bit ? kVersion32bit : kVersion16bit;
|
|
break;
|
|
|
|
case kRTGetJTAddress:
|
|
case kRTGetJTAddressA5:
|
|
|
|
// Return address of code pointed by the given thunk.
|
|
// Thunk must be valid and in "Loaded" state.
|
|
|
|
{
|
|
THUNK *pthunkJT =
|
|
(THUNK *) ((char *)prtpb->fRTParam.fJTAddrParam.fJTAddr - 2);
|
|
|
|
if ( (pthunkJT <= ++pthunk) ||
|
|
(f32Bit && pthunkJT->op == opLoadSeg) ||
|
|
(!f32Bit && pthunkJT->op == opMoveWImm)
|
|
)
|
|
return eRTInvalidJTPtr;
|
|
|
|
prtpb->fRTParam.fJTAddrParam.fCodeAddr = (void *) pthunk->lOffset;
|
|
}
|
|
break;
|
|
|
|
case kRTSetPreLoad:
|
|
case kRTSetPreLoadA5:
|
|
|
|
// hook segment preload handler and return old value
|
|
|
|
prtpb->fRTParam.fSegLoadParam.fOldUserHdlr =
|
|
(void *) pslht->pfnPreLoad;
|
|
pslht->pfnPreLoad = prtpb->fRTParam.fSegLoadParam.fUserHdlr;
|
|
break;
|
|
|
|
case kRTSetSegLoadErr:
|
|
case kRTSetSegLoadErrA5:
|
|
|
|
// hook segment load error handler and return old value
|
|
|
|
prtpb->fRTParam.fSegLoadParam.fOldUserHdlr =
|
|
(void *) pslht->pfnSegLoadErr;
|
|
pslht->pfnSegLoadErr = prtpb->fRTParam.fSegLoadParam.fUserHdlr;
|
|
break;
|
|
|
|
case kRTSetPostLoad:
|
|
case kRTSetPostLoadA5:
|
|
|
|
// hook segment postload handler and return old value
|
|
|
|
prtpb->fRTParam.fSegLoadParam.fOldUserHdlr =
|
|
(void *) pslht->pfnPostLoad;
|
|
pslht->pfnPostLoad = prtpb->fRTParam.fSegLoadParam.fUserHdlr;
|
|
break;
|
|
|
|
case kRTSetPreUnload:
|
|
case kRTSetPreUnloadA5:
|
|
|
|
// hook segment preunload handler and return old value
|
|
|
|
prtpb->fRTParam.fSegLoadParam.fOldUserHdlr =
|
|
(void *) pslht->pfnPreUnload;
|
|
pslht->pfnPreUnload = prtpb->fRTParam.fSegLoadParam.fUserHdlr;
|
|
break;
|
|
|
|
case kRTUnloadSeg:
|
|
|
|
// Calls the __RTUnloadSegSn routine to unload a segment
|
|
|
|
__RTUnloadSegSn(prtpb->fRTParam.fUnloadSegParam.fSegNumber, 0L);
|
|
break;
|
|
}
|
|
|
|
// normal termination, no error
|
|
|
|
return eRTNoErr;
|
|
}
|
|
|
|
|