appletprocess.c

Go to the documentation of this file.
00001 
00002 /*  $Id: appletprocess.c 355 2005-01-11 22:48:55Z andreradke $    */
00003 
00004 /* copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
00005 
00006 
00007 #include <Aliases.h>
00008 #include <GestaltEqu.h>
00009 #include <Folders.h>
00010 
00011 #include <iac.h>
00012 
00013 #ifndef macBirdRuntime /*it has no app.xxx record*/
00014     
00015     #include "applet.h"
00016 
00017 #else
00018 
00019     #include "appletdefs.h"
00020     #include "appletstrings.h"
00021     #include "appletmemory.h"
00022     #include "appletsyserror.h"
00023     
00024     extern void alertdialog (bigstring);
00025     
00026 #endif
00027 
00028 #include "appletprocess.h"
00029 #include "appletsyserror.h"
00030 #include "appletfolder.h"
00031 
00032 
00033 
00034 typedef AppParameters **AppParametersHandle;
00035 
00036 #define kAEFinderEvents 'FNDR'
00037 #define kAEFinderID 'MACS'
00038 #define kAEShowClipboard 'shcl'
00039 #define kAEPutAway 'sput'
00040 #define keyAEFinderSelection 'fsel'
00041 #define kAEDrag 'drag'
00042 #define keyAEFinderMisc 'fmsc'
00043 #define kAEEmptyTrash 'empt'
00044 #define kAEOpenSelection 'sope'
00045 #define kAEPrintSelection 'spri'
00046 
00047 
00048 static struct {
00049 
00050     boolean launched;
00051 
00052     OSType apptype;
00053 
00054     bigstring errormessage;
00055     } helperappinfo;
00056 
00057 
00058 
00059 boolean processloop (typrocessloopcallback callback, long refcon) {
00060     
00061     ProcessInfoRec sysinfo;
00062     typrocessinfo ourinfo;
00063     ProcessSerialNumber psn;
00064     
00065     sysinfo.processInfoLength = sizeof (sysinfo);
00066     
00067     sysinfo.processName = (StringPtr) ourinfo.name; /*place to store process name*/
00068     
00069     sysinfo.processAppSpec = &ourinfo.file; /*place to store process filespec*/
00070     
00071     psn.highLongOfPSN = kNoProcess;
00072     
00073     psn.lowLongOfPSN = kNoProcess;
00074     
00075     while (GetNextProcess (&psn) == noErr) {
00076         
00077         clearbytes (&ourinfo, longsizeof (ourinfo));
00078         
00079         sysinfo.processInfoLength = sizeof (sysinfo);
00080         
00081         if (GetProcessInformation (&psn, &sysinfo) != noErr)
00082             continue; /*keep going -- ignore error*/
00083                 
00084         ourinfo.serialnumber = sysinfo.processNumber;
00085         
00086         ourinfo.launcherserialnumber = sysinfo.processLauncher;
00087         
00088         ourinfo.filetype = sysinfo.processType;
00089         
00090         ourinfo.filecreator = sysinfo.processSignature;
00091         
00092         ourinfo.sizerecourceflags = sysinfo.processMode;
00093         
00094         ourinfo.partition = sysinfo.processLocation;
00095         
00096         ourinfo.partitionsize = sysinfo.processSize;
00097         
00098         ourinfo.freebytesinheap = sysinfo.processFreeMem;
00099         
00100         ourinfo.launchticks = sysinfo.processLaunchDate;
00101         
00102         ourinfo.activeticks = sysinfo.processActiveTime;
00103         
00104         if (!(*callback) (&ourinfo, refcon))
00105             return (false);
00106         } /*while*/
00107         
00108     return (true); /*loop terminated, none of the visit routines returned false*/
00109     } /*processloop*/
00110     
00111 
00112 static boolean findrunningappvisit (typrocessinfo *visitinfo, long refcon) {
00113     
00114     typrocessinfo *lookforinfo = (typrocessinfo *) refcon;
00115     
00116     if ((*visitinfo).filecreator == (*lookforinfo).filecreator) {
00117         
00118         moveleft (visitinfo, lookforinfo, longsizeof (typrocessinfo));
00119 
00120         return (false);
00121         }
00122         
00123     return (true);
00124     } /*findrunningappvisit*/
00125     
00126 
00127 boolean findrunningapp (OSType id, typrocessinfo *info) {
00128     
00129     clearbytes (info, longsizeof (typrocessinfo));
00130     
00131     (*info).filecreator = id; /*this is the one we're looking for*/
00132     
00133     return (!processloop (&findrunningappvisit, (long) info));
00134     } /*findrunningapp*/
00135     
00136 
00137 boolean bringapptofront (OSType id) {
00138 
00139     typrocessinfo info;
00140     
00141     if (!findrunningapp (id, &info))
00142         return (false);
00143     
00144     WakeUpProcess (&info.serialnumber);
00145     
00146     SetFrontProcess (&info.serialnumber);
00147     
00148     return (true); 
00149     } /*bringapptofront*/
00150     
00151     
00152 static OSErr buildlaunchparamlist (FSSpec *fsdoc, AppParametersHandle *appparams) {
00153     
00154     AEDesc addrdesc;
00155     AEDesc launchdesc;
00156     AEDescList doclist;
00157     AppleEvent event;
00158     OSErr ec;
00159     AliasHandle halias;
00160     AEDesc docdesc;
00161     
00162     if (!testheapspace (0x0200)) /*512 bytes should be plenty to avoid lots of error checking*/
00163         return (memFullErr);
00164     
00165     ec = NewAliasMinimal (fsdoc, &halias);
00166     
00167     if (ec != noErr)
00168         return (ec);
00169     
00170     addrdesc.descriptorType = typeNull;
00171     
00172     addrdesc.dataHandle = nil;
00173     
00174     AECreateAppleEvent (kCoreEventClass, kAEOpenDocuments, &addrdesc, kAutoGenerateReturnID, kAnyTransactionID, &event);
00175     
00176     AECreateList (nil, 0, false, &doclist); /*create list for the fsspec*/
00177     
00178     docdesc.descriptorType = typeAlias;
00179     
00180     docdesc.dataHandle = (Handle) halias;
00181     
00182     AEPutDesc (&doclist, 0, &docdesc); /*put alias on the list*/
00183     
00184     AEDisposeDesc (&docdesc);
00185     
00186     AEPutParamDesc (&event, keyDirectObject, &doclist); /*put list on the event*/
00187     
00188     AEDisposeDesc (&doclist); /*dispose list*/
00189     
00190     ec = AECoerceDesc (&event, typeAppParameters, &launchdesc); /*this is what Launch wants*/
00191     
00192     AEDisposeDesc (&event); /*we're done with it*/
00193     
00194     if (ec != noErr) /*shouldn't fail, but...*/
00195         return (ec);
00196     
00197     *appparams = (AppParametersHandle) launchdesc.dataHandle;
00198     
00199     return (noErr);
00200     } /*buildlaunchparamlist*/
00201 
00202 
00203 boolean launchappwithdoc (FSSpec *fsapp, FSSpec *fsdoc, boolean flbringtofront) {
00204     
00205     LaunchParamBlockRec pb;
00206     AppParametersHandle docparams = nil;
00207     OSErr ec;
00208     
00209     clearbytes (&pb, longsizeof (pb));
00210     
00211     pb.launchAppSpec = fsapp;
00212     
00213     pb.launchBlockID = extendedBlock;
00214     
00215     pb.launchEPBLength = extendedBlockLen;
00216     
00217     pb.launchControlFlags = launchContinue | launchNoFileFlags;
00218     
00219     if (!flbringtofront)
00220         pb.launchControlFlags = pb.launchControlFlags | launchDontSwitch;
00221     
00222     if (fsdoc != nil) { /*set up docparam with launch event*/
00223         
00224         ec = buildlaunchparamlist (fsdoc, &docparams);
00225         
00226         if (ec != noErr)
00227             return (false);
00228         
00229         lockhandle ((Handle) docparams);
00230         
00231         pb.launchAppParameters = *docparams;
00232         }
00233     
00234     ec = LaunchApplication (&pb);
00235     
00236     disposehandle ((Handle) docparams); /*checks for nil*/
00237     
00238     if (ec != noErr)
00239         return (false);
00240     
00241     /*wait for a few events, per DMB's advice*/ {
00242     
00243         short i;
00244         EventRecord ev;
00245         
00246         for (i = 1; i <= 5; i++)
00247             EventAvail (everyEvent, &ev);
00248         }
00249     
00250     return (true);
00251     } /*launchappwithdoc*/
00252 
00253 
00254 static boolean pushaliaslist (FSSpec *fsdoc, OSType listkey, AppleEvent *event) {
00255     
00256     AEDescList doclist;
00257     OSErr ec;
00258     AliasHandle halias;
00259     AEDesc docdesc;
00260     
00261     ec = NewAliasMinimal (fsdoc, &halias);
00262     
00263     if (ec != noErr)
00264         return (false);
00265     
00266     ec = AECreateList (nil, 0, false, &doclist); /*create list for the fsspec*/
00267     
00268     if (ec != noErr)
00269         return (false);
00270         
00271     docdesc.descriptorType = typeAlias;
00272     
00273     docdesc.dataHandle = (Handle) halias;
00274     
00275     ec = AEPutDesc (&doclist, 0, &docdesc); /*put alias on the list*/
00276     
00277     if (ec != noErr)
00278         return (false);
00279         
00280     AEDisposeDesc (&docdesc);
00281     
00282     AEPutParamDesc (event, listkey, &doclist); /*put list on the event*/
00283     
00284     AEDisposeDesc (&doclist); /*dispose list*/
00285     
00286     return (true);
00287     } /*pushaliaslist*/
00288 
00289 
00290 static boolean oldsendodoc (OSType appid, FSSpec *fsdoc) { 
00291 
00292     AppleEvent event, reply;
00293     boolean fl = false;
00294     
00295     if (!IACnewverb (appid, kCoreEventClass, kAEOpenDocuments, &event))
00296         return (false);
00297     
00298     if (!pushaliaslist (fsdoc, keyDirectObject, &event))
00299         goto exit;
00300     
00301     fl = IACsendverb (&event, &reply);
00302     
00303     AEDisposeDesc (&reply);
00304     
00305     exit:
00306     
00307     AEDisposeDesc (&event); 
00308     
00309     return (fl);
00310     } /*oldsendodoc*/
00311     
00312 
00313 boolean sendodoc (OSType appid, FSSpec *fsdoc) {
00314     
00315     typrocessinfo info;
00316     AEAddressDesc adr; 
00317     OSErr ec;
00318     AppleEvent event, reply;
00319     boolean fl = false;
00320     
00321     if (!findrunningapp (appid, &info))
00322         return (false);
00323         
00324     AECreateDesc (typeProcessSerialNumber, (Ptr) &info.serialnumber, sizeof (info.serialnumber), &adr);
00325     
00326     ec = AECreateAppleEvent (kCoreEventClass, kAEOpenDocuments, &adr, kAutoGenerateReturnID, kAnyTransactionID, &event);
00327     
00328     AEDisposeDesc (&adr);
00329     
00330     if (ec != noErr)
00331         return (false);
00332     
00333     if (!pushaliaslist (fsdoc, keyDirectObject, &event))
00334         goto exit;
00335     
00336     fl = IACsendverb (&event, &reply);
00337     
00338     AEDisposeDesc (&reply);
00339     
00340     exit:
00341     
00342     AEDisposeDesc (&event); 
00343     
00344     return (fl);
00345     } /*sendodoc*/
00346     
00347 
00348 static boolean xxxfinderevent (OSType idverb, FSSpec *fsdoc) {
00349 
00350     AppleEvent event, reply;
00351     boolean fl = false;
00352     OSErr ec;
00353     
00354     if (!IACnewverb ('MACS', 'FNDR', idverb, &event))
00355         return (false);
00356     
00357     if (!pushaliaslist (fsdoc, 'fsel', &event)) {
00358         
00359         AEDisposeDesc (&event);
00360         
00361         return (false);
00362         }
00363     
00364     ec = AESend (
00365         &event, &reply, kAENoReply + kAENeverInteract, 
00366         
00367         kAENormalPriority, kAEDefaultTimeout, nil, nil);
00368     
00369     AEDisposeDesc (&event); 
00370     
00371     return (ec == noErr);
00372     } /*finderevent*/
00373     
00374     
00375 static boolean finderevent (OSType idverb, FSSpec *fsdoc) {
00376     
00377     /*
00378     this is crufty code donated by Jorg, stolen from Frontier.
00379     
00380     really needs to be cleaned out, I think. DW 7/19/93.
00381     */
00382     
00383     static EventRecord er;
00384     short err;
00385     AliasHandle a1 = 0, a2 = 0;
00386     long hs1, hs2;
00387     FSSpec fs1, fs2 = *fsdoc;
00388     Handle message;
00389     CInfoPBRec  pb;
00390     long version;
00391     
00392     /* get some catalog information, which we will use later. */
00393     pb.dirInfo.ioCompletion=0;
00394     pb.dirInfo.ioNamePtr = fs2.name;
00395     pb.dirInfo.ioVRefNum = fs2.vRefNum;
00396     pb.dirInfo.ioFDirIndex = 0;
00397     pb.dirInfo.ioDrDirID = fs2.parID;
00398     
00399     err = PBGetCatInfoSync(&pb);
00400     
00401     if (err != noErr)
00402         goto exit;
00403     
00404     err = NewAliasMinimal(&fs2, &a2);
00405     
00406     if (err != noErr)
00407         goto exit;
00408     
00409     fs1 = fs2;
00410     
00411     if (Gestalt (gestaltAUXVersion, &version)) { /*running under A/UX; cover bugs*/
00412         
00413         if (fs1.parID == 1) { /*it's a volume*/
00414             
00415             fs1.vRefNum = -1; /*a/ux wants to see the root as the parent*/
00416             }
00417         else { /*not a volume: path parsing works better under a/ux*/
00418             
00419             /*
00420             bigstring path;
00421             
00422             if (!filespectopath (fs1, path))
00423                 return (false);
00424             
00425             folderfrompath (path, path);
00426             
00427             if (!pathtofilespec (path, &fs1))
00428                 return (false);
00429             
00430             goto gotfs1;
00431             */
00432             }
00433         }
00434     else {
00435         
00436         if (fs1.parID == 1) { /*it's a volume*/
00437             
00438             err = FindFolder(fs1.vRefNum, kDesktopFolderType, FALSE, &fs1.vRefNum, &fs1.parID);
00439             
00440             if (err != noErr)
00441                 goto exit;
00442             }
00443         }
00444     
00445     err = FSMakeFSSpec(fs1.vRefNum, fs1.parID, "\p", &fs1);
00446     
00447     if (err != noErr)
00448         goto exit;
00449     
00450     gotfs1:
00451     
00452     err = NewAliasMinimal(&fs1, &a1);
00453     
00454     if (err != noErr)
00455         goto exit;
00456     
00457     hs1 = GetHandleSize((Handle) a1);
00458     hs2 = GetHandleSize((Handle) a2);
00459     
00460     MoveHHi((Handle) a1); HLock((Handle) a1);
00461     MoveHHi((Handle) a2); HLock((Handle) a2);
00462     
00463     er.what = kHighLevelEvent;              /* PHLE fills this in, but we do it just to be clear. */
00464     er.message = kAEFinderEvents;           /* this is the event class */
00465     *(long *)&er.where = idverb;            /* this is the event type - see Card 131 */
00466     er.when = TickCount();                  /* this also gets filled in, but... */
00467     er.modifiers = 0;                       /* doesn't matter */
00468     
00469     message = appnewhandle (24 + hs1 + 28 + hs2);
00470     
00471     /*
00472     normally you'd use Apple Events manager calls to pack up a message and
00473     send it.  I do things this way only because I can't be sure the frontmost
00474     app has initialized that manager.
00475     */
00476     
00477     if (message) {
00478         register long *filler = (void *)*message;
00479         
00480         *filler++ = 'aevt';
00481         *filler++ = 0x00010001;
00482         *filler++ = ';;;;';
00483         *filler++ = '----';
00484         *filler++ = 'alis';
00485         *filler++ = hs1;
00486         BlockMove(*a1, filler, hs1); filler = (long *)(hs1 + (long) filler);
00487         *filler++ = 'fsel';
00488         *filler++ = 'list';
00489         *filler++ = hs2 + 16;
00490         *filler++ = 1;
00491         *filler++ = 0;
00492         *filler++ = 'alis';
00493         *filler++ = hs2;
00494         BlockMove(*a2, filler, hs2);
00495         };
00496     
00497     DisposHandle((Handle) a1);
00498     DisposHandle((Handle) a2);
00499     
00500     if (!message) {
00501         
00502         err = memFullErr;
00503         
00504         goto exit;
00505         }
00506     
00507     HLock(message);
00508     
00509     err = PostHighLevelEvent (&er, (long) kAEFinderID, 237, *message, GetHandleSize (message), receiverIDisSignature);
00510     
00511     if ((pb.dirInfo.ioFlAttrib & ioDirMask) || (pb.hFileInfo.ioFlFndrInfo.fdType == 'cdev')) 
00512         bringapptofront (kAEFinderID);
00513     
00514     DisposHandle(message);
00515     
00516     exit:
00517     
00518     return (err == noErr);
00519     } /*finderevent*/
00520     
00521 
00522 boolean launchusingfinder (FSSpec *fs) {
00523     
00524     return (finderevent (kAEOpenSelection, fs));
00525     } /*launchusingfinder*/
00526     
00527     
00528 boolean revealinfinder (FSSpec *fs) {
00529 
00530     return (finderevent ('srev', fs));
00531     } /*revealinfinder*/
00532     
00533     
00534 static boolean apprunningflag;
00535 
00536 
00537 static boolean fileisrunningvisit (typrocessinfo *info, long refcon) {
00538     
00539     FSSpec *fs = (FSSpec *) refcon;
00540     
00541     if (equalfilespecs (&(*info).file, fs)) {
00542         
00543         apprunningflag = true;
00544         
00545         return (false);
00546         }
00547     
00548     return (true);
00549     } /*fileisrunningvisit*/
00550     
00551     
00552 boolean fileisrunning (FSSpec *fs) {
00553     
00554     apprunningflag = false;
00555     
00556     processloop (&fileisrunningvisit, (long) fs);
00557     
00558     return (apprunningflag);
00559     } /*fileisrunning*/
00560     
00561 
00562 boolean equalprocesses (typrocessinfo *rec1, typrocessinfo *rec2) {
00563     
00564     Boolean flsameprocess;
00565     
00566     SameProcess (&(*rec1).serialnumber, &(*rec2).serialnumber, &flsameprocess);
00567     
00568     return (flsameprocess);
00569     } /*equalprocesses*/
00570     
00571 
00572 boolean quitapplication (OSType idapp) {
00573     
00574     AppleEvent event, reply;
00575     boolean fl;
00576     
00577     if (!IACnewverb (idapp, kCoreEventClass, kAEQuitApplication, &event))
00578         return (false);
00579     
00580     fl = IACsendverb (&event, &reply);
00581     
00582     AEDisposeDesc (&reply);
00583     
00584     AEDisposeDesc (&event); 
00585     
00586     return (fl);
00587     } /*quitapplication*/
00588     
00589     
00590 boolean launchdeskaccessoryfile (FSSpec *fs) {
00591     
00592     OSErr ec;
00593     
00594     ec = LaunchDeskAccessory (fs, nil);
00595     
00596     return (!syserror (ec));
00597     } /*launchdeskaccessoryfile*/
00598     
00599 
00600 static boolean helpercallback (bigstring fname, tyfileinfo *info, long pxinfo) {
00601     
00602     #pragma unused (pxinfo)
00603     
00604     tyfilespec fs;
00605     
00606     filemakespec ((*info).vnum, (*info).dirid, fname, &fs);
00607     
00608     if ((*info).filetype != 'APPL') /*keep looking*/
00609         return (true);
00610     
00611     if ((*info).filecreator != helperappinfo.apptype) /*keep looking*/
00612         return (true);
00613     
00614     if (!launchappwithdoc (&fs, nil, false)) {
00615         
00616         bigstring bs;
00617         
00618         copystring ("\pCouldn't launch \"", bs);
00619         
00620         pushstring (fname, bs);
00621         
00622         pushstring ("\p\".", bs);
00623         
00624         copystring (bs, helperappinfo.errormessage);
00625         }
00626     else
00627         helperappinfo.launched = true;
00628     
00629     return (false); /*the search is over*/
00630     } /*helpercallback*/
00631     
00632     
00633 boolean getcurrentappfilespec (ptrfilespec pfs) {
00634     
00635     #ifndef macBirdRuntime /*it has no app.xxx record*/
00636     
00637         typrocessinfo info;
00638         
00639         if (!findrunningapp (app.creator, &info)) /*get info about the app*/
00640             return (false);
00641         
00642         *pfs = info.file;
00643     
00644         return (true);
00645     
00646     #else
00647     
00648         #pragma unused (pfs)
00649     
00650         return (false);
00651         
00652     #endif
00653     } /*getcurrentappfilespec*/
00654     
00655     
00656 boolean getcurrentappfolder (ptrfilespec pfs) {
00657     
00658     if (!getcurrentappfilespec (pfs))
00659         return (false);
00660 
00661     return (filegetparentfolderspec (pfs, pfs));
00662     } /*getcurrentappfolder*/
00663     
00664     
00665 static boolean gethelperfolder (ptrfilespec pfshelperfolder, bigstring errormessage) {
00666 
00667     tyfilespec fsfolder;
00668     
00669     setstringlength (errormessage, 0);
00670     
00671     if (!getcurrentappfolder (&fsfolder))
00672         return (false);
00673     
00674     filegetsubitemspec (&fsfolder, "\pHelper Apps", pfshelperfolder);
00675     
00676     if (!fileexists (pfshelperfolder)) {
00677         
00678         copystring ("\pCouldn't locate the \"Helper Apps\" folder.", errormessage);
00679         
00680         return (false);
00681         }
00682     
00683     return (true);
00684     } /*gethelperfolder*/
00685     
00686     
00687 boolean launchHelperApp (OSType serverid, void *verrormessage) {
00688     
00689     byte *errormessage = (byte *) verrormessage;
00690     typrocessinfo info;
00691     tyfilespec fshelperfolder;
00692     
00693     if (findrunningapp (serverid, &info)) /*already running, nothing to do*/
00694         return (true);
00695         
00696     if (!gethelperfolder (&fshelperfolder, errormessage))
00697         return (false);
00698     
00699     helperappinfo.launched = false;
00700     
00701     helperappinfo.apptype = serverid;
00702     
00703     setstringlength (helperappinfo.errormessage, 0);
00704     
00705     folderloop (&fshelperfolder, false, &helpercallback, 0);
00706     
00707     copystring (helperappinfo.errormessage, errormessage);
00708     
00709     return (helperappinfo.launched);
00710     } /*launchHelperApp*/
00711     
00712 
00713 static boolean launchFrontier (void) { /*sample code*/
00714     
00715     bigstring errormessage;
00716     
00717     if (!launchHelperApp ('LAND', errormessage)) {
00718         
00719         if (stringlength (errormessage) == 0)
00720             copystring ("\pCouldn't locate Frontier or Frontier Runtime in the Helper Apps folder.", errormessage);
00721             
00722         alertdialog (errormessage);
00723         
00724         return (false);
00725         }
00726 
00727     return (true);
00728     } /*launchFrontier*/
00729     
00730     

Generated on Wed May 31 18:19:43 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6