mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-14 21:29:53 +00:00
4325cdcc78
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.
881 lines
24 KiB
C
881 lines
24 KiB
C
/*
|
|
File: OSDispatch.c
|
|
|
|
Contains: Selected Process Mgr dispatch routines.
|
|
|
|
Written by: Phil Goldman and Erich Ringewald
|
|
|
|
Copyright: © 1986-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<18> 9/4/92 DRF #1041525,<EA> Changed SameProcess() to handle the case where
|
|
there is no current process.
|
|
<17> 8/26/92 DTY Change ModSquadÕs funky conditional to use #ifdefs like everyone
|
|
else.
|
|
<16> 8/26/92 DTY Roll in latest changes for A/UX.
|
|
<15> 8/17/92 hjcr Adding support for OCE's "defer drag" feature. Conditionally
|
|
compiled under MODSQUAD
|
|
<14> 4/10/92 JSM Get rid of compiler warning from last change.
|
|
<13> 4/9/92 KST #1025131,<JH>: Changed SWM from a background app to a driver so
|
|
that input method can do dialog, change cursor, access the menu,
|
|
and type into the dialog window.
|
|
<12> 3/25/92 DTY #1024114,<pvh>: Added c_PEntryFromProcessSerialNumber. This is
|
|
identical to the PEntryFromPSN routine in Processes.c, except
|
|
that this follows Pascal calling conventions and is accessed as
|
|
a selector off of OSDispatch. Cube-E Finder needs this routine
|
|
so that it doesnÕt have to rely on hard coded offsets into
|
|
Process Manager globals for the application assassin code. The
|
|
ultimate solution would be to move the assassin into Launch and
|
|
remove this selector.
|
|
<11> 1/11/92 YK Added NewTSMLayerOwner and RouteEventToSWM for TSM.
|
|
<10> 10/16/91 YK Added c_InlineAware for supporting the Text Services Manager.
|
|
<9> 10/9/91 DTY Add #include "OSDispatchPrivate.h" for new definition of
|
|
FindAppLayer(). The build was broken because FindAppLayer() was
|
|
changed to FindAppBaseLayer(), and FindAppLayer() became a macro
|
|
which called the new name. This file wasnÕt updated to reflect
|
|
the new scheme of things.
|
|
<8> 1/14/91 DFH Fix checkin comment.
|
|
<7> 1/14/91 DFH (dba) Make system mode per process.
|
|
<6> 1/14/91 DFH (JDR) Conditionalize out AUX support.
|
|
<4> 1/8/91 DFH (rdd) Changed c_SetFrontProcess to allow for case where
|
|
destination process is already frontmost, but suspended for
|
|
high-level debugging.
|
|
<3> 12/20/90 DFH (dba) Remove obsolete dispatch routine TWKill.
|
|
<2> 12/5/90 DFH Integrate AUX support.
|
|
<0> x/xx/86 PYG New Today.
|
|
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <memory.h>
|
|
#include <files.h>
|
|
#include <quickdraw.h>
|
|
#include <windows.h>
|
|
#include <menus.h>
|
|
#include <events.h>
|
|
#include <resources.h>
|
|
#include <osutils.h>
|
|
#include <toolutils.h>
|
|
#include <retrace.h>
|
|
#include <desk.h>
|
|
#include <dialogs.h>
|
|
#include <errors.h>
|
|
|
|
#include "Glue.h"
|
|
#include "Lomem.h"
|
|
#include "Data.h"
|
|
#include "SysMisc.h"
|
|
#include "Aux.h"
|
|
#include "Puppet.h"
|
|
#include "OSDispatchPrivate.h"
|
|
|
|
/*------------------------------------------------------------------
|
|
|
|
Here are the exported (via Trap) task management calls.
|
|
|
|
------------------------------------------------------------------*/
|
|
|
|
#pragma segment kernel_segment
|
|
|
|
/* c_KernelLaunch. Launch a task into a new partition. */
|
|
pascal OSErr
|
|
c_KernelLaunch(InternalLaunchPBPtr pParams)
|
|
{
|
|
unsigned long olda5;
|
|
OSErr err, NewProcess(InternalLaunchPBPtr);
|
|
void DisposeProcessEntry(PEntryPtr);
|
|
|
|
/* Get access to our globals, and switch to launchee's volume */
|
|
olda5 = ProcessMgrA5Setup();
|
|
|
|
/* Create a new process. Let AUX have the first chance at it. */
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
if (AUXIsPresent)
|
|
{
|
|
err = AUX_Launch(pParams);
|
|
if ((err == permErr))
|
|
err = NewProcess(pParams);
|
|
}
|
|
else
|
|
#endif HAS_AUX_PROCESSMGR
|
|
err = NewProcess(pParams);
|
|
|
|
A5Restore(olda5);
|
|
return(err);
|
|
}
|
|
|
|
/* TWFGSwitch. This routine arranges for a foreground switch from the current application
|
|
* to the given one. Note: It is OK for a task to switch to itself, as long as it's not
|
|
* currently the foreground task. In this way a background app could force itself to the
|
|
* front.
|
|
* NOTE: This is the old call, so it just defers to the current one (SetFrontProcess).
|
|
*/
|
|
pascal long
|
|
c_TWFGSWitch(ProcessID pid)
|
|
{
|
|
PEntryPtr pProc;
|
|
|
|
/* Locate the process. */
|
|
if ((pProc = PEntryFromPID(pid)) == nil)
|
|
return(procNotFound);
|
|
|
|
return(SetFrontProcess(&pProc->p_serialNumber));
|
|
}
|
|
|
|
/* KillProcess. Terminate the given process. Actually, this just puts the process
|
|
* in a state where the next switch in will make it ExitToShell. This way, the
|
|
* low memory/trap patch/VBL/etc context is correct for the cleanup.
|
|
*/
|
|
pascal OSErr
|
|
c_KillProcess(ProcessSerialNumberPtr pPSN)
|
|
{
|
|
PEntryPtr pDeadMeat;
|
|
unsigned long olda5;
|
|
void PushOnStateList(PEntryPtr, PEntryPtr *);
|
|
|
|
/* Locate the poor thing */
|
|
if ((pDeadMeat = PEntryFromPSN(pPSN)) == nil)
|
|
return(procNotFound);
|
|
|
|
/* Special case! */
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
if (pDeadMeat == pCurrentProcess)
|
|
ExitToShell();
|
|
|
|
/* Rouse him from his slumber */
|
|
CancelSleep(pDeadMeat);
|
|
|
|
/* And throw him into the chute */
|
|
if (pDeadMeat->p_condemned == wFalse)
|
|
{
|
|
pDeadMeat->p_condemned = wTrue;
|
|
PushOnStateList(pDeadMeat, &pDyingStateList);
|
|
}
|
|
|
|
A5SimpleRestore(olda5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* TWGetPID. Return the currently running process ID. */
|
|
pascal ProcessID
|
|
c_TWGetPID(void)
|
|
{
|
|
unsigned long olda5;
|
|
ProcessID retval;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
retval = (pCurrentProcess != nil) ? pCurrentProcess->p_mypid : 0;
|
|
A5SimpleRestore(olda5);
|
|
return(retval);
|
|
}
|
|
|
|
/* TWGetProcInfo. This routine fills in the data of the passed info record for the
|
|
* given process ID. Returns noErr for real processes, or procNotFound for a bogus
|
|
* ProcessID.
|
|
*/
|
|
pascal long
|
|
c_TWGetProcInfo(ProcessID pid, struct procinfo *inforec)
|
|
{
|
|
PEntryPtr p, pDadProc;
|
|
PCB *pc;
|
|
THz savezone;
|
|
unsigned long olda5;
|
|
|
|
if ((p = PEntryFromPID(pid)) == nil)
|
|
return(procNotFound);
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
inforec->p_state = p->p_state;
|
|
inforec->p_mypid = p->p_mypid;
|
|
inforec->p_type = p->p_type;
|
|
inforec->p_signature = p->p_signature;
|
|
inforec->p_version = p->p_version;
|
|
inforec->p_zone = p->p_zone;
|
|
inforec->p_taskmode = p->p_taskmode;
|
|
inforec->p_needsuspresevts = ((p->p_taskmode & modeNeedSuspendResume) != 0);
|
|
inforec->p_back = ((p->p_taskmode & modeCanBackground) != 0);
|
|
/* NOTE: Add this when next Finder created:
|
|
* inforec->p_isfirstbackevt = p->p_isfirstbackevt;
|
|
*/
|
|
inforec->p_activateonresume = ((p->p_taskmode & modeDoesActivateOnFGSwitch) != 0);
|
|
inforec->p_dad = ((pDadProc = p->p_dadProcess) != nil) ? pDadProc->p_mypid : 0;
|
|
inforec->p_size = p->p_size;
|
|
inforec->p_ssize = p->p_ssize;
|
|
inforec->p_slices = p->p_slices;
|
|
|
|
assert(p->p_pcb != nil);
|
|
pc = *p->p_pcb;
|
|
BlockMove(&pc->curapname, &inforec->p_name, 32);
|
|
inforec->p_vrefnum = pc->p_vrefnum;
|
|
|
|
/* NOTE: Assumes FreeMem can not cause ProcessMgrZone to move, since we restore the
|
|
* saved zone unconditionally, instead of using SafeSetZone and RestoreZone.
|
|
*/
|
|
savezone = THEZONE;
|
|
THEZONE = p->p_zone;
|
|
inforec->p_freemem = (unsigned long)(*p->p_pcb)->appllimit
|
|
- (unsigned long)((p->p_zone)->bkLim) + FreeMem();
|
|
THEZONE = savezone;
|
|
A5SimpleRestore(olda5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_GetCurrentProcess. Return the serial number of the currently running process.
|
|
* NOTE: Must allow for times when there is no current process (e.g. during a switch).
|
|
*/
|
|
pascal OSErr
|
|
c_GetCurrentProcess(ProcessSerialNumberPtr psnStorage)
|
|
{
|
|
PEntryPtr pCurrProc;
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
pCurrProc = pCurrentProcess;
|
|
if (pCurrProc != nil)
|
|
*psnStorage = pCurrProc->p_serialNumber;
|
|
else
|
|
SetPSN(kNoProcess, psnStorage);
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_GetSystemClientProcess. Return a process serial number to identify the party
|
|
* responsible for current system activity. This will be either "the system" or
|
|
* the current application.
|
|
*/
|
|
pascal OSErr
|
|
c_GetSystemClientProcess(ProcessSerialNumberPtr psnStorage)
|
|
{
|
|
OSErr retval;
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* Check depth counter */
|
|
if ((pCurrentProcess != nil) && (pCurrentProcess->p_systemModeLevel == 0))
|
|
retval = GetCurrentProcess(psnStorage);
|
|
else
|
|
{
|
|
SetPSN(kSystemProcess, psnStorage);
|
|
retval = noErr;
|
|
}
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(retval);
|
|
}
|
|
|
|
/* c_GetNextProcess. Return the next highest process serial number in use.
|
|
* NOTE: Assumes that the process list is in descending order of p_serialNumber.
|
|
*/
|
|
#define IS_GTE_PSN(src, dst) \
|
|
(((src)->highLongOfPSN != (dst)->highLongOfPSN) ? \
|
|
((src)->highLongOfPSN >= (dst)->highLongOfPSN) \
|
|
: ((src)->lowLongOfPSN >= (dst)->lowLongOfPSN))
|
|
pascal OSErr
|
|
c_GetNextProcess(ProcessSerialNumberPtr pParamPSN)
|
|
{
|
|
register PEntryPtr pProc, pPrev;
|
|
ProcessSerialNumberPtr pCheckPSN;
|
|
OSErr retVal = noErr;
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* Look for special values */
|
|
if (EqualPSNConst(kCurrentProcess, pParamPSN) && (pCurrentProcess != nil))
|
|
pCheckPSN = &pCurrentProcess->p_serialNumber;
|
|
else
|
|
pCheckPSN = pParamPSN;
|
|
|
|
/* Search the process list */
|
|
pPrev = nil;
|
|
pProc = pProcessList;
|
|
while (pProc != nil)
|
|
{
|
|
if (IS_GTE_PSN(pCheckPSN, &(pProc->p_serialNumber)))
|
|
break;
|
|
pPrev = pProc;
|
|
pProc = pProc->p_NextProcess;
|
|
}
|
|
|
|
/* If we actually found something, pProc points to the item after the desired
|
|
* one (nil if the desired one is last in the list). pPrev points to the desired
|
|
* one itself (nil if the desired one is first in the list). Handle these cases.
|
|
*/
|
|
if (pPrev != nil)
|
|
*pParamPSN = pPrev->p_serialNumber;
|
|
else
|
|
{
|
|
SetPSN(kNoProcess, pParamPSN);
|
|
retVal = procNotFound;
|
|
}
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return (retVal);
|
|
}
|
|
|
|
/* c_GetProcessFromLayer. Identify the process ultimately responsible for the
|
|
* given layer. If pLayer is -1, caller is asking for the frontmost process.
|
|
*/
|
|
pascal OSErr
|
|
c_GetProcessFromLayer(ProcessSerialNumberPtr pPSN, LayerPtr pLayer)
|
|
{
|
|
LayerPtr pAppLayer;
|
|
PEntryPtr pOwnerProc;
|
|
unsigned long olda5;
|
|
OSErr retval;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* Set up probable return value */
|
|
retval = noErr;
|
|
|
|
/* Weed out some bad cases */
|
|
if ((pLayer == nil) || (pPSN == nil))
|
|
retval = paramErr;
|
|
else
|
|
{
|
|
pAppLayer = (pLayer == (LayerPtr) -1) ? GetFrontAppLayer() : FindAppLayer((WindowPtr) pLayer);
|
|
if ( (pAppLayer != nil) && ((pOwnerProc = LayerOwner(pAppLayer)) != nil) )
|
|
*pPSN = pOwnerProc->p_serialNumber;
|
|
else
|
|
retval = procNotFound;
|
|
}
|
|
|
|
/* Return kNoProcess if caller goofed, or there is no front process */
|
|
if (retval != noErr)
|
|
SetPSN(kNoProcess, pPSN);
|
|
|
|
A5SimpleRestore(olda5);
|
|
return(retval);
|
|
}
|
|
|
|
/* c_SameProcess. Determine whether two ProcessSerialNumbers refer to the
|
|
* exact same process. Provided partially for convenience, but mainly so that
|
|
* we can keep the format of a PSN private (e.g. might want PSN to have subfields
|
|
* with abstract values, like machine ID).
|
|
*/
|
|
pascal OSErr
|
|
c_SameProcess(ProcessSerialNumberPtr pPSN1, ProcessSerialNumberPtr pPSN2, Boolean *pResult)
|
|
{
|
|
PEntryPtr pCurrProc;
|
|
ProcessSerialNumberPtr pCheckPSN1, pCheckPSN2;
|
|
u_long oldA5;
|
|
|
|
/* Weed out the hose heads */
|
|
if ( pPSN1 == nil || pPSN2 == nil || pResult == nil )
|
|
return(paramErr);
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* Convert special values to real PSNs */
|
|
pCheckPSN1 = pPSN1;
|
|
pCheckPSN2 = pPSN2;
|
|
if ((pCurrProc = pCurrentProcess) != nil)
|
|
{
|
|
if (EqualPSNConst(kCurrentProcess, pPSN1))
|
|
pCheckPSN1 = &pCurrProc->p_serialNumber;
|
|
|
|
if (EqualPSNConst(kCurrentProcess, pPSN2))
|
|
pCheckPSN2 = &pCurrProc->p_serialNumber;
|
|
}
|
|
#if TheFuture
|
|
else // DRF #1041525: Handle case where there is no current process
|
|
{
|
|
if (EqualPSNConst(kNoProcess, pPSN1))
|
|
SetPSN(kNoProcess,pCheckPSN1);
|
|
|
|
if (EqualPSNConst(kNoProcess, pPSN2))
|
|
SetPSN(kNoProcess,pCheckPSN2);
|
|
}
|
|
#endif
|
|
|
|
/* Compare them */
|
|
*pResult = EqualPSN(pCheckPSN1, pCheckPSN2);
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_GetProcessInformation. Fill caller's record with data about the specified
|
|
* process.
|
|
*/
|
|
|
|
/* Size of first ProcessInfoRec we ever defined */
|
|
#define FIRSTPROCESSINFORECLENGTH (11*sizeof(long) + 2*sizeof(ProcessSerialNumber))
|
|
|
|
pascal OSErr
|
|
c_GetProcessInformation(ProcessSerialNumberPtr pPSN, ProcessInfoRecPtr pStorage)
|
|
{
|
|
PEntryPtr pProc, pDadProc;
|
|
PCB *pPCB;
|
|
OSErr err = noErr;
|
|
FSSpecPtr pFileSpec;
|
|
FCBPBRec fcbInfo;
|
|
THz savezone;
|
|
u_long oldA5;
|
|
|
|
/* check for dupes */
|
|
if ((pStorage == nil) || (pStorage->processInfoLength < FIRSTPROCESSINFORECLENGTH))
|
|
return(paramErr);
|
|
|
|
/* Can't do anything if there is no such process */
|
|
if ((pProc = PEntryFromPSN(pPSN)) == nil)
|
|
return(procNotFound);
|
|
|
|
/* Fill in the record. */
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
assert(pProc->p_pcb != nil);
|
|
pPCB = *pProc->p_pcb;
|
|
|
|
if (pStorage->processName != nil)
|
|
BlockMove(&pPCB->curapname, pStorage->processName, 32);
|
|
|
|
pStorage->processNumber = pProc->p_serialNumber;
|
|
pStorage->processSignature = pProc->p_signature;
|
|
pStorage->processType = pProc->p_type;
|
|
pStorage->processMode = pProc->p_taskmode;
|
|
|
|
/* Get process location, size, and amount of free memory.
|
|
* NOTE: Locates PCB via handle so that we are independant of evaluation order (in
|
|
* case FreeMem() moves memory).
|
|
* NOTE: Assumes FreeMem can not cause ProcessMgrZone to move, since we restore saved
|
|
* zone unconditionally, instead of using SafeSetZone and RestoreZone.
|
|
*/
|
|
pStorage->processLocation = (Ptr) pProc->p_zone;
|
|
pStorage->processSize = pProc->p_size;
|
|
savezone = THEZONE;
|
|
THEZONE = pProc->p_zone;
|
|
pStorage->processFreeMem = (unsigned long) (*pProc->p_pcb)->appllimit
|
|
- (unsigned long)((pProc->p_zone)->bkLim) + FreeMem();
|
|
THEZONE = savezone;
|
|
pPCB = *pProc->p_pcb;
|
|
|
|
/* Get information about launcher */
|
|
if ((pDadProc = pProc->p_dadProcess) != nil)
|
|
pStorage->processLauncher = pDadProc->p_serialNumber;
|
|
else
|
|
SetPSN(kNoProcess, &pStorage->processLauncher);
|
|
pStorage->processLaunchDate = pPCB->launchDate;
|
|
|
|
/* Get scheduling information */
|
|
pStorage->processActiveTime = pProc->p_activeTime;
|
|
|
|
/* Get the specification for the application or DA file. */
|
|
|
|
if ((pFileSpec = pStorage->processAppSpec) != nil)
|
|
{
|
|
fcbInfo.ioFCBIndx = 0;
|
|
fcbInfo.ioRefNum = pPCB->p_fileRefNum;
|
|
fcbInfo.ioNamePtr = &pFileSpec->name;
|
|
fcbInfo.ioCompletion = nil;
|
|
if ((err = PBGetFCBInfo(&fcbInfo, SyncHFS)) == noErr)
|
|
{
|
|
pFileSpec->vRefNum = fcbInfo.ioFCBVRefNum;
|
|
pFileSpec->parID = fcbInfo.ioFCBParID;
|
|
}
|
|
}
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(err);
|
|
}
|
|
|
|
/* c_SetFrontProcess. Cause the specified process to become the frontmost. */
|
|
pascal OSErr
|
|
c_SetFrontProcess(ProcessSerialNumberPtr pPSN)
|
|
{
|
|
PEntryPtr pProc, pFront;
|
|
u_long oldA5;
|
|
|
|
/* Locate the process */
|
|
if ((pProc = PEntryFromPSN(pPSN)) == nil)
|
|
return(procNotFound);
|
|
|
|
/* Can't switch background-only process to the front! */
|
|
if ((pProc->p_taskmode & modeOnlyBackground) != 0)
|
|
return(appIsDaemon);
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
pFront = pFrontProcess;
|
|
|
|
/* Is specified process suspended for high-level debugging? */
|
|
if (pProc->p_state == PRNULL)
|
|
{
|
|
/* Don't allow switch to debuggee unless current process is the debugger. */
|
|
if (pCurrentProcess != pDebugProcess)
|
|
{
|
|
A5SimpleRestore(oldA5);
|
|
return(procNotFound);
|
|
}
|
|
|
|
/* If debuggee is still in front, all we need to do is allow it to run */
|
|
if (pProc == pFront)
|
|
{
|
|
pProc->p_state = PRREADY;
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
}
|
|
|
|
/* Don't switch to fg guy! */
|
|
if (pProc != pFront)
|
|
{
|
|
/* Since this may be done from a background app, we wakeup the current
|
|
* front process so it can start the coercion.
|
|
*/
|
|
CancelSleep(pFront);
|
|
|
|
/* Herd him in */
|
|
AddToFrontProcessQueue(pProc);
|
|
}
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* Wakeup. Wake up the given task, or at least tell MF you'd like to. We
|
|
* don't adjust the list right now, because this call could be being made by
|
|
* an interrupt routine while we are otherwise looking at the list. Instead,
|
|
* we flag the list, then do the move at a more synchronous time.
|
|
* NOTE: Should we dump this now that WakeupProcess is the public trap?
|
|
*/
|
|
short
|
|
c_Wakeup(ProcessID pid)
|
|
{
|
|
PEntryPtr pPEntry;
|
|
|
|
dbmsg("Current app using unpublished TWWakeup trap!");
|
|
if ((pPEntry = PEntryFromPID(pid)) == nil)
|
|
return(procNotFound);
|
|
|
|
return(WakeUpProcess(&pPEntry->p_serialNumber));
|
|
}
|
|
|
|
/* c_WakeUpProcess. Rouse the specified process from the sleep induced by waiting
|
|
* for an event. We don't adjust the list right now, because this call could be
|
|
* being made by an interrupt routine while we are otherwise looking at the list.
|
|
* Instead, we flag the list, then do the move at a more synchronous time.
|
|
* NOTE: We zero the p_wakeuptime even if p_state != PRSLEEPING. This keeps the
|
|
* the app from sleeping at the end of its current event call in some intermediate
|
|
* state like PRUPDATE. Of course, this only works if the app is in the event call
|
|
* that would sleep him. If instead, it is in the middle of a series (like you might
|
|
* see for PRUPDATE), the effect is lost.
|
|
*/
|
|
pascal OSErr
|
|
c_WakeUpProcess(ProcessSerialNumberPtr pPSN)
|
|
{
|
|
PEntryPtr pPEntry;
|
|
u_long oldA5;
|
|
|
|
/* Can't wake someone who isn't sleeping */
|
|
if ((pPEntry = PEntryFromPSN(pPSN)) == nil)
|
|
return(procNotFound);
|
|
|
|
/* Set flag we'll see in scheduler and/or event calls. */
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
if (pPEntry->p_state == PRSLEEPING)
|
|
napOver = true;
|
|
pPEntry->p_wakeuptime = 0;
|
|
#ifdef HAS_AUX_PROCESSMGR
|
|
pPEntry->wakeup_flag++;
|
|
#endif HAS_AUX_PROCESSMGR
|
|
A5SimpleRestore(oldA5);
|
|
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_BeginSystemMode. Switch to a mode where GetSystemClientProcess will indicate
|
|
* "the system". This is so that the ROM/system can obtain files, memory, etc.
|
|
* that will not be tracked by application death.
|
|
*/
|
|
pascal OSErr
|
|
c_BeginSystemMode(void)
|
|
{
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
if (pCurrentProcess != nil)
|
|
pCurrentProcess->p_systemModeLevel += 1;
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_EndSystemMode. Potentially switch out of "system mode". Is not really out
|
|
* if caller is nested in mode.
|
|
*/
|
|
pascal OSErr
|
|
c_EndSystemMode(void)
|
|
{
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
if ((pCurrentProcess != nil) && (pCurrentProcess->p_systemModeLevel != 0))
|
|
pCurrentProcess->p_systemModeLevel -= 1;
|
|
A5SimpleRestore(oldA5);
|
|
return(noErr);
|
|
}
|
|
|
|
|
|
/* NewDesktopLayerOwner. The shell (Finder) calls this trap to gain ownership of the
|
|
* desktop appearance. We hand back the DeskPort we found earlier. The shell will
|
|
* copy the updateRgn into its own window.
|
|
*/
|
|
pascal OSErr
|
|
c_newdesktoplayerowner(LayerPtr *ppNewLayer)
|
|
{
|
|
u_long olda5;
|
|
OSErr retval;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
if (desklayerowner == nil)
|
|
{
|
|
*ppNewLayer = desklayer;
|
|
desklayerowner = pCurrentProcess;
|
|
retval = noErr;
|
|
}
|
|
else
|
|
retval = protocolErr;
|
|
|
|
A5SimpleRestore(olda5);
|
|
return(retval);
|
|
}
|
|
|
|
// <12> PEntryFromProcessSerialNumber. Locate existing process having given ProcessSerialNumber.
|
|
// This routine is a duplicate of PEntryFromPSN in Processes.c so that the Cube-E Finder doesnÕt
|
|
// have hard coded offsets to Process Manager globals to do the application
|
|
// assassin stuff. In the long run, we should get rid of this routine, and
|
|
// implement the assassin as a new launch flag.
|
|
|
|
pascal PEntryPtr
|
|
c_PEntryFromProcessSerialNumber(ProcessSerialNumberPtr pPSN)
|
|
{
|
|
register PEntryPtr pProc;
|
|
unsigned long oldA5;
|
|
|
|
/* Weed out the junkies */
|
|
if (pPSN == nil)
|
|
return(nil);
|
|
|
|
/* Look first for special value */
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
if ((pPSN->lowLongOfPSN == kCurrentProcess) && (pPSN->highLongOfPSN == 0))
|
|
pProc = pCurrentProcess;
|
|
else
|
|
{
|
|
/* Loop until ProcessSerialNumber matches or end of list */
|
|
pProc = pProcessList;
|
|
while (pProc != nil)
|
|
{
|
|
if (EqualPSN(&pProc->p_serialNumber, pPSN))
|
|
break;
|
|
|
|
pProc = pProc->p_NextProcess;
|
|
}
|
|
}
|
|
|
|
A5SimpleRestore(oldA5);
|
|
return(pProc);
|
|
}
|
|
|
|
/* DisableSwitching. This routine arranges such that the calling process
|
|
* will not be switched for any reason.
|
|
*/
|
|
pascal void
|
|
c_DisableSwitching(void)
|
|
{
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
dont_switch++;
|
|
A5SimpleRestore(olda5);
|
|
}
|
|
|
|
/* EnableSwitching. This routine arranges such that the calling process
|
|
* will be switched for any reason.
|
|
*/
|
|
pascal void
|
|
c_EnableSwitching(void)
|
|
{
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
if (dont_switch > 0)
|
|
dont_switch--;
|
|
A5SimpleRestore(olda5);
|
|
}
|
|
|
|
PrTypeString globalPrTypeString;
|
|
|
|
/* [GS]etPrTypeStrings. These routines read and write the name of the current
|
|
* printer type for a given process and the current global printer -- the real one.
|
|
* NOTE: The interface should be changed to copy the strings because *pLocalStrPtr
|
|
* is in the middle of the pcb and thus can move.
|
|
*/
|
|
pascal char
|
|
c_GetPrTypeStrings(PrTypeStringPtr *pLocalStrPtr, PrTypeStringPtr *pGlobalStrPtr)
|
|
{
|
|
unsigned long olda5;
|
|
PrTypeStringHandle prTypeStringHdl;
|
|
PCB *pPCB;
|
|
char enablePrTypeChanges;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
#ifndef CHOOSE_CALLS_SETPRTYPESTRINGS
|
|
Length(&globalPrTypeString) = 0;
|
|
|
|
/* Make sure ResLoad is true, so we get the data */
|
|
{
|
|
Boolean oldResLoad = RESLOAD;
|
|
|
|
RESLOAD = true;
|
|
prTypeStringHdl = GetResource('STR ',-8192);
|
|
RESLOAD = oldResLoad;
|
|
}
|
|
|
|
if (prTypeStringHdl != nil)
|
|
{
|
|
BlockMove(*prTypeStringHdl, &globalPrTypeString, PRTYPE_STRING_SIZE);
|
|
ReleaseResource(prTypeStringHdl);
|
|
}
|
|
#endif
|
|
*pGlobalStrPtr = &globalPrTypeString;
|
|
|
|
assert(pCurrentProcess->p_pcb != nil);
|
|
pPCB = *pCurrentProcess->p_pcb;
|
|
*pLocalStrPtr = &(pPCB->localPrTypeString);
|
|
if (Length(&(pPCB->localPrTypeString)) == 0) /* Is there a local one yet? */
|
|
BlockMove(&globalPrTypeString, *pLocalStrPtr, PRTYPE_STRING_SIZE);
|
|
|
|
enablePrTypeChanges = pPCB->enablePrTypeChanges;
|
|
|
|
A5SimpleRestore(olda5);
|
|
return enablePrTypeChanges;
|
|
}
|
|
|
|
pascal void
|
|
c_SetPrTypeStrings(PrTypeStringPtr localStrPtr, PrTypeStringPtr globalStrPtr, char enablePrTypeChanges)
|
|
{
|
|
unsigned long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
|
|
if (globalStrPtr != nil)
|
|
BlockMove(globalStrPtr, &globalPrTypeString, PRTYPE_STRING_SIZE);
|
|
|
|
if (localStrPtr != nil)
|
|
BlockMove(localStrPtr, &((*pCurrentProcess->p_pcb)->localPrTypeString), PRTYPE_STRING_SIZE);
|
|
|
|
assert(PRTYPE_CHANGESTATUS_SAME == (-1))
|
|
if (enablePrTypeChanges >= 0)
|
|
(*pCurrentProcess->p_pcb)->enablePrTypeChanges = enablePrTypeChanges;
|
|
|
|
A5SimpleRestore(olda5);
|
|
}
|
|
|
|
/* c_TWPostAllPseudoEvent. Don't need anymore. SysError instead. (August 90) */
|
|
pascal short
|
|
c_TWPostAllPseudoEvent(long signature, long tyype, EventRecord *pEvent, u_short priority)
|
|
{
|
|
#pragma unused (signature, tyype, pEvent, priority)
|
|
SysError(dsCoreErr);
|
|
return(noErr);
|
|
}
|
|
|
|
/* c_TWPostPseudoEvent. Don't need anymore. SysError instead. (August 90) */
|
|
pascal void
|
|
c_TWPostPseudoEvent(ProcessID pid, EventRecord *pEvent, u_short priority)
|
|
{
|
|
#pragma unused (pid, pEvent, priority)
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* c_SetStdFileDir. Don't support anymore. SysError instead. (August 90) */
|
|
pascal void
|
|
c_SetStdFileDir(ProcessID pid, short sfSaveDisk, unsigned long curDirID)
|
|
{
|
|
#pragma unused (pid, sfSaveDisk, curDirID)
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
/* c_BackgroundNotify. Can't support anymore. SysError instead. (November 89) */
|
|
pascal void
|
|
c_BackgroundNotify(StringPtr msgStringPtr)
|
|
{
|
|
#pragma unused (msgStringPtr)
|
|
SysError(dsCoreErr);
|
|
}
|
|
|
|
#ifdef MODSQUAD
|
|
pascal OSErr c_AcceptDrag(void)
|
|
{
|
|
u_long oldA5;
|
|
OSErr retval = noErr;
|
|
|
|
//Debugger();
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
if (pCurrentProcess && pCurrentProcess->p_state == PRSTARTDRAG)
|
|
gDragState = DRAG_DONE;
|
|
else
|
|
retval = protocolErr; // What should I return here?
|
|
A5SimpleRestore(oldA5);
|
|
return(retval);
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************************
|
|
* Text Services Manager supporting routine.
|
|
************************************************************************************/
|
|
pascal Boolean
|
|
c_InlineAware(ProcessSerialNumberPtr pPSN, Boolean aware)
|
|
{
|
|
Boolean prevValue;
|
|
PEntryPtr pPEntry;
|
|
u_long oldA5;
|
|
|
|
if ((pPEntry = PEntryFromPSN(pPSN)) == nil)
|
|
return(procNotFound);
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
prevValue = pPEntry->p_inlineAware;
|
|
pPEntry->p_inlineAware = aware;
|
|
WakeUpProcess(&pFrontProcess->p_serialNumber);
|
|
A5SimpleRestore(oldA5);
|
|
|
|
return(prevValue);
|
|
}
|
|
|
|
pascal OSErr
|
|
c_NewTSMLayerOwner( const ProcessSerialNumber *pPSN)
|
|
{
|
|
OSErr retval;
|
|
u_long olda5;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
if (tsmLayerOwner == nil)
|
|
{
|
|
tsmLayerOwner = (PEntryPtr)(pPSN->lowLongOfPSN); // owner is the driver refnum
|
|
retval = noErr;
|
|
}
|
|
else
|
|
retval = protocolErr;
|
|
|
|
A5SimpleRestore(olda5);
|
|
return(retval);
|
|
}
|
|
|
|
pascal Boolean
|
|
c_RouteEventToSWM( Boolean doRoute)
|
|
{
|
|
Boolean prevValue;
|
|
u_long oldA5;
|
|
|
|
oldA5 = ProcessMgrA5SimpleSetup();
|
|
prevValue = routeEvent;
|
|
routeEvent = doRoute;
|
|
A5SimpleRestore(oldA5);
|
|
|
|
return(prevValue);
|
|
}
|