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" 
  35 #include <CoreFoundation/CoreFoundation.h> 
  36 #include <ApplicationServices/ApplicationServices.h> 
  39 #include "wx/filename.h" 
  40 #include "wx/mac/corefoundation/cfstring.h" 
  44 #define kDefaultPathStyle kCFURLPOSIXPathStyle 
  46 #define kDefaultPathStyle kCFURLHFSPathStyle 
  49 //=========================================================================== 
  51 //=========================================================================== 
  53 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  57 // argv is the command line split up, with the application path first 
  58 // flags are the flags from wxExecute 
  59 // process is the process passed from wxExecute for pipe streams etc. 
  60 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC 
  61 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  62 long wxMacExecute(wxChar 
**argv
, 
  64                wxProcess 
*WXUNUSED(process
)) 
  66     // Semi-macros used for return value of wxMacExecute 
  67     const long errorCode 
= ((flags 
& wxEXEC_SYNC
) ? -1 : 0); 
  68     const long successCode 
= ((flags 
& wxEXEC_SYNC
) ? 0 : -1); // fake PID 
  70     // Obtains the number of arguments for determining the size of 
  71     // the CFArray used to hold them 
  73     for(wxChar
** argvcopy 
= argv
; *argvcopy 
!= NULL 
; ++argvcopy
) 
  78     // If there is not a single argument then there is no application 
  82         wxLogDebug(wxT("wxMacExecute No file to launch!")); 
  87     wxString path 
= *argv
++; 
  89     // Create a CFURL for the application path 
  90     // Created this way because we are opening a bundle which is a directory 
  92         CFURLCreateWithFileSystemPath( 
  94             wxMacCFStringHolder(path
), 
  96             true); //false == not a directory 
  98     // Check for error from the CFURL 
 101         wxLogDebug(wxT("wxMacExecute Can't open path: %s"), path
.c_str()); 
 105     // Create a CFBundle from the CFURL created earlier 
 106     CFBundleRef cfbApp 
= CFBundleCreate(kCFAllocatorDefault
, cfurlApp
); 
 108     // Check to see if CFBundleCreate returned an error, 
 109     // and if it did this was an invalid bundle or not a bundle 
 110     // at all (maybe a simple directory etc.) 
 113         wxLogDebug(wxT("wxMacExecute Bad bundle: %s"), path
.c_str()); 
 118     // Get the bundle type and make sure its an 'APPL' bundle 
 119     // Otherwise we're dealing with something else here... 
 120     UInt32 dwBundleType
, dwBundleCreator
; 
 121     CFBundleGetPackageInfo(cfbApp
, &dwBundleType
, &dwBundleCreator
); 
 122     if(dwBundleType 
!= 'APPL') 
 124         wxLogDebug(wxT("wxMacExecute Not an APPL bundle: %s"), path
.c_str()); 
 130     // Create a CFArray for dealing with the command line 
 131     // arguments to the bundle 
 132     CFMutableArrayRef cfaFiles 
= CFArrayCreateMutable(kCFAllocatorDefault
, 
 133                                     cfiCount
-1, &kCFTypeArrayCallBacks
); 
 134     if(!cfaFiles
) //This should never happen 
 136         wxLogDebug(wxT("wxMacExecute Could not create CFMutableArray")); 
 142     // Loop through command line arguments to the bundle, 
 143     // turn them into CFURLs and then put them in cfaFiles 
 144     // For use to launch services call 
 145         for( ; *argv 
!= NULL 
; ++argv
) 
 147         // Check for '<' as this will ring true for 
 148         // CFURLCreateWithString but is generally not considered 
 149         // typical on mac but is usually passed here from wxExecute 
 150         if (wxStrcmp(*argv
, wxT("<")) == 0) 
 154         CFURLRef cfurlCurrentFile
;    // CFURL to hold file path 
 155         wxFileName 
argfn(*argv
);     // Filename for path 
 157         if(argfn
.DirExists()) 
 159             // First, try creating as a directory 
 160             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 162                                 wxMacCFStringHolder(*argv
), 
 164                                 true); //true == directory 
 166         else if(argfn
.FileExists()) 
 168             // And if it isn't a directory try creating it 
 170             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 172                                 wxMacCFStringHolder(*argv
), 
 174                                 false); //false == regular file 
 178             // Argument did not refer to 
 179             // an entry in the local filesystem, 
 180             // so try creating it through CFURLCreateWithString 
 181             cfurlCurrentFile 
= CFURLCreateWithString( 
 183                                 wxMacCFStringHolder(*argv
), 
 187         // Continue in the loop if the CFURL could not be created 
 188         if(!cfurlCurrentFile
) 
 191                 wxT("wxMacExecute Could not create CFURL for argument:%s"), 
 196         // Add the valid CFURL to the argument array and then 
 197         // release it as the CFArray adds a ref count to it 
 202             CFRelease(cfurlCurrentFile
); // array has retained it 
 205     // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec 
 206     // Note that there are several flag options (launchFlags) such 
 207     // as kLSLaunchDontSwitch etc. and maybe we could be more 
 208     // picky about the flags we choose 
 209     LSLaunchURLSpec launchspec
; 
 210     launchspec
.appURL 
= cfurlApp
; 
 211     launchspec
.itemURLs 
= cfaFiles
; 
 212     launchspec
.passThruParams 
= NULL
; //AEDesc* 
 213     launchspec
.launchFlags 
= kLSLaunchDefaults
; 
 214     launchspec
.asyncRefCon 
= NULL
; 
 216     // Finally, call LSOpenFromURL spec with our arguments 
 217     // 2nd parameter is a pointer to a CFURL that gets 
 218     // the actual path launched by the function 
 219     OSStatus status 
= LSOpenFromURLSpec(&launchspec
, NULL
); 
 221     // Cleanup corefoundation references 
 226     // Check for error from LSOpenFromURLSpec 
 229         wxLogDebug(wxT("wxMacExecute LSOpenFromURLSpec Error: %d"), 
 234     // No error from LSOpenFromURLSpec, so app was launched