mac-rom/ProcessMgr/SegmentLoaderPatches.c

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);
}