mac-rom/ProcessMgr/SegmentLoaderPatches.c
Elliot Nunn 0ba83392d4 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-09-20 18:04:16 +08:00

789 lines
25 KiB
C

/*
File: SegmentLoaderPatches.c
Contains: Routines which patch the segment loader traps.
Written by: Erich Ringewald and Phil Goldman
Copyright: © 1986-1992 by Apple Computer, Inc., all rights reserved.
This file is used in these builds: System
Change History (most recent first):
<18> 5/21/92 gbm #1030303,<dty>: Start using the new (and improved!) 'SIZE'(1)
for launching, if itÕs present.
<17> 1/14/92 YK Take out <15>,<16> since we found a better way.
<16> 1/10/92 YK Oops, I didn't close the comment.
<15> 1/10/92 YK Check if the app is the Service Window Manager app (for TSM) in
GetSizeInfo, then set the flag. (this is a tentative solution)
<14> 7/26/91 stb use HOpenResFile instead of old glue
<13> 4/18/91 DFH TED, WS#DFH-910418b : Fixed LaunchApplication to restore the
zone in the error patch where the file could not be opened.
<12> 4/1/91 DFH (with John Iarocci) Merged in latest AUX support code. NOTE: No
AUX support code is referenced unless the build defines the
HAS_AUX_PROCESSMGR condition.
<11> 3/25/91 DFH JSM,#DFH-910325a: Fix SetAppParameters to deal with the fact
that the fabricated AppleEvent is in an unlocked handle.
<10> 2/28/91 DFH VL,#83781: Removed 32-bit clean check from LaunchApplication. It
is deemed no longer relevant, since Finder always overrode it.
<9> 2/21/91 DFH dba,#82504, #82681, #83168, #83182, #83207: Available memory
calc in StandardLaunch no longer needs special param for
ProcessMgrMaxBlock to be accurate.
<8> 1/31/91 DFH NGK,WS#DFH-910131a:Changed SetAppParameters so that launchee
gets a saeLaunchedWithoutDocs AppleEvent when the launcher
passed launchAppParameters == nil.
<7> 1/14/91 DFH (JDR) Conditionalize out AUX support.
<5> 12/5/90 DFH Integrated AUX support.
<4> 11/26/90 DFH Change trespass() to dbmsg().
<2> 10/30/90 csd Fixed some identifiers to match the newest interfaces.
<0> x/xx/86 PYG New Today.
*/
#include <types.h>
#include <memory.h>
#include <toolutils.h>
#include <osutils.h>
#include <quickdraw.h>
#include <fonts.h>
#include <events.h>
#include <devices.h>
#include <desk.h>
#include <resources.h>
#include <retrace.h>
#include <menus.h>
#include <windows.h>
#include <files.h>
#include <segload.h>
#include <errors.h>
#include <Aliases.h>
#include <folders.h>
#include <MFPrivate.h>
#include "Glue.h"
#include "Lomem.h"
#include "Data.h"
#include "SysMisc.h"
#include "Aux.h"
#include "Puppet.h"
#include "Zone.h"
#include "AppleEventExtensions.h"
/* Function prototypes internal to this file */
void OpenAppWDs(PEntryPtr);
void CopyAppParmHandle(AppParmRecHdl, PCB **);
void GetSizeInfo(swParmPtr, short);
void SyncSIZEInfo(void);
/* Some function prototypes that should be in (yet another) header file */
AppParmRecHdl AEParmToAppParmHandle(AppParametersPtr, PCB **);
Handle AppParmHandleToAEParm(AppParmRecHdl);
OSErr DecomposeWD(short, short *, unsigned long *);
void FPInit(void);
void NextAppFile(AppFile **);
unsigned long SizeOfThisAppFile(AppFile *);
void kill_dce(THz);
/* Macros for easy access to the _Launch parameters */
#define IS_EXTENDED_BLOCK(pLaunchBlock) ((pLaunchBlock)->launchBlockID == extendedBlock)
#define FIRST_EXTENSION_SIZE (2*sizeof(short))
#define SECOND_EXTENSION_SIZE ( FIRST_EXTENSION_SIZE + sizeof(ProcessSerialNumber) + 5*sizeof(long) )
/* This is roughly the memory overhead to handle an application that will have
* half a chance of running. It includes PCBs, HLists, 'lmem' resources, AppleEvents,
* etc. that are made in either the system heap or the Process Mgr heap.
*/
#define APPSIZESLOP (0x1000)
/* SyncSIZEInfo. Sync the SIZE information in case a pre-7.1 system has touched the SIZE(0)
* information but the SIZE(1) is not yet updated. We would prefer to use the SIZE(1) resource
* to do the launch, but only after it is up to date. Data is updated as follows: if the
* psize (preferred size) in the SIZE(0) is different from the same field in SIZE(1), then
* copy that size into SIZE(1). Then, if the msize (minimum size) in SIZE(1) is greater than
* the new psize, set msize the same as psize. If either SIZE(1) or SIZE(0) are
* missing, then bail.
*/
void
SyncSIZEInfo()
{
swParmHdl h0, h1;
/* Get the resources */
h0 = Get1Resource('SIZE', 0);
h1 = Get1Resource('SIZE', 1);
if ( h0 && h1 ) // if we have both handles, then do more stuff
{
if ( (**h0).psize != (**h1).psize )
{
(**h1).psize = (**h0).psize;
if ( (**h1).msize > (**h1).psize )
(**h1).msize = (**h1).psize;
ChangedResource( (Handle) h1 ); // if this fails, we donÕt care...
WriteResource( (Handle) h1 ); // ...the in-memory copy will still be right
}
}
}
/* GetSizeInfo. Extract SIZE information from current file. Supplies defaults
* in no-find case. The defaults were chosen with the assumption that the app
* is capable of running on a MacPlus. We also assume that the sizes (default or
* otherwise) were chosen with the MacPlus stack size in mind, and adjust them
* according to the stack size we'll actually use for this launch.
*/
void
GetSizeInfo(swParmPtr pSizeInfo, short firstChoice)
{
swParmHdl h;
/* Make sure the SIZE resources are correct */
SyncSIZEInfo();
/* First, try the preferred resource ID. This will either be a 1 for applications or
* a weird negative ID for DAs. If itÕs for a DA and itÕs unavailable, give up. If itÕs for
* an application and weÕre looking for ID 1 and itÕs unavailable, then try ID 0. If neither
* ID 0 or ID 1 (made by Finder) are present, try one more time for ID -1. If ID -1 canÕt be
* found, then just give up.
*/
if ( ((h = Get1Resource('SIZE', firstChoice)) == nil) && (firstChoice == 1) )
if ( (h = Get1Resource('SIZE', 0)) == nil )
h = Get1Resource('SIZE', -1);
/* Copy info if available. Otherwise, assume the app has old requirements. */
if (h != nil)
BlockMove(*h,pSizeInfo,sizeof(swParms));
else
{
pSizeInfo->flags = 0;
pSizeInfo->psize = (512*1024);
pSizeInfo->msize = (512*1024);
}
/* Normalize to MacPlus stack size if not a daemon */
if (((pSizeInfo->flags & modeOnlyBackground) == 0) && (DEFLTSTACK > MACPLUS_DEFLTSTACK))
{
unsigned long normalization;
normalization = DEFLTSTACK - MACPLUS_DEFLTSTACK;
pSizeInfo->psize += normalization;
pSizeInfo->msize += normalization;
}
}
/* StandardLaunch. Subroutinizes most of what it takes to launch an application
* into a process. Name and vRefNum specify the application resource file. Assumes
* that any necessary working directories have already been opened.
* Called internally, we may have extra flags on in the taskMode (such as to
* indicate a Desk Accessory launch).
* NOTE: Callers should be able to rely on launchResults->pNewProcess == nil if the result != noErr.
* NOTE: assumes a5 == PROCESSMGRGLOBALS
*/
void
StandardLaunch(FSSpecPtr pFileSpec, u_short launchFlags, u_long taskMode, Ptr pAppParms, LaunchResultsPtr launchResults, DASpecBlockPtr pDAInfo)
{
InternalLaunchPB ILParams;
swParms sizeInfo;
OSErr retVal;
short rfn, saveCurMap;
u_size appSize;
THz saveZone;
/* Fill in param block for lower routines */
ILParams.ilAppSpecPtr = pFileSpec;
ILParams.ilDAInfoPtr = pDAInfo;
ILParams.ilStackSize = DEFLTSTACK;
ILParams.ilAppParameters = pAppParms;
ILParams.ilAppParamHdl = nil;
/* In case of error */
launchResults->pNewProcess = nil;
appSize = 0;
/* Get access to the application resource file SIZE resource. Switch to the
* system heap, since the caller may not have enough room to even create the
* resource map when we open the file.
*/
saveCurMap = CURMAP;
SafeSetZone(saveZone, SYSZONE);
if ((taskMode & modeDeskAccessory) != 0)
{
UseResFile(0);
GetSizeInfo(&sizeInfo, DAH_SIZE_RESOURCE_ID);
}
else
{
SetResLoad(false);
rfn = HOpenResFile(pFileSpec->vRefNum, pFileSpec->parID, &pFileSpec->name,
((taskMode & modeMultiLaunch) != 0) ? fsRdPerm : fsCurPerm);
launchResults->LaunchError = RESERR;
SetResLoad(true);
/* Fail if we couldn't open the resource file */
if (rfn == (-1))
{
SafeRestoreZone(saveZone);
return;
}
/* Set the taskMode. OR in the MultiLaunch flag, and replace the low word
* with control information from the SIZE resource.
*/
if ((taskMode & FILE_FLAG_MULTILAUNCH) != 0)
taskMode |= modeMultiLaunch;
GetSizeInfo(&sizeInfo, 1); // <18>
/* Don't close yet so that we get opWrErr later on.
* NOTE: Closing the app file (we do it here in the non-continue case)
* has the potential for screwing up VBLs (and others?) that will still
* be running out of its code segments. Mostly a problem only if the
* heap moves before the VBLKILL in the launcher's ExitToShell.
*/
if ( ((launchFlags & launchContinue) == 0) || (rfn != CURAPREFNUM) )
CloseResFile(rfn);
}
/* Have to restore map, since app file might not have been at top of chain */
SafeRestoreZone(saveZone);
CURMAP = saveCurMap;
/* Copy the flags into the task mode */
ILParams.ilTaskMode = ((taskMode & 0xFFFF0000) | (u_long) sizeInfo.flags);
/* If it's a BG-only app, is that OK? */
if (((sizeInfo.flags & modeOnlyBackground) != 0)
&& ((launchFlags & launchInhibitDaemon) != 0))
{
launchResults->LaunchError = appIsDaemon;
return;
}
/* Try to launch in the preferred size */
ILParams.ilPartitionSize = sizeInfo.psize;
retVal = KernelLaunch(&ILParams);
/* If launch failed because there was not enough room, retry in smaller space
* if the user wants to, and the space is available. Use the largest available
* size, as long as it meets the application's minimum size requirement. Try to
* leave enough memory in ProcessMgrZone to allocate subordinate structures, like
* the PCB, HLists, etc.
* NOTE: Assumes that the partition is the next block allocated from the
* ProcessMgrZone (otherwise, we are not guaranteed to get full appSize).
*/
if (retVal == memFullErr)
{
appSize = ProcessMgrMaxBlock();
if (appSize < APPSIZESLOP)
appSize = 0;
else
appSize -= APPSIZESLOP;
/* Do we have enough to retry?
* NOTE: Assumes that the first KernelLaunch didn't change anything in ILParams.
*/
if ( (appSize >= sizeInfo.msize)
&& ((launchFlags & launchUseMinimum) != 0) )
{
ILParams.ilPartitionSize = appSize;
retVal = KernelLaunch(&ILParams);
appSize = 0;
}
}
if (retVal == noErr)
{
/* Synchronize count for scrap coercion */
(ILParams.ilResultProc)->p_cutcopycount = cutCopyCount;
/* Launching an app cancels an saeQuitAll */
if (pSystemQuitAllMsg != nil)
CancelQuitAll(&((ILParams.ilResultProc)->p_serialNumber));
}
/* Return output information */
launchResults->pNewProcess = ILParams.ilResultProc;
launchResults->AvailableSize = appSize;
launchResults->PreferredSize = sizeInfo.psize;
launchResults->MinimumSize = sizeInfo.msize;
launchResults->LaunchError = retVal;
}
#pragma segment INIT
/* LaunchFacelessTasks. Find and launch all background applications kept in the
* "extensions" folder.
* NOTE: Theoretically, FindFolder or HOpenResFile could move memory by calling
* _GetResource, which is a problem for the rsrc mgr routine CheckLoad(), which
* will save and restore TheZone for resources w/ resSysHeap set. Growing the
* system heap means moving ProcessMgrZone, so the resource manager save/restore would
* restore an obsolete value.
* NOTE: assumes a5 == PROCESSMGRGLOBALS
* NOTE: assumes THEZONE == ProcessMgrZone since we specifically restore it
*/
void
LaunchFacelessTasks(void)
{
LaunchResults bgLaunchResults;
swParms sizeInfo;
short rfn, saveCurMap;
FSSpec fileSpec;
CInfoPBRec cInfoPBRec;
/* Locate the startup folder. */
assert(THEZONE == ProcessMgrZone);
THEZONE = SYSZONE;
if (FindFolder(kOnSystemDisk, kExtensionFolderType, kDontCreateFolder,
&fileSpec.vRefNum, &fileSpec.parID) != noErr)
{
THEZONE = ProcessMgrZone;
return;
}
/* Now iterate over all the files in the directory */
cInfoPBRec.hFileInfo.ioNamePtr = &fileSpec.name;
cInfoPBRec.hFileInfo.ioVRefNum = fileSpec.vRefNum;
cInfoPBRec.hFileInfo.ioFDirIndex = 0;
cInfoPBRec.hFileInfo.ioCompletion = nil;
for(;;)
{
/* Reset parameters and get next file. Quit if directory went bad. */
cInfoPBRec.hFileInfo.ioDirID = fileSpec.parID;
cInfoPBRec.hFileInfo.ioFDirIndex++;
if (PBGetCatInfo(&cInfoPBRec, SyncHFS) != noErr)
break;
/* Don't try launch if file isn't an application */
if ( ((cInfoPBRec.hFileInfo.ioFlAttrib & FILE_ATTRIB_ISDIR) != 0)
|| (cInfoPBRec.hFileInfo.ioFlFndrInfo.fdType != 'appe') )
continue;
/* Don't launch if it is not a background-only system extension */
saveCurMap = CURMAP;
SetResLoad(false);
rfn = HOpenResFile(fileSpec.vRefNum, fileSpec.parID, &fileSpec.name, fsCurPerm);
SetResLoad(true);
if (rfn == (-1))
continue;
GetSizeInfo(&sizeInfo, 1); // <18>
CloseResFile(rfn);
CURMAP = saveCurMap;
if ((sizeInfo.flags & modeOnlyBackground) == 0)
continue;
/* Try the launch */
StandardLaunch(&fileSpec, 0, 0, nil, &bgLaunchResults, nil);
}
THEZONE = ProcessMgrZone;
}
#pragma segment Main
/* c_launch. Our patch to the _Launch trap. It has takes a parameter block that
* may be any of three different sizes. To make things worse, there are flag
* fields that can tell us to perform optional extra work so that the caller
* doesn't have to. Please excuse my GOTOs, but they were the most effective
* way to bail out of error conditions without some extremely unwieldy coding.
* This is essentially a wrapper for our internal routine StandardLaunch.
*/
#define APPPARMS_NOT_SPECIFIABLE (-1)
pascal long
c_launch(LaunchPBPtr pLaunchBlock)
{
u_short launchOpts, wdRefNumDst;
u_long blockLen, olda5;
Boolean alreadyLaunched;
FInfo fndrInfo;
unsigned short fileFlags;
Ptr appParms;
LaunchResults appLaunchResults;
FSSpec fileSpec, *pFileSpec;
#define pProc (appLaunchResults.pNewProcess)
#define retVal (appLaunchResults.LaunchError)
olda5 = ProcessMgrA5SimpleSetup();
/* Clear retVal, pProc, and SIZE information */
MemClear(&appLaunchResults, sizeof(LaunchResults));
/* Fill in default values for parameters that might not be there */
blockLen = 0;
pFileSpec = nil;
fileFlags = 0;
launchOpts = 0;
appParms = (Ptr) APPPARMS_NOT_SPECIFIABLE;
/* Get the parameters that were given */
blockLen = (IS_EXTENDED_BLOCK(pLaunchBlock)) ? pLaunchBlock->launchEPBLength : 0;
if (blockLen >= FIRST_EXTENSION_SIZE)
{
fileFlags = pLaunchBlock->launchFileFlags;
launchOpts = pLaunchBlock->launchControlFlags;
}
if (blockLen >= SECOND_EXTENSION_SIZE)
{
pFileSpec = pLaunchBlock->launchAppSpec;
pLaunchBlock->launchPreferredSize = 0;
pLaunchBlock->launchMinimumSize = 0;
pLaunchBlock->launchAvailableSize = 0;
if ((appParms = pLaunchBlock->launchAppParameters) == APPPARMS_NOT_SPECIFIABLE)
appParms = nil;
}
else
{
GetVol(0, &wdRefNumDst);
if ((retVal = FSMakeFSSpec(wdRefNumDst, 0, (StringPtr) pLaunchBlock->reserved1, &fileSpec)) != noErr)
goto AfterLaunch;
pFileSpec = &fileSpec;
}
/* Launch the application into a process. Relaunch existing application only if
* it is the caller himself and he is not trying to get a second copy!.
*/
alreadyLaunched = ((pProc = PEntryFromFileSpec(pFileSpec, nil)) != nil);
if ( (alreadyLaunched == false) ||
((pProc == pCurrentProcess) && ((launchOpts & launchContinue) == 0)) )
{
/* Get file's flags if the caller wants us to */
if ((launchOpts & launchNoFileFlags) != 0)
{
if ((retVal = FSpGetFInfo(pFileSpec, &fndrInfo)) != noErr)
goto AfterLaunch;
fileFlags = fndrInfo.fdFlags;
}
/* Try the launch */
StandardLaunch(pFileSpec, launchOpts, (u_long) fileFlags, appParms, &appLaunchResults, nil);
}
/* Return output parameters */
if (blockLen >= SECOND_EXTENSION_SIZE)
{
if (retVal == noErr)
pLaunchBlock->launchProcessSN = pProc->p_serialNumber;
else
SetPSN(kNoProcess, &pLaunchBlock->launchProcessSN);
pLaunchBlock->launchPreferredSize = appLaunchResults.PreferredSize;
pLaunchBlock->launchMinimumSize = appLaunchResults.MinimumSize;
pLaunchBlock->launchAvailableSize = appLaunchResults.AvailableSize;
}
AfterLaunch:
/* Arrange for the new app layer to be created in front, unless overridden. We then
* put the newborn to sleep until fg_resched decides to schedule it. This ensures
* that the app gets its first time in the foreground, and when there are no modals
* up. A "don't switcher" will be created in the very back (it doesn't matter
* whether there's a modal in this case).
* If the app was already launched, a simple SetFrontProcess will do.
*/
if (retVal == noErr)
{
if ( ((launchOpts & launchDontSwitch) == 0) &&
((pProc->p_taskmode & modeOnlyBackground) == 0) )
{
if ((SetFrontProcess(&pProc->p_serialNumber) == noErr)
&& (alreadyLaunched == false))
PutOnSleepQueue(pProc, MAXVALUE);
}
}
/* Old style launch causes the launcher to quit. This is true even if the new
* application fails to launch (no error return possible, so just beep).
*/
if ((launchOpts & launchContinue) == 0)
{
if (retVal != noErr)
SysBeep(20);
A5SimpleRestore(olda5);
ExitToShell();
dbmsg("ExitToShell in LaunchApplication failed.");
}
A5SimpleRestore(olda5);
/* Return short process descriptor or error to caller */
return ( ((retVal == noErr) && (blockLen < SECOND_EXTENSION_SIZE)) ? pProc->p_mypid : retVal);
#undef pProc
#undef retVal
}
#pragma segment kernel_segment
/* NewAppParmHandle. Create a blank AppParmRecHdl of the specified size.
* NOTE: Locking the AppParmHandle is done explicitly for MacWrite 4.5 (and
* 4.6?) and should someday be removed.
*/
AppParmRecHdl
NewAppParmHandle(Size theSize)
{
AppParmRecHdl retHdl;
ResrvMem(theSize);
if ((retHdl = (AppParmRecHdl) NewHandleClear(theSize)) != nil)
HLock(retHdl);
return(retHdl);
}
/* SizeOfThisAppFile. Figure out the size of the given AppFile structure. Allows
* for even alignment.
*/
unsigned long
SizeOfThisAppFile(AppFile *pAppFile)
{
register unsigned long theSize;
theSize = 2*sizeof(short) + sizeof(OSType) + Length(&(pAppFile->fName))+ 1;
WORD_ALIGN(theSize);
return(theSize);
}
/* NextAppFile. Moves the specified AppFile pointer past its data. */
void
NextAppFile(AppFile **ppAppFile)
{
AppFile *pAppFile;
/* Bump pointer by size of data */
pAppFile = *ppAppFile;
(Ptr) pAppFile += SizeOfThisAppFile(pAppFile);
*ppAppFile = pAppFile;
}
/* CopyAppParmHandle. Copy the specified AppParmRecHdl into the current zone, and
* set up the p_appWDList for later consumption by OpenAppWDs.
*/
void
CopyAppParmHandle(AppParmRecHdl sourceAPH, PCB **hPCB)
{
AppWDRecPtr dstLoc;
AppWDListPtr pWDList;
AppWDListHdl hWDList;
AppParmRecPtr pAPH;
AppFile *parmLoc;
short parmCount = 0, sizeOfStruct;
/* In case of error */
(*hPCB)->p_appWDList = nil;
/* Copy the APPPARMHANDLE into new zone. Allocate it low so we can lock it.
* NOTE: Locking the AppParmHandle is done explicitly for MacWrite 4.5 (and
* 4.6?) and should someday be removed.
*/
ResrvMem(GetHandleSize(sourceAPH));
HandToHand(&sourceAPH);
if (MEMERROR != noErr)
return;
HLock(sourceAPH);
APPPARMHANDLE = sourceAPH;
pAPH = *sourceAPH;
/* See how many files there are. Get out if there are none. */
parmCount = pAPH->count;
if (parmCount == 0)
return;
/* Allocate the list in a relocatable block in the current heap */
sizeOfStruct = sizeof(AppWDList) + (parmCount * sizeof(AppWDRec));
if ( (hWDList = (AppWDListHdl) NewHandleClear(sizeOfStruct)) == nil )
{
DisposHandle(sourceAPH);
return;
}
/* Traverse the APPPARMHANDLE to save off the WD information therein */
pWDList = *hWDList;
pWDList->wdlCount = parmCount;
dstLoc = &(pWDList->wdlDirectories);
parmLoc = &(pAPH->appFiles[0]);
while (parmCount-- != 0)
{
(void) DecomposeWD(parmLoc->vRefNum, &dstLoc->awdVolume, &dstLoc->awdDirID);
parmLoc->vRefNum = 0;
NextAppFile(&parmLoc);
dstLoc++;
}
(*hPCB)->p_appWDList = hWDList;
}
/* SetAppParameters. Ensures that the new app gets the intended parameters in a
* form it can understand. This can mean translating from an AppleEvent to an
* APPPARMHANDLE, or vice versa. It definitely means saving the necessary working
* directory info.
*/
void
SetAppParameters(PCB **hPCB, unsigned long currentA5, register InternalLaunchPBPtr pParams, Boolean appDoesEppc)
{
PCB *pPCB;
DASpecBlockPtr pDAInfo;
AppParmRecHdl aph;
struct appparmarea *parm;
/* Get the resource file directory. If this is DA Handler being launched,
* the resource file directory is the one containing the Desk Accessory file.
*/
pPCB = *hPCB;
if ((pDAInfo = pParams->ilDAInfoPtr) == nil)
{
pPCB->p_appVolume = (pParams->ilAppSpecPtr)->vRefNum;
pPCB->p_appDirID = (pParams->ilAppSpecPtr)->parID;
}
else
{
pPCB->p_appVolume = (pDAInfo->daFileSpec)->vRefNum;
pPCB->p_appDirID = (pDAInfo->daFileSpec)->parID;
}
/* Convert DocList to AppParmRecHdl or vice-versa. Do nothing for the thoroughly
* modern case of the launcher giving an AppleEvent to an AppleEvent-aware launchee,
* except to ensure that the launchee gets an saeLaunchedWithoutDocs ('oapp') in
* case ilAppParameters is nil (AppleEvent-aware applications count on seeing an
* AppleEvent at startup, knowing that it came from the launcher and not sometime
* after they were launched).
*/
aph = APPPARMHANDLE;
APPPARMHANDLE = nil;
if (pParams->ilAppParameters != APPPARMS_NOT_SPECIFIABLE)
{
if (appDoesEppc == false)
{
APPPARMHANDLE = AEParmToAppParmHandle(pParams->ilAppParameters, hPCB);
pParams->ilAppParameters = nil;
}
else if (pParams->ilAppParameters == nil)
pParams->ilAppParamHdl = AppParmHandleToAEParm(nil);
}
else
{
pParams->ilAppParameters = nil;
if (appDoesEppc)
pParams->ilAppParamHdl = AppParmHandleToAEParm(aph);
else if ((aph != nil) && (*aph != nil))
CopyAppParmHandle(aph, hPCB);
}
/* fix up application parameter area */
parm = (struct appparmarea *) ((Ptr)currentA5 + 8);
parm->stdin = 0;
parm->stdout = 0;
parm->physexec = 0;
parm->parmhandle = APPPARMHANDLE;
}
/* OpenAppWDs. Open the working directories needed by a new application. Also
* sets CURDIRSTORE and SFSAVEDISK according to the last file in APPPARMHANDLE
* (if there is no APPPARMHANDLE, it uses the resource file directory).
*/
void
OpenAppWDs(PEntryPtr pProc)
{
AppWDListHdl hWDList;
AppWDRecPtr pWDInfo;
short wdCount;
WDPBRec wdpbrec;
AppFile *pAppFile;
PCB *pPCB;
/* Open home working directory */
wdpbrec.ioNamePtr = nil;
wdpbrec.ioCompletion = nil;
pPCB = *(pProc->p_pcb);
wdpbrec.ioVRefNum = pPCB->p_appVolume;
wdpbrec.ioWDDirID = pPCB->p_appDirID;
wdpbrec.ioWDProcID = 0;
PBOpenWD(&wdpbrec, SyncHFS);
(*pProc->p_pcb)->p_vrefnum = wdpbrec.ioVRefNum;
SetVol(nil, wdpbrec.ioVRefNum);
/* Get list of parameter WDs to open, if any. */
if ((hWDList = (*pProc->p_pcb)->p_appWDList) == nil)
{
SFSAVEDISK = -(pPCB->p_appVolume);
CURDIRSTORE = pPCB->p_appDirID;
return;
}
/* Traverse said list, opening a WD from the component info. Note that the
* volume/dirid that ultimately get used for SFSAVEDISK and CURDIRSTORE will
* be from the last AppFile in APPPARMHANDLE.
*/
HLock(hWDList);
wdCount = (*hWDList)->wdlCount;
pWDInfo = &((*hWDList)->wdlDirectories);
if (APPPARMHANDLE != nil)
pAppFile = &((*(AppParmRecHdl) APPPARMHANDLE)->appFiles[0]);
while (wdCount-- != 0)
{
wdpbrec.ioVRefNum = pWDInfo->awdVolume;
wdpbrec.ioWDDirID = pWDInfo->awdDirID;
wdpbrec.ioWDProcID = 0;
PBOpenWD(&wdpbrec, SyncHFS);
pAppFile->vRefNum = wdpbrec.ioVRefNum;
SFSAVEDISK = -(pWDInfo->awdVolume);
CURDIRSTORE = pWDInfo->awdDirID;
NextAppFile(&pAppFile);
pWDInfo++;
}
/* Free the memory */
DisposHandle(hWDList);
(*pProc->p_pcb)->p_appWDList = nil;
}
/* BeginApplication. Code executed by a newborn process after it is switched in for
* the very first time. Set up the toolbox and OS worlds.
*/
void
BeginApplication(void)
{
#ifdef HAS_AUX_PROCESSMGR
void (*auxidleprocptr)();
#endif HAS_AUX_PROCESSMGR
unsigned long olda5;
olda5 = ProcessMgrA5SimpleSetup();
if (MachineHasFPU)
FPInit();
/* Fix up working directories for home directory and files in APPPARMHANDLE */
OpenAppWDs(pCurrentProcess);
#ifdef HAS_AUX_PROCESSMGR
auxidleprocptr = ((pCurrentProcess->p_taskmode & COFF_BINARY) != 0) ? AUX_IdleProc : nil;
#endif HAS_AUX_PROCESSMGR
A5SimpleRestore(olda5);
/* now call toolbox/system initializing trap */
InitApplication();
#ifdef HAS_AUX_PROCESSMGR
/* Let coff binary be initialized and scheduled by AUX.
* NOTE: AUX context switch will probably occur hereÉ
*/
if (auxidleprocptr != nil)
(*auxidleprocptr)();
#endif HAS_AUX_PROCESSMGR
}
#pragma segment kernel_segment
/* c_rdrvrinstall. Fix up the unit table when the application zone is nuked.
* NOTE: Also, gives appropriate GBKisses to drivers, which is not done in the ROM
* routine (Done inline in _ExitToShell/_Launch) but no one except _ExitToShell should
* be calling this anyway.
* NOTE: Needs to be same segment as kill_dce.
*/
pascal void
c_rdrvrinstall(void)
{
kill_dce(APPLZONE);
}