home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / SimpleTrap / Sources / SignatureToApp.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  6.8 KB  |  250 lines

  1. /*
  2.     File:        SignatureToApp.c
  3.  
  4.     Contains:    Implementation of the SignatureToApp function.
  5.  
  6.     Written by: Jens Alfke    
  7.  
  8.     Copyright:    Copyright © 1991-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/27/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24.  
  25. #include <Errors.h>
  26. #include <Files.h>
  27. #include <Processes.h>
  28. #include <Folders.h>
  29.  
  30. #include "SignatureToApp.h"
  31.  
  32.  
  33.    ////////////////////////////////////////////////////////////
  34.   //    FindRunningAppBySignature                            //
  35.  //            Search process list for app with this signature//
  36. ////////////////////////////////////////////////////////////
  37. static OSErr
  38. FindRunningAppBySignature( OSType sig, ProcessSerialNumber *psn, FSSpec *fileSpec )
  39. {
  40.     OSErr err;
  41.     ProcessInfoRec info;
  42.     
  43.     psn->highLongOfPSN = 0;
  44.     psn->lowLongOfPSN  = kNoProcess;
  45.     do{
  46.         err= GetNextProcess(psn);
  47.         if( !err ) {
  48.             info.processInfoLength = sizeof(info);
  49.             info.processName = NULL;
  50.             info.processAppSpec = fileSpec;
  51.             err= GetProcessInformation(psn,&info);
  52.         }
  53.     } while( !err && info.processSignature != sig );
  54.  
  55.     if( !err )
  56.         *psn = info.processNumber;
  57.     return err;
  58. }
  59.  
  60.  
  61.    ////////////////////////////////////////////////////////////
  62.   //    GetSysVolume                                        //
  63.  //            Get the vRefNum of the system (boot) volume       //
  64. ////////////////////////////////////////////////////////////
  65. static OSErr
  66. GetSysVolume( short *vRefNum )
  67. {
  68.     long dir;
  69.     
  70.     return FindFolder(kOnSystemDisk,kSystemFolderType,false, vRefNum,&dir);
  71. }
  72.  
  73.  
  74.    ////////////////////////////////////////////////////////////
  75.   //    GetIndVolume                                        //
  76.  //            Get the vRefNum of an indexed on-line volume   //
  77. ////////////////////////////////////////////////////////////
  78. static OSErr
  79. GetIndVolume( short index, short *vRefNum )
  80. {
  81.     ParamBlockRec pb;
  82.     OSErr err;
  83.     
  84.     pb.volumeParam.ioCompletion = NULL;
  85.     pb.volumeParam.ioNamePtr = NULL;
  86.     pb.volumeParam.ioVolIndex = index;
  87.     
  88.     err= PBGetVInfo(&pb,false);
  89.     
  90.     *vRefNum = pb.volumeParam.ioVRefNum;
  91.     return err;
  92. }
  93.  
  94.  
  95.    ////////////////////////////////////////////////////////////
  96.   //    VolHasDesktopDB                                        //
  97.  //            Check if a volume supports desktop DB calls       //
  98. ////////////////////////////////////////////////////////////
  99. static OSErr
  100. VolHasDesktopDB( short vRefNum, Boolean *hasDesktop )
  101. {
  102.     typedef struct {                        // Volume Info Rec; see IM-VI 25-32
  103.         short    vMVersion;
  104.         long    vMAttrib;
  105.         Handle    vMLocalHand;
  106.         long    vMServerAddr;
  107.         long    vMVolumeGrade;
  108.         short    vMForeignPrivID;
  109.     } VolInfoRec;
  110.     const bHasNewDesk = 1L <<12;            // Flag mask for vMAttrib field
  111.     
  112.     HParamBlockRec pb;
  113.     VolInfoRec info;
  114.     OSErr err;
  115.     
  116.     pb.ioParam.ioCompletion = NULL;
  117.     pb.ioParam.ioNamePtr = NULL;
  118.     pb.ioParam.ioVRefNum = vRefNum;
  119.     pb.ioParam.ioBuffer = (Ptr)&info;
  120.     pb.ioParam.ioReqCount = sizeof(VolInfoRec);
  121.     
  122.     err= PBHGetVolParms(&pb,false);            // Get volume info
  123.  
  124.     *hasDesktop = err==noErr && (info.vMAttrib & bHasNewDesk)!=0;
  125.     return err;
  126. }
  127.  
  128.  
  129.    ////////////////////////////////////////////////////////////
  130.   //    FindAppOnVolume                                        //
  131.  //            Ask vol's desktop db for application           //
  132. ////////////////////////////////////////////////////////////
  133. static OSErr
  134. FindAppOnVolume( OSType sig, short vRefNum, FSSpec *file )
  135. {
  136.     DTPBRec pb;
  137.     OSErr err;
  138.     short refNum;
  139.     
  140.     pb.ioCompletion = NULL;
  141.     pb.ioVRefNum = vRefNum;
  142.     pb.ioNamePtr = NULL;
  143.     err= PBDTGetPath(&pb);                // Puts DT refnum into pb.ioDTRefNum
  144.     if( err ) return err;
  145.     refNum = pb.ioDTRefNum;
  146.     
  147.     pb.ioCompletion = NULL;
  148.     pb.ioDTRefNum = refNum;
  149.     pb.ioIndex = 0;
  150.     pb.ioFileCreator = sig;
  151.     pb.ioNamePtr = file->name;
  152.     err= PBDTGetAPPLSync(&pb);                        // Find it!
  153.     
  154.     if( err == fnfErr )
  155.         err = afpItemNotFound;                        // Bug in PBDTGetAPPL
  156.     if( err )
  157.         return err;                                    // Returns afpItemNotFound if app wasn't found.
  158.  
  159.     file->vRefNum = vRefNum;
  160.     file->parID = pb.ioAPPLParID;
  161.     return noErr;
  162. }
  163.  
  164.  
  165.    ////////////////////////////////////////////////////////////
  166.   //    LaunchIt                                            //
  167.  //            Launch app once we have a location               //
  168. ////////////////////////////////////////////////////////////
  169. static OSErr
  170. LaunchIt( const FSSpecPtr fileSpec, LaunchFlags launchControlFlags, ProcessSerialNumber *psn )
  171. {
  172.     LaunchParamBlockRec pb;
  173.     OSErr err;
  174.     
  175.     pb.launchBlockID = extendedBlock;
  176.     pb.launchEPBLength = extendedBlockLen;
  177.     pb.launchFileFlags = launchNoFileFlags;
  178.     pb.launchControlFlags = launchControlFlags | launchNoFileFlags;
  179.     pb.launchAppSpec = fileSpec;
  180.     pb.launchAppParameters = NULL;
  181.     
  182.     err= LaunchApplication(&pb);
  183.     if( !err )
  184.         *psn = pb.launchProcessSN;
  185.     return err;
  186. }
  187.  
  188.  
  189.    ////////////////////////////////////////////////////////////
  190.   //    SignatureToApp                                        //
  191.  //            Main routine. Find app, launching if need be   //
  192. ////////////////////////////////////////////////////////////
  193. OSErr
  194. SignatureToApp( OSType sig, ProcessSerialNumber *psn, FSSpec *fileSpec, Boolean *launched,
  195.                 Sig2App_Mode mode,
  196.                 LaunchFlags launchControlFlags )
  197. {
  198.     ProcessSerialNumber dummyPSN;
  199.     OSErr err;
  200.     short sysVRefNum, vRefNum, index;
  201.     FSSpec file;
  202.     Boolean hasDesktopDB;
  203.     
  204.     if( launched )
  205.         *launched = false;
  206.     if( psn == NULL )
  207.         psn = &dummyPSN;                                // Allow psn parameter to be NIL
  208.     
  209.     // First see if it's already running:
  210.     
  211.     err= FindRunningAppBySignature(sig,psn,fileSpec);
  212.     
  213.     if( err==noErr )
  214.         if( (launchControlFlags & launchDontSwitch) == 0 )
  215.             return SetFrontProcess(psn);                // They wanted to switch to it…
  216.  
  217.     if( err != procNotFound || mode<=Sig2App_FindProcess )
  218.         return err;
  219.     
  220.     // Well, it's not running but it's okay to launch it. Let's have a look around:
  221.     
  222.     if( err= GetSysVolume(&sysVRefNum) ) return err;    // Find boot volume
  223.     vRefNum = sysVRefNum;                                // Start search with boot volume
  224.     index = 0;
  225.     do{
  226.         if( index==0 || vRefNum != sysVRefNum ) {
  227.             if( err= VolHasDesktopDB(vRefNum,&hasDesktopDB) )
  228.                 return err;
  229.             if( hasDesktopDB ) {                        // If volume has a desktop DB,
  230.                 err= FindAppOnVolume(sig,vRefNum, &file);        // ask it to find app
  231.                 if( err==noErr ) {                                // If found,
  232.                     if( fileSpec )
  233.                         *fileSpec = file;
  234.                     if( mode==Sig2App_LaunchApplication ) {
  235.                         if( launched )
  236.                             *launched = true;
  237.                         err= LaunchIt(&file,launchControlFlags,psn);        // Launch it!
  238.                     }
  239.                     return err;
  240.                 } else if( err != afpItemNotFound )
  241.                     return err;
  242.             }
  243.         }
  244.         err= GetIndVolume(++index,&vRefNum);                // Else go to next volume
  245.     } while( err==noErr );                                // Keep going until we run out of vols
  246.     
  247.     if( err==nsvErr || err==afpItemNotFound )
  248.         err= fnfErr;                                    // File not found on any volume
  249.     return err;
  250. }