Alan.Michelson@f141.n102.z1.FIDONET.ORG (Alan Michelson) (03/19/90)
A Sublaunch from C To sublaunch from MPW C, we need to have a small assembly language routine that calls _Launch, since MPW C currently will not allow either inline assembly or multiple word extern declarations: ; OSErr Launchit(pLaunch) ; pLaunchStruct pLaunch; ; extern; INCLUDE 'traps.a' CASE ON ; so C can C Launchit Launchit PROC EXPORT MOVE.L 4(SP),A0 ; get pointer to parameter block _Launch ; call launch ; note that now we can return from _Launch (under MultiFinder) so ; we'd better be prepared to continue. ; we've returned from Launch, we now have the return address on the ; stack, but first we need to clean up the address of our parameter MOVE.L (SP)+,A0 ; get the return address in A0 ADDQ #4,SP ; get rid of the paramter JMP (A0) ; we need to be prepared to come back ; from a launch ENDP END Now heres the MPW C source: typedef struct LaunchStruct { char *pfName; /* pointer to the name of launchee */ short int param; char LC[2]; /*extended parameters:*/ long int extBlockLen;/*number of bytes in extension == 6*/ short int fFlags; /*Finder file info flags (see below)*/ long int launchFlags; /*bit 31,30==1 for sublaunch, others reserved*/ } *pLaunchStruct; extern OSErr Launchit(); OSErr DoLaunch() { /* DoLaunch */ struct LaunchStruct myLaunch; Point wher; /*where to display dialog*/ SFReply reply; /*reply record*/ SFTypeList myFileTypes;/* we only want APPLs */ short int numFileTypes=1; HFileInfo myPB; char *dirNameStr; OSErr err; wher.h = 80; wher.v = 90; myFileTypes[0] = 'APPL'; /* we only want APPLs */ /*Let the user choose the file to Launch*/ SFGetFile(wher, "", nil, numFileTypes, myFileTypes, nil, &reply); if (reply.good) { dirNameStr = &reply.fName; /*initialize to file selected*/ /*Get the Finder flags*/ myPB.ioNamePtr= dirNameStr; myPB.ioVRefNum= reply.vRefNum; myPB.ioFDirIndex= 0; myPB.ioDirID = 0; err = PBGetCatInfo(&myPB,false); if (err != noErr) return err; /*Set the current volume to where the target application is*/ err = SetVol(nil, reply.vRefNum); if (err != noErr) return err; /*Set up the launch parameters*/ myLaunch.pfName = &reply.fName; /*pointer to our fileName*/ myLaunch.param = 0; /*we dont want alternate screen or sound buffers*/ /*set up LC so as to tell Launch that there is non-junk next*/ myLaunch.LC[0] = 'L'; myLaunch.LC[1] = 'C'; myLaunch.extBlockLen = 6; /*length of param. block past this long word*/ /*copy flags; set bit 6 of low byte to 1 for RO access:*/ myLaunch.fFlags = myPB.ioFlFndrInfo.fdFlags; /*from GetCatInfo*/ myLaunch.launchFlags = 0xC0000000; /*set BOTH hi bits for a sublaunch*/ err = Launchit(&myLaunch); /* do the sublaunch */ if (err < 0) { /* the launch failed, so put up an alert to inform the user */ DoLaunchFailed(); return err; } else return noErr; } /*if reply.good*/ } /*DoLaunch*/ Working directories Putting aside the compatibility issue for the moment, the only problem this creates under the current system is one of Working Directory Control Blocks, or WDCBs. Unless the application you are launching is at the root or on an MFS volume, a new WDCB must be created so that it may be set as the current directory when the program is run. In the example procedure above, the new working directory is opened (allocated) by Standard File and its WDRefNum is returned in reply.vRefNum. If you werent using Standard File and couldnt assume, for instance, that the application was in the blessed folder or root then you would have to open a new working directory explicitly via OpenWD. The new WDCB should have a WDProcID of 'ERIK' so the Finder or another shell which saw that the WDCB had been allocated by a"sublaunchee would know to de-allocate it. The sublaunching process is recursive; you may sublaunch a program which then sublaunches another, and so on, and when each application exits it may return to the one that called it. The problem is that there is a limit to the number of WDCBs that can be created; currently (and probably forever) the limit is 40. You can see how quickly these might be used up if many programs were playing the shell game or neglecting to de-allocate WDCBs they had created. Make sure that you check for all errors after calling PBOpenWD. A tMWDOErr (121) means that all available WDCBs have been allocated. -- Alan Michelson via cmhGate - Net 226 fido<=>uucp gateway Col, OH UUCP: ...!osu-cis!n8emr!cmhgate!102!141!Alan.Michelson INET: Alan.Michelson@f141.n102.z1.FIDONET.ORG