mac-rom/OS/PPC/PPCEntry.c
Elliot Nunn 4325cdcc78 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-12-26 09:52:23 +08:00

917 lines
30 KiB
C

/*
File: PPCEntry.c
Contains: PPC Dispatcher of various calls
Written by: Sangam, Eric M. Trehus
Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
Change History (most recent first):
<39> 4/14/92 BBM <JSM>: Remove unfinished PPC code that is under the contitional
ÒTheFututeÓ, and remove the conditional ÒCubeEÓ since that is
reality. Remove conditionals, since all they do is confuse.
<38> 10/4/91 JSM Change PsychoticFarmerOrLater conditionals to TheFuture.
<37> 9/30/91 DTY DeanÕs in the dog house. The System build got derailed with that
last change.
<36> 9/29/91 DTY Conditionalize <33> through <35> out of CubeE.
<35> 6/26/91 EMT Add support to kill PPCInform calls
<34> 6/10/91 EMT Check for duplicate completion.
<33> 6/4/91 EMT Roll in StoreAndForward Revisions
<32> 1/7/91 EMT <VC> Fix bug that causes machine to hang in PPCStart and
IPCListPorts, related to GetMyZone call.
<31> 12/13/90 EMT <JSM> Change calling conventions to support new glue, and Inline
Async/Sync parameterless calls.
<30> 11/28/90 EMT <VC> Fix/Work around bug that prevents my completion routine
from being called.
<29> 11/8/90 EMT Change how PPCStart and IPCListports determine if the session is
local or not. Because we can't assume that the zone name in our
globals is correct.
<28> 11/6/90 EMT Changing CheckLocName to not used IUEqualString where it is not
needed
<27> 10/30/90 EMT Fix usage and bug in PPCCommonPBEntry, that would not call
completion routine if an error occured because we weren't
initialized or had no globals.
<26> 10/19/90 JSM <EMT> Break out PPCEntry() into separate routines for new
dispatching scheme.
<25> 10/18/90 EMT Change userName to machineName where needed
<24> 10/11/90 EMT Remove #define DEBUG
<23> 9/21/90 EMT Update constants, types, and field names as dictated by
PPCToolBox.h
<22> 9/16/90 EMT Fix bug
<21> 9/15/90 EMT Fix CheckLocName bug introduced.
<20> 9/14/90 EMT Make changes to support only type specification in PPCOpen with
location name.
<19> 9/5/90 EMT Make this file C3.0 friendly
<18> 9/4/90 EMT Eric's changes rolled in
<17> 8/6/90 S Bug Fixes.
<16> 6/28/90 S To Improve Dynamic allocation and fix other bugs.
<15> 4/24/90 S To Un fix Jeff's code changes.
<14> 4/18/90 JSM Add prototype for AvoidDuplicateCompletion, miscellaneous code
size reductions.
<13> 4/10/90 S To Support Network IPCList Port call when incomming sessions are
prevented.
<11> 3/5/90 S Don't Look for User &Group File at PPCOpen.
<10> 2/27/90 S Don't allow BOTH for PPCOpen.
<9> 2/13/90 S Some Error Code Changes.
<8> 2/7/90 S Bug Fix with PPCOpen call.
<7> 2/5/90 S Included check to ignore duplicate check for locName for
PPCOpen.
<6> 2/5/90 S Included Checking for netVisible Flag before making NBP
registration.
<5> 1/30/90 S Bug Fixes
<3+> 1/12/90 S Bug Fixes
<2+> 1/5/90 S Some Error Codes
<1.3> 10/12/89 CVC no change
<1.2> 10/12/89 CVC Handling NoLocName in PortLocName
<1.1> 9/25/89 ss Support port types.
<1.0> 9/18/89 CVC Adding PPC toolbox for the first time.
Old Revision History:
05/30/89 Sangam New Today
07/20/89 Sangam 1.0d2 release today!
07/25/89 Sangam Nbp name is concatenated strings for setuser nbp name
08/01/89 Sangam Fixed PPOpen for not registering name when ADSP is not there
08/09/89 Sangam Reverted back to unpacked format for location name
10/09/89 Sangam Handling NoLocName in PortLocName.
Returning noUserRecErr if user & group file is not there
but user wants authentication
1/4/90 Sangam Some bug fixes and return errorcode changes.
*/
#include "PPCCommon.h"
#include <Packages.h>
/*----------------------------------------------------------------------------------------
Prototypes used only in this file.
----------------------------------------------------------------------------------------*/
STATIC Boolean PPCCommonPBEntry(void *PB, PPCGlobalParamsPtr *ppcglobPtrPtr);
STATIC OSErr PPCCommonPBExit(void *PB, PPCGlobalParamsPtr ppcglobPtr);
STATIC void NetOpenCompletion(void); // <36>
STATIC void CallCompletionRoutine(PPCParamBlockPtr PB,OSErr ioResult);
STATIC Boolean LocNameTaken(LocationNamePtr locationName,PPCGlobalParamsPtr ppcglobPtr);
STATIC void BeginLocalOrRemote(PPCGlobalParamsPtr ppcglobPtr,PPCParamBlockPtr PB,void *portPtr);
STATIC void LocalOrNot(void);
STATIC void DoGetMyZone(XCallParam *xpb,Boolean async,ProcPtr compRtn,Str32 zoneName);
/*----------------------------------------------------------------------------------------
Main entry point to the PPCOpen call.
----------------------------------------------------------------------------------------*/
OSErr ppcOpen(PPCOpenPBPtr openPB)
{
PPCGlobalParamsPtr ppcglobPtr;
PPCPortEntryPtr portPtr; // <36>
LocationNamePtr theLocName;
if (PPCCommonPBEntry(openPB, &ppcglobPtr)) // do common entry code for parameter block based calls
{
openPB->csCode = PPCOpenCall; // save command code
openPB->nbpRegistered = false;
openPB->portRefNum = 0;
theLocName = openPB->locationName;
if(openPB->resFlag) // <36> Enforce resFlag == 0
{ // <36>
CompleteWithResult(openPB,badReqErr); // <36>
goto Done; // <36>
} // <36>
if (!ValidPortName(openPB->portName)) // <36> make sure the Port name looks good
{ // <36>
CompleteWithResult(openPB,badPortNameErr); // <36>
goto Done; // <36>
}
if (CheckPortName(openPB->portName, ppcglobPtr)) // make sure the Port name is not already in use
{
CompleteWithResult(openPB,portNameExistsErr);
goto Done;
}
if (openPB->serviceType != ppcServiceRealTime) // make sure we support this serviceType
{
CompleteWithResult(openPB,badServiceMethodErr);
goto Done;
}
if (openPB->networkVisible && openPB->locationName)
{
if (theLocName->locationKindSelector != ppcNBPTypeLocation)
{
CompleteWithResult(openPB,nameTypeErr); // <36>
goto Done; // <36>
}
if (theLocName->u.nbpType[0] > 32 || theLocName->u.nbpType[0] == 0)
{
CompleteWithResult(openPB,badLocNameErr);
goto Done;
}
if(LocNameTaken(openPB->locationName,ppcglobPtr))
{
CompleteWithResult(openPB,nbpDuplicate);
goto Done;
}
}
if (!(portPtr = GetPortTable(openPB, ppcglobPtr))) // make sure this port exists
{
CompleteWithResult(openPB,noPortErr);
goto Done;
}
if (portPtr->locationInfo) // If client wants a location name with the port
{
if(ppcglobPtr->allowIncommingRequests) // Are we allowing incomming IAC.
{
PortLocationTablePtr locInfo;
locInfo = portPtr->locationInfo;
RegisterName(ppcglobPtr->machineName, // use our machine name
locInfo->typeStr, // use the type specified.
"\p*", // always *
ppcglobPtr->adspSocket, // socket to register name on
true, // Call ASyncronously
(ProcPtr)NetOpenCompletion, // NBPCompletion routine
(Ptr)&locInfo->nteQEle, // ntePtr
&locInfo->nbpPB); // PB for NBP call
}
else // Port open, location name not registered.
{
portPtr->openPB = nil; // This is important
CompleteWithResult(openPB,noErr);
goto Done;
}
}
else // Port open without a location name.
{
portPtr->openPB = nil; // This is important
CompleteWithResult(openPB,noErr);
goto Done;
}
}
Done:
return PPCCommonPBExit(openPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCStart call.
----------------------------------------------------------------------------------------*/
OSErr ppcStart(PPCStartPBPtr startPB)
{
PPCGlobalParamsPtr ppcglobPtr;
OSErr result;
PPCPortEntryPtr portPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(startPB, &ppcglobPtr))
{
startPB->csCode = PPCStartCall; // save command code
if (!ValidPortName(startPB->portName))
{
CompleteWithResult(startPB,badPortNameErr);
}
else if (startPB->serviceType != ppcServiceRealTime)
{
CompleteWithResult(startPB,badServiceMethodErr);
}
else if ((portPtr = PortRefNumtoPtr(startPB->portRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(startPB,noPortErr); // <36>
}
else if (result = VerifyLocNameFormat(startPB->locationName))
{
CompleteWithResult(startPB,result);
}
else
BeginLocalOrRemote(ppcglobPtr,(PPCParamBlockPtr)startPB,portPtr);
}
return PPCCommonPBExit(startPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCInformCall.
----------------------------------------------------------------------------------------*/
OSErr ppcInform(PPCInformPBPtr informPB)
{
PPCGlobalParamsPtr ppcglobPtr;
PPCPortEntryPtr portPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(informPB, &ppcglobPtr))
{
informPB->csCode = PPCInformCall; // save command code
if ((portPtr = PortRefNumtoPtr(informPB->portRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(informPB,noPortErr);
}
#ifdef notDefined // <36>
else // <36>
if(portPtr->serviceType == StoreAndForward || portPtr->serviceType == Both) // <36>
{ // <36>
} // <36>
#endif // <36>
else // <36>
{ // <36>
SetPortInformQue(informPB, portPtr); // <36> Wait for somthing.
} // <36>
}
return PPCCommonPBExit(informPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCAccept call.
----------------------------------------------------------------------------------------*/
OSErr ppcAccept(PPCAcceptPBPtr acceptPB)
{
PPCGlobalParamsPtr ppcglobPtr;
CommonSessionParams *sessPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(acceptPB, &ppcglobPtr))
{
acceptPB->csCode = PPCAcceptCall; // save command code
if ((sessPtr = SessRefNumtoPtr(acceptPB->sessRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(acceptPB,noSessionErr);
}
else if (sessPtr->sessState != AwaitAcceptReq)
{
if (sessPtr->sessState == AwaitAbortComp)
CompleteWithResult(acceptPB,noSessionErr);
else
CompleteWithResult(acceptPB,badReqErr);
}
else if (sessPtr->sessUse == locUse)
{
AcceptLocalSession(acceptPB, sessPtr,ppcglobPtr);
}
else if (sessPtr->sessUse == netUse)
{
AcceptNetworkSession(acceptPB,(NetIPCParamsPtr)sessPtr);
}
else
{
CompleteWithResult(acceptPB,paramErr); // <36>
}
}
return PPCCommonPBExit(acceptPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCReject call.
----------------------------------------------------------------------------------------*/
OSErr ppcReject(PPCRejectPBPtr rejectPB)
{
PPCGlobalParamsPtr ppcglobPtr;
CommonSessionParams *sessPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(rejectPB, &ppcglobPtr))
{
rejectPB->csCode = PPCRejectCall; // save command code
if ((sessPtr = SessRefNumtoPtr(rejectPB->sessRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(rejectPB,noSessionErr);
}
else if (sessPtr->sessState != AwaitAcceptReq)
{
if (sessPtr->sessState == AwaitAbortComp)
CompleteWithResult(rejectPB,noSessionErr);
else
CompleteWithResult(rejectPB,badReqErr);
}
else if (sessPtr->sessUse == locUse)
{
RejectLocalSession(rejectPB, sessPtr, ppcglobPtr);
}
else if (sessPtr->sessUse == netUse)
{
RejectNetworkSession(rejectPB,(NetIPCParamsPtr)sessPtr);
}
else
{
CompleteWithResult(rejectPB,paramErr); // <36>
}
}
return PPCCommonPBExit(rejectPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCWrite call.
----------------------------------------------------------------------------------------*/
OSErr ppcWrite(PPCWritePBPtr writePB)
{
PPCGlobalParamsPtr ppcglobPtr;
CommonSessionParams *sessPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(writePB, &ppcglobPtr))
{
writePB->csCode = PPCWriteCall; // save command code
writePB->actualLength = 0;
if ((sessPtr = SessRefNumtoPtr(writePB->sessRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(writePB,noSessionErr); // <36>
}
else if (sessPtr->sessState != DataXferState)
{
if (sessPtr->sessState == AwaitAbortComp)
CompleteWithResult(writePB,noSessionErr);
else
CompleteWithResult(writePB,badReqErr);
}
else if (sessPtr->sessUse == locUse)
{
WriteLocalData( writePB, sessPtr, ppcglobPtr);
}
else if (sessPtr->sessUse == netUse)
{
WriteNetworkData(writePB,(NetIPCParamsPtr)sessPtr);
}
else // <36>
{ // <36>
CompleteWithResult(writePB,paramErr); // <36>
}
}
return PPCCommonPBExit(writePB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCRead call.
----------------------------------------------------------------------------------------*/
OSErr ppcRead(PPCReadPBPtr readPB)
{
PPCGlobalParamsPtr ppcglobPtr;
CommonSessionParams *sessPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(readPB, &ppcglobPtr))
{
readPB->csCode = PPCReadCall; // save command code
readPB->actualLength = 0;
if ((sessPtr = SessRefNumtoPtr(readPB->sessRefNum, ppcglobPtr)) == nil)
{
CompleteWithResult(readPB,noSessionErr); // <36>
}
else if (sessPtr->sessState != DataXferState)
{
if (sessPtr->sessState == AwaitAbortComp)
CompleteWithResult(readPB,noSessionErr);
else
CompleteWithResult(readPB,badReqErr);
}
else if (sessPtr->sessUse == locUse)
{
ReadLocalData( readPB, sessPtr, ppcglobPtr);
}
else if (sessPtr->sessUse == netUse)
{
ReadNetworkData( readPB,(NetIPCParamsPtr)sessPtr);
}
else
{
CompleteWithResult(readPB,paramErr);
}
}
return PPCCommonPBExit(readPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCEnd call.
----------------------------------------------------------------------------------------*/
OSErr ppcEnd(PPCEndPBPtr endPB)
{
PPCGlobalParamsPtr ppcglobPtr;
CommonSessionParams *sessPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(endPB, &ppcglobPtr))
{
endPB->csCode = PPCEndCall; // save command code
if (sessPtr = SessRefNumtoPtr(endPB->sessRefNum, ppcglobPtr))
{
if (sessPtr->sessState == DataXferState)
{
if (sessPtr->sessUse == locUse)
{
sessPtr = DeleteSessByRefNum(endPB->sessRefNum, ppcglobPtr);
EndLocalSession( endPB, sessPtr, ppcglobPtr);
}
else if (sessPtr->sessUse == netUse)
{
sessPtr = DeleteSessByRefNum(endPB->sessRefNum, ppcglobPtr);
EndNetworkSession(endPB,(NetIPCParamsPtr) sessPtr);
}
else
{
CompleteWithResult(endPB,noSessionErr);
}
}
else
{
CompleteWithResult(endPB,noSessionErr);
}
}
else
{
CompleteWithResult(endPB,noSessionErr);
}
}
return PPCCommonPBExit(endPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the PPCClose call.
----------------------------------------------------------------------------------------*/
OSErr ppcClose(PPCClosePBPtr closePB)
{
PPCGlobalParamsPtr ppcglobPtr;
PPCPortEntryPtr portPtr;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(closePB, &ppcglobPtr))
{
closePB->csCode = PPCCloseCall; // save command code
if (portPtr = DeletePortByRefNum(closePB->portRefNum, ppcglobPtr))
{
ClosePortTable(closePB, portPtr, ppcglobPtr);
}
else
{
CompleteWithResult(closePB,noPortErr);
}
}
return PPCCommonPBExit(closePB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
Main entry point to the IPCListPorts call.
----------------------------------------------------------------------------------------*/
OSErr ipcListPorts(IPCListPortsPBPtr listPB)
{
PPCGlobalParamsPtr ppcglobPtr;
OSErr result;
// do common entry code for parameter block based calls
if (PPCCommonPBEntry(listPB, &ppcglobPtr))
{
listPB->csCode = IPCListPortsCall; // save command code
if (!ValidPortName(listPB->portName))
{
CompleteWithResult(listPB,badPortNameErr); // <36>
}
else if (result = VerifyLocNameFormat(listPB->locationName))
{
CompleteWithResult(listPB,result);
}
else
BeginLocalOrRemote(ppcglobPtr,(PPCParamBlockPtr)listPB,NULL);
}
return PPCCommonPBExit(listPB, ppcglobPtr);
}
/*----------------------------------------------------------------------------------------
PPCCommonPBEntry is called at the beginning of all parameter block based calls. It returns true
if PPC can even deal with PB calls right now. We make sure we have globals, and that we are
initialized first. We then prepare ourself to process the request.
WARNING: This routine has strange calling conventions. It depends upon register D1 having the
the PPCToolBox trap word in register D1. C
----------------------------------------------------------------------------------------*/
STATIC Boolean PPCCommonPBEntry(void *PB, PPCGlobalParamsPtr *ppcglobPtrPtr)
PPCParamBlockPtr PB;
{
PPCGlobalParamsPtr ppcglobPtr;
PBWriteResPtr res; // <36>
unsigned short PPCTrap;
PPCTrap = GetD1();
#ifdef DEBUG
if(PPCTrap != 0xA0DD && PPCTrap != 0xA4DD)
DebugStr("\pRegister D1 did not have our trap word");
#endif
if(*ppcglobPtrPtr = ppcglobPtr = getGlobal()) // get globals
{
// save application's A5
res = (PBWriteResPtr)(PB->startParam.Reserved); // <36>
res->ApplA5 = GetA5(); // <36>
res->cmdMode = PPCTrap & 0x0400?true:false; // <36>
if (!ppcglobPtr->inited)
{
CompleteWithResult(PB,notInitErr);
return(false);
}
// mark PB as busy
PB->startParam.ioResult = 1;
// increment nesting level
++ppcglobPtr->inEntry;
// replenish resources if call made synchronously
if(!res->cmdMode) // <36>
Replenish(ppcglobPtr);
return(true); // We are prepared to process this request.
}
else // No Globals, return false and let PPCCommonPBExit handle it.
{
return false;
}
}
/*----------------------------------------------------------------------------------------
PPCCommonPBExit is called at the end of all parameter block based calls. Note if
PPCCommonPBEntry returned false because we don't have globals, we will no this here
since the ppcglobPtr will be NULL. So we have to complete the request differently in
this because CompleteWithResult depends upon globals being present.
----------------------------------------------------------------------------------------*/
STATIC OSErr PPCCommonPBExit(void *PB, PPCGlobalParamsPtr ppcglobPtr)
PPCParamBlockPtr PB;
{
short result = PB->startParam.ioResult;
if(ppcglobPtr) // Should always be no zero, but one never knows!
{
if(ppcglobPtr->inEntry == 1) // If at outermost Entry in stack frame
{
PPCParamBlockPtr tempPB; // complete all pending calls.
do
{
short p;
p = spl(kNoInterrupts); // Extremely Critical Code.
if(!ppcglobPtr->CompletedPBQueue.qSize) // if the queue is empty
{
--ppcglobPtr->inEntry; // We will allow direct call of comp routines.
spl(p); // restore the interrupt level.
break; // Done with this loop.
}
else // Somthing is in the queue!
{
spl(p); // Restore interrupts to the way they were.
tempPB = ServeQueue(&ppcglobPtr->CompletedPBQueue); // Get user PB.
CallCompletionRoutine(tempPB,tempPB->startParam.ioResult); // Call comp routine
}
}
while(true); // Repeat until the queue is empty.
if (!((PBWriteResPtr)(PB->startParam.Reserved))->cmdMode) // <36> if Synchronous
{
while (PB->startParam.ioResult == 1); // Wait for the call to complete.
return PB->startParam.ioResult;
}
}
else // Not at top level.
--ppcglobPtr->inEntry; // Decrease our level indicator.
// if call still processing, return noErr, else return result
return(result == 1 ? noErr : result);
}
else
{
CallCompletionRoutine(PB,noGlobalsErr);
return(noGlobalsErr);
}
}
STATIC void NetOpenCompletion(void)
{
PPCPortEntryPtr portPtr;
PortLocationTablePtr locInfo;
PPCOpenPBPtr openPB;
locInfo = GetA0();
portPtr = locInfo->portPtr;
openPB = (PPCOpenPBPtr)(portPtr->openPB); /* get back the openPB */
if (locInfo->nbpPB.ioResult == noErr)
portPtr->nbpRegistered = openPB->nbpRegistered = true; // we did register with nbp
portPtr->openPB = nil; // This is important
CompleteWithResult(openPB,noErr);
} // NetNBPCompletion
STATIC void CallCompletionRoutine(PPCParamBlockPtr PB,OSErr ioResult)
{
PPCReservedPtr res = (PPCReservedPtr)(&(PB->startParam.Reserved[0]));
if (res->cmdMode) // if Asynchronous
{
callCompletion(PB, ioResult); // Save AppA5 and call completion
}
}
/*----------------------------------------------------------------------------------------
CompleteWithResult prepares and completes the usage of the client's parameter block
with the specified result code. If we are not inEntry, then the call is complete
immediatly, otherwise it is place on the CompletedPBQueue to be served later when the
stack unwinds within PPCCommonPBExit.
----------------------------------------------------------------------------------------*/
OSErr CompleteWithResult(void *PB,OSErr Result)
PPCParamBlockPtr PB;
{
PPCGlobalParamsPtr ppcglobPtr;
PB->closeParam.ioResult = Result;
ppcglobPtr = getGlobal();
if(ppcglobPtr->inEntry)
{
EnQueue(PB,&ppcglobPtr->CompletedPBQueue);
}
else
CallCompletionRoutine(PB,Result);
return(Result); // For callers convience!
}
/*----------------------------------------------------------------------------------------
VerifyLocNameFormat is used to verify that a location name can be used to start a
session. It just checks the structure.
----------------------------------------------------------------------------------------*/
OSErr VerifyLocNameFormat(LocationNamePtr locName)
{
if(locName)
{
if (locName->locationKindSelector == ppcNoLocation)
return noErr; // NoLocation implies local.
if (locName->locationKindSelector != ppcNBPLocation)
return nameTypeErr; // we don't understand any other type
if (locName->u.nbpEntity.objStr[0] > 32 || locName->u.nbpEntity.typeStr[0] > 32 ||
locName->u.nbpEntity.zoneStr[0] > 32)
return badLocNameErr;
// NOTE: little known AppleTalk fact, a zero length zone string indicates this zone.
// That is why I won't check for minimum length on the zone string here.
if (locName->u.nbpEntity.objStr[0] == 0 || locName->u.nbpEntity.typeStr[0] == 0)
return badLocNameErr;
}
return(noErr);
}
/*----------------------------------------------------------------------------------------
LocationNameLocal Determines if the given location name exists on this machine.
----------------------------------------------------------------------------------------*/
Boolean LocationNameLocal(LocationNamePtr locName)
{
PortLocationTablePtr locInfo;
PPCGlobalParamsPtr ppcglobPtr;
PPCPortEntryPtr portPtr; // <36>
if(!locName)
return(true);
if (locName->locationKindSelector == ppcNoLocation)
return(true);
ppcglobPtr = getGlobal();
if(locName->u.nbpEntity.zoneStr[0] == 0 ||
(locName->u.nbpEntity.zoneStr[0] == 1 && locName->u.nbpEntity.zoneStr[1] == '*') ||
EqualString(locName->u.nbpEntity.zoneStr,ppcglobPtr->zoneName,false,true))
{
// At this point the zone is our zone, so we will check the object.
if(EqualString(locName->u.nbpEntity.objStr,ppcglobPtr->machineName,false,true))
{
if(EqualString(locName->u.nbpEntity.typeStr, ppcglobPtr->configData.ppctoolboxName,false,true))
return(true);
else
{
short sr;
sr = spl(kNoInterrupts); // Make sure we don't have any problems.
FOREACHELEMENT(portPtr,&ppcglobPtr->OpenPortQueue)
{
if (locInfo = portPtr->locationInfo)
{
if (EqualString(locName->u.nbpEntity.typeStr, locInfo->typeStr,false,true))
{
spl(sr);
return(true); // Name is locally registered already
}
}
}
spl(sr);
}
}
}
NotLocal:
return(false);
}
/*----------------------------------------------------------------------------------------
LocNameTaken determines if the typeStr is currently in use in this machine for some
port.
----------------------------------------------------------------------------------------*/
STATIC Boolean LocNameTaken(LocationNamePtr locationName,PPCGlobalParamsPtr ppcglobPtr)
{
short sr;
Boolean isTaken;
PPCPortEntryPtr portPtr; // <36>
isTaken = false;
sr = spl(kNoInterrupts);
FOREACHELEMENT(portPtr,&ppcglobPtr->OpenPortQueue)
{
if(portPtr->locationInfo)
{
if(EqualString(locationName->u.nbpType,
portPtr->locationInfo->typeStr,
false,true)) /* case insensitive, diacritical sensitive */
{
isTaken = true;
break;
}
}
}
spl(sr);
return(isTaken);
}
/*----------------------------------------------------------------------------------------
BeginLocalOrRemote begins a local or remote request for IPCListPorts or PPCStart. It has a
side effect of updating our global down-below with our current zone name, keeping it fresh. NOTE
there exists an interesting, but harmless race condition, worst case we perform a GetMyZone call
and when it completes have nothing to processes, casue it was already taken care of.
----------------------------------------------------------------------------------------*/
STATIC void BeginLocalOrRemote(PPCGlobalParamsPtr ppcglobPtr,PPCParamBlockPtr PB,void *portPtr)
{
short sr;
PB->startParam.intUsePtr = portPtr; // Remember this for later in case of PPCStart.
EnQueue(PB,&ppcglobPtr->BeginLRQueue);
sr = spl(kNoInterrupts);
if(ppcglobPtr->BeginLRQueue.qSize == 1) // Not currently performing a GetMyZone.
{
spl(sr);
DoGetMyZone(&ppcglobPtr->xpb, // Use this parameter block
true, // do this asyncrhonously
(ProcPtr)LocalOrNot, // Completion Routine.
&ppcglobPtr->zoneName); // here is where to put the zone name.
}
else
spl(sr);
}
/*----------------------------------------------------------------------------------------
LocalOrNot is chained from BeginLocalOrRemote. It processes the list pending IPCListPorts
and PPCStart requests by branching to the appropriate routine, or completing the request with
an error if we don't support remote request.
----------------------------------------------------------------------------------------*/
STATIC void LocalOrNot(void)
{
PPCGlobalParamsPtr ppcglobPtr;
Boolean Local;
PPCParamBlockPtr PB;
ppcglobPtr = getGlobal();
if(ppcglobPtr->xpb.ioResult)
BlockMove("\p*",ppcglobPtr->zoneName,2);
while(PB = ServeQueue(&ppcglobPtr->BeginLRQueue)) // Batch process the requests.
{
Local = LocationNameLocal(PB->startParam.locationName);
if (!Local && !ppcglobPtr->canRemote) // If its remote, and we can't, then
{
CompleteWithResult(PB,localOnlyErr);
continue;
}
if(PB->startParam.csCode == PPCStartCall)
{
if(Local)
StartLocalSession((PPCStartPBPtr)PB,(PPCPortEntryPtr)PB->startParam.intUsePtr, ppcglobPtr);
else
StartNetworkSession((PPCStartPBPtr)PB,(PPCPortEntryPtr)PB->startParam.intUsePtr, ppcglobPtr);
}
else // Must be an IPCListPorts request
{
if(Local)
ListLocalPorts((IPCListPortsPBPtr)PB, ppcglobPtr);
else
ListNetworkPorts((IPCListPortsPBPtr)PB, ppcglobPtr);
}
}
}
/*----------------------------------------------------------------------------------------
DoGetMyZone performs the task of a GetMyZone call, its just a nice interface to perform such
a boring task.
----------------------------------------------------------------------------------------*/
STATIC void DoGetMyZone(XCallParam *xpb,
Boolean async,
ProcPtr compRtn,
Str32 zoneName)
{
OSErr result;
xpb->ioCompletion = compRtn;
xpb->zipBuffPtr = (Ptr)zoneName;
xpb->zipInfoField[0] = 0;
xpb->zipInfoField[1] = 0;
xpb->xppTimeout = 1;
xpb->xppRetry = 3;
if (getGlobal()->mppOpen)
{
#ifdef JimFixedTheGlue
result = DMFix(GetMyZone((XPPParmBlkPtr)xpb, async),xpb);
#else
xpb->csCode = xCall;
xpb->xppSubCode = zipGetMyZone;
xpb->ioRefNum = xppRefNum;
result = DMFix(PBControl((ParmBlkPtr)xpb, async),xpb);
#endif
}
else // pretend we are .XPP for a moment.
{
BlockMove("\p*",zoneName,2);
xpb->ioResult = noErr;
FakeCompletion(xpb);
}
}
/*----------------------------------------------------------------------------------------
DMFix checks to see if the error code in a parameter block was returned
by the Device Manager. The Device Manger fails to call the completion routine specified in
the parameter block. So I will check for the known cases when this happens, and if its one of
them, call the completion routine as if I were the device manager doing its job properly.
----------------------------------------------------------------------------------------*/
OSErr DMFix(OSErr Result,void *thePB)
MPPparms *thePB;
{
if(Result == notOpenErr || Result == badUnitErr)
{
if(thePB->ioCompletion) // Assume if completion routine specified, call is async.
{
FakeCompletion(thePB); // Calls the completion routine with Device Manager calling conventions.
}
}
return(Result);
}