1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        mac/corefoundation/utilsexc_base.cpp 
   3 // Purpose:     wxMacExecute 
   8 // Copyright:   (c) Ryan Norton 
   9 // Licence:     wxWindows licence 
  10 // Notes:       Source was originally in utilsexc_cf.cpp,1.6 then moved 
  11 //              to totally unrelated hid.cpp,1.8. 
  12 ///////////////////////////////////////////////////////////////////////////// 
  14 //=========================================================================== 
  16 //=========================================================================== 
  18 //--------------------------------------------------------------------------- 
  19 // Pre-compiled header stuff 
  20 //--------------------------------------------------------------------------- 
  22 // For compilers that support precompilation, includes "wx.h". 
  23 #include "wx/wxprec.h" 
  27     #include "wx/string.h" 
  34 #include <CoreFoundation/CoreFoundation.h> 
  35 #include <ApplicationServices/ApplicationServices.h> 
  38 #include "wx/filename.h" 
  39 #include "wx/mac/corefoundation/cfstring.h" 
  43 #define kDefaultPathStyle kCFURLPOSIXPathStyle 
  45 #define kDefaultPathStyle kCFURLHFSPathStyle 
  48 //=========================================================================== 
  50 //=========================================================================== 
  52 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  56 // argv is the command line split up, with the application path first 
  57 // flags are the flags from wxExecute 
  58 // process is the process passed from wxExecute for pipe streams etc. 
  59 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC 
  60 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  61 long wxMacExecute(wxChar 
**argv
, 
  65     // Semi-macros used for return value of wxMacExecute 
  66     const long errorCode 
= ((flags 
& wxEXEC_SYNC
) ? -1 : 0); 
  67     const long successCode 
= ((flags 
& wxEXEC_SYNC
) ? 0 : -1); // fake PID 
  69     // Obtains the number of arguments for determining the size of 
  70     // the CFArray used to hold them 
  72     for(wxChar
** argvcopy 
= argv
; *argvcopy 
!= NULL 
; ++argvcopy
) 
  77     // If there is not a single argument then there is no application 
  81         wxLogDebug(wxT("wxMacExecute No file to launch!")); 
  86     wxString path 
= *argv
++; 
  88     // Create a CFURL for the application path 
  89     // Created this way because we are opening a bundle which is a directory 
  91         CFURLCreateWithFileSystemPath( 
  93             wxMacCFStringHolder(path
), 
  95             true); //false == not a directory 
  97     // Check for error from the CFURL 
 100         wxLogDebug(wxT("wxMacExecute Can't open path: %s"), path
.c_str()); 
 104     // Create a CFBundle from the CFURL created earlier 
 105     CFBundleRef cfbApp 
= CFBundleCreate(kCFAllocatorDefault
, cfurlApp
); 
 107     // Check to see if CFBundleCreate returned an error, 
 108     // and if it did this was an invalid bundle or not a bundle 
 109     // at all (maybe a simple directory etc.) 
 112         wxLogDebug(wxT("wxMacExecute Bad bundle: %s"), path
.c_str()); 
 117     // Get the bundle type and make sure its an 'APPL' bundle 
 118     // Otherwise we're dealing with something else here... 
 119     UInt32 dwBundleType
, dwBundleCreator
; 
 120     CFBundleGetPackageInfo(cfbApp
, &dwBundleType
, &dwBundleCreator
); 
 121     if(dwBundleType 
!= 'APPL') 
 123         wxLogDebug(wxT("wxMacExecute Not an APPL bundle: %s"), path
.c_str()); 
 129     // Create a CFArray for dealing with the command line 
 130     // arguments to the bundle 
 131     CFMutableArrayRef cfaFiles 
= CFArrayCreateMutable(kCFAllocatorDefault
, 
 132                                     cfiCount
-1, &kCFTypeArrayCallBacks
); 
 133     if(!cfaFiles
) //This should never happen 
 135         wxLogDebug(wxT("wxMacExecute Could not create CFMutableArray")); 
 141     // Loop through command line arguments to the bundle, 
 142     // turn them into CFURLs and then put them in cfaFiles 
 143     // For use to launch services call 
 144         for( ; *argv 
!= NULL 
; ++argv
) 
 146         // Check for '<' as this will ring true for 
 147         // CFURLCreateWithString but is generally not considered 
 148         // typical on mac but is usually passed here from wxExecute 
 149         if (wxStrcmp(*argv
, wxT("<")) == 0) 
 153         CFURLRef cfurlCurrentFile
;    // CFURL to hold file path 
 154         wxFileName 
argfn(*argv
);     // Filename for path 
 156         if(argfn
.DirExists()) 
 158             // First, try creating as a directory 
 159             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 161                                 wxMacCFStringHolder(*argv
), 
 163                                 true); //true == directory 
 165         else if(argfn
.FileExists()) 
 167             // And if it isn't a directory try creating it 
 169             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 171                                 wxMacCFStringHolder(*argv
), 
 173                                 false); //false == regular file 
 177             // Argument did not refer to 
 178             // an entry in the local filesystem, 
 179             // so try creating it through CFURLCreateWithString 
 180             cfurlCurrentFile 
= CFURLCreateWithString( 
 182                                 wxMacCFStringHolder(*argv
), 
 186         // Continue in the loop if the CFURL could not be created 
 187         if(!cfurlCurrentFile
) 
 190                 wxT("wxMacExecute Could not create CFURL for argument:%s"), 
 195         // Add the valid CFURL to the argument array and then 
 196         // release it as the CFArray adds a ref count to it 
 201             CFRelease(cfurlCurrentFile
); // array has retained it 
 204     // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec 
 205     // Note that there are several flag options (launchFlags) such 
 206     // as kLSLaunchDontSwitch etc. and maybe we could be more 
 207     // picky about the flags we choose 
 208     LSLaunchURLSpec launchspec
; 
 209     launchspec
.appURL 
= cfurlApp
; 
 210     launchspec
.itemURLs 
= cfaFiles
; 
 211     launchspec
.passThruParams 
= NULL
; //AEDesc* 
 212     launchspec
.launchFlags 
= kLSLaunchDefaults
; 
 213     launchspec
.asyncRefCon 
= NULL
; 
 215     // Finally, call LSOpenFromURL spec with our arguments 
 216     // 2nd parameter is a pointer to a CFURL that gets 
 217     // the actual path launched by the function 
 218     OSStatus status 
= LSOpenFromURLSpec(&launchspec
, NULL
); 
 220     // Cleanup corefoundation references 
 225     // Check for error from LSOpenFromURLSpec 
 228         wxLogDebug(wxT("wxMacExecute LSOpenFromURLSpec Error: %d"), 
 233     // No error from LSOpenFromURLSpec, so app was launched