Ignore:
Timestamp:
03/12/06 12:44:00 (18 years ago)
Author:
Nicholas Riley
Message:

VERSION: Updated for 1.1d1.

main.c: Updated copyright statement. Updated for 1.1d1. Removed
ancient todo list. Only support 10.4 and higher - removed unnecessary
BROKEN_LSOPENFROMURLSPEC and unused DEBUG #defines. Replace
LSLaunchURLSpec with LSApplicationParameters. Added -o for arguments
(which doesn't work, delaying 1.1's release pending Apple fix).
Support app paths with -a, like open(1) does. Print file content's
UTI if possible on -f. Removed a couple of extraneous arguments to
osstatusexit. Replaced error codes with symbolic constants again.

README: Updated for 1.1d1.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/launch/launch/main.c

    r166 r214  
    33 Nicholas Riley <launchsw@sabi.net>
    44
    5  Copyright (c) 2001-05, Nicholas Riley
     5 Copyright (c) 2001-06, Nicholas Riley
    66 All rights reserved.
    77
     
    1616*/
    1717
    18 /* To do/think about:
    19 
    20 - Launching as root: use authentication framework - doesn't work.
    21 
    22 - launch URL with specified URL handler (done, except for IC)
    23 
    24 - launch apps by IC protocol handler (esp. editor)
    25 
    26 Thanks to:
    27 
    28 - Nat Irons, for encouragement and suggestions
    29 
    30 - Brian Hill, for the great Security.framework tutorial and sample code
    31 
    32 */
    33 
    34 /* #define DEBUG 1 */
    3518#define BROKEN_AUTHORIZATION 1
    36 #define BROKEN_LSOPENFROMURLSPEC 1
    3719#define kComponentSignatureString "launch"
    3820
     
    5133const char *APP_NAME;
    5234
    53 #define VERSION "1.0.1"
     35#define VERSION "1.1d1"
    5436
    5537#define STRBUF_LEN 1024
     
    7153#define DEFAULT_LAUNCH_FLAGS (kLSLaunchNoParams | kLSLaunchStartClassic | kLSLaunchAsync)
    7254
    73 LSLaunchURLSpec LSPEC = {NULL, NULL, NULL, DEFAULT_LAUNCH_FLAGS, NULL};
     55LSApplicationParameters LPARAMS = {0, DEFAULT_LAUNCH_FLAGS, NULL, NULL, NULL, NULL, NULL};
     56CFArrayRef ITEMS = NULL;
     57FSRef APPLICATION;
    7458
    7559char *TEMPFILE = NULL;
     
    8670    { kLSLaunchInProgressErr, "application is being opened; please try again after the application is open" },
    8771    { kLSNotRegisteredErr, "application not registered in Launch Services database" },
    88     { -10827, "application package contains no executable, or an unusable executable" }, /* kLSNoExecutableErr, not defined in 10.2 */
    89     { -10828, "Classic environment required but not available" }, /* kLSNoClassicEnvironmentErr, not defined in 10.2 */
    90     { -10829, "unable to launch multiple instances of application" }, /* kLSMultipleSessionsNotSupportedErr, not defined in 10.2 */
     72    { kLSNoExecutableErr, "application package contains no executable, or an unusable executable" },
     73    { kLSNoClassicEnvironmentErr, "Classic environment required but not available" },
     74    { kLSMultipleSessionsNotSupportedErr, "unable to launch multiple instances of application" },
    9175#ifndef BROKEN_AUTHORIZATION
    9276    // Security framework errors
     
    10892
    10993void usage() {
    110     fprintf(stderr, "usage: %s [-npswbmhCXU] [-c creator] [-i bundleID] [-u URL] [-a name] [item ...] [-]\n"
    111                     "   or: %s [-npflswbmhCXU] item ...\n", APP_NAME, APP_NAME);
     94    fprintf(stderr, "usage: %s [-npswbmhCXU] [-c creator] [-i bundleID] [-u URL] [-a name] [-o argument] [item ...] [-]\n"
     95                    "   or: %s [-npflswbmhCXU] [-o argument] item ...\n", APP_NAME, APP_NAME);
    11296    fprintf(stderr,
    11397        "  -n            print matching paths/URLs instead of opening them\n"
     
    128112        "  -i bundle ID  match application by bundle identifier (com.apple.scripteditor)\n"
    129113        "  -u URL        open application at file:// URL (NOT RECOMMENDED for scripts)\n"
    130         "  -a name       match application by name (NOT RECOMMENDED, very fragile)\n"
     114        "  -a name|path  match application by name/path (NOT RECOMMENDED, very fragile)\n"
     115        "  -o argument   pass argument to application (may be specified more than once)\n"
    131116        "'document' may be a file, folder, or disk - whatever the application can open.\n"
    132117        "'item' may be a file, folder, disk, or URL.\n\n");
    133     fprintf(stderr, "launch "VERSION" (c) 2001-05 Nicholas Riley <http://web.sabi.net/nriley/software/>.\n"
     118    fprintf(stderr, "launch "VERSION" (c) 2001-06 Nicholas Riley <http://web.sabi.net/nriley/software/>.\n"
    134119                    "Please send bugs, suggestions, etc. to <launchsw@sabi.net>.\n");
    135120
     
    288273        errexit("can't create temporary file '%s'", tempPath);
    289274    // mark file as stationery
    290     err = FSPathMakeRef(tempPath, &fsr, NULL);
     275    err = FSPathMakeRef((UInt8 *)tempPath, &fsr, NULL);
    291276    if (err != noErr) osstatusexit(err, "can't find '%s'", tempPath);
    292277    err = FSGetCatalogInfo(&fsr, kFSCatInfoFinderInfo, &catalogInfo, NULL, NULL, NULL);
     
    341326    extern int optind;
    342327    int ch;
     328    OSStatus err;
    343329    Boolean appSpecified = false;
    344330
    345331    if (argc == 1) usage();
    346332   
    347     while ( (ch = getopt(argc, argv, "npflswbmhCXUc:i:u:a:")) != -1) {
     333    while ( (ch = getopt(argc, argv, "npflswbmhCXUc:i:u:a:o:")) != -1) {
    348334        switch (ch) {
    349335        case 'n':
     
    354340            if (OPTS.action != ACTION_DEFAULT) errexit("choose only one of -n, -p, -f, -l options");
    355341            OPTS.action = ACTION_OPEN;
    356             LSPEC.launchFlags |= kLSLaunchAndPrint;
     342            LPARAMS.flags |= kLSLaunchAndPrint;
    357343            break;
    358344        case 'f':
     
    382368        }
    383369#endif
    384         case 'w': LSPEC.launchFlags ^= kLSLaunchAsync; break;      // synchronous
    385         case 'b': LSPEC.launchFlags |= kLSLaunchDontSwitch; break; // open in background
    386         case 'm': LSPEC.launchFlags |= kLSLaunchNewInstance; break;// open multiple
    387         case 'h': LSPEC.launchFlags |= kLSLaunchAndHide; break;    // hide once launched
    388         case 'C': LSPEC.launchFlags |= kLSLaunchInClassic; break;  // force Classic
    389         case 'X': LSPEC.launchFlags ^= kLSLaunchStartClassic; break;// don't start Classic for app
     370        case 'w': LPARAMS.flags ^= kLSLaunchAsync; break;      // synchronous
     371        case 'b': LPARAMS.flags |= kLSLaunchDontSwitch; break; // open in background
     372        case 'm': LPARAMS.flags |= kLSLaunchNewInstance; break;// open multiple
     373        case 'h': LPARAMS.flags |= kLSLaunchAndHide; break;    // hide once launched
     374        case 'C': LPARAMS.flags |= kLSLaunchInClassic; break;  // force Classic
     375        case 'X': LPARAMS.flags ^= kLSLaunchStartClassic; break;// don't start Classic for app
    390376        case 'U': OPTS.forceURLs = true; break;
    391377        case 'c':
     
    399385            break;
    400386        case 'a':
    401             OPTS.name = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
    402             appSpecified = true;
     387            err = FSPathMakeRef((UInt8 *)optarg, &APPLICATION, NULL);
     388            if (err == noErr) {
     389                LPARAMS.application = &APPLICATION;
     390            } else {
     391                OPTS.name = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
     392            }
     393            appSpecified = true;
    403394            break;
    404395        case 'u':
    405396            { CFStringRef str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
    406               LSPEC.appURL = CFURLCreateWithString(NULL, str, NULL);
    407               if (str != NULL) CFRelease(str);
     397              CFURLRef appURL = CFURLCreateWithString(NULL, str, NULL);
     398              if (appURL == NULL)
     399                  errexit("invalid URL (argument of -u)");
     400              err = CFURLGetFSRef(appURL, &APPLICATION);
     401              if (err != noErr)
     402                  osstatusexit(err, "can't find application (argument of -u)");
    408403            }
    409             if (LSPEC.appURL == NULL) {
    410                 errexit("invalid URL (argument of -u)");
    411             } else {
    412                 CFURLRef absURL = CFURLCopyAbsoluteURL(LSPEC.appURL);
    413                 CFRelease(LSPEC.appURL);
    414                 LSPEC.appURL = NULL;
    415                 if (absURL != NULL) {
    416                     CFStringRef scheme = CFURLCopyScheme(absURL);
    417                     LSPEC.appURL = absURL;
    418                     if (scheme == NULL || !CFEqual(scheme, CFSTR("file")))
    419                         errexit("invalid file:// URL (argument of -u)");
    420                     CFRelease(scheme);
    421                 }
    422             }
     404            LPARAMS.application = &APPLICATION;
    423405            appSpecified = true;
    424406            break;
     407        case 'o':
     408            if (LPARAMS.argv == NULL)
     409                LPARAMS.argv = CFArrayCreateMutable(NULL, 0, NULL);
     410            CFArrayAppendValue((CFMutableArrayRef)LPARAMS.argv,
     411                               CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8));
     412            break;
    425413        default: usage();
    426414        }
     
    431419   
    432420    if ( (OPTS.action == ACTION_FIND || OPTS.action == ACTION_LAUNCH_URLS ||
    433           OPTS.action == ACTION_INFO_ITEMS) && LSPEC.launchFlags != DEFAULT_LAUNCH_FLAGS)
     421          OPTS.action == ACTION_INFO_ITEMS) && LPARAMS.flags != DEFAULT_LAUNCH_FLAGS)
    434422        errexit("options -s, -b, -m, -h, -C, -X apply to application launch (not -n, -f or -l)");
    435423   
    436424    if (OPTS.creator == kLSUnknownCreator && OPTS.bundleID == NULL && OPTS.name == NULL) {
    437         if (argc == 0 && LSPEC.appURL == NULL)
     425        if (argc == 0 && LPARAMS.application == NULL)
    438426            errexit("must specify an application by -u, or one or more of -c, -i, -a");
    439427        if (!appSpecified) {
     
    444432        }
    445433    } else {
    446         if (LSPEC.appURL != NULL)
     434        if (LPARAMS.application != NULL)
    447435            errexit("application URL (argument of -u) incompatible with matching by -c, -i, -a");
    448436    }
     
    454442        errexit("can't get information (-f) on item(s) using an application (-u, -c, -i, -a)");
    455443
    456     if (argc == 0 && OPTS.action == ACTION_OPEN && LSPEC.launchFlags & kLSLaunchAndPrint)
     444    if (argc == 0 && OPTS.action == ACTION_OPEN && LPARAMS.flags & kLSLaunchAndPrint)
    457445        errexit("print option (-p) must be accompanied by document(s) to print");
    458446   
     
    468456
    469457        // handle document/item/URL arguments
    470         LSPEC.itemURLs = CFArrayCreateMutable(NULL, argc, NULL);
     458        ITEMS = CFArrayCreateMutable(NULL, argc, NULL);
    471459        for (i = 0 ; i < argc ; i++) {
    472460            argStr = NULL;
    473461            if (strcmp(argv[i], "-") == 0) {
    474462                TEMPFILE = stdinAsTempFile();
    475                 itemURL = CFURLCreateFromFileSystemRepresentation(NULL, TEMPFILE, strlen(TEMPFILE), false);
    476                 LSPEC.launchFlags ^= kLSLaunchAsync;
     463                itemURL = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)TEMPFILE, strlen(TEMPFILE), false);
     464                LPARAMS.flags ^= kLSLaunchAsync;
    477465            } else {
    478466                struct stat stat_buf;
     
    494482                if (itemURL == NULL) {
    495483                    // check for file paths
    496                     itemURL = CFURLCreateFromFileSystemRepresentation(NULL, argv[i], strlen(argv[i]), false);
     484                    itemURL = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)argv[i], strlen(argv[i]), false);
    497485                    err = LSCopyItemInfoForURL(itemURL, kLSRequestExtensionFlagsOnly, &docInfo);
    498486                    if (err != noErr) osstatusexit(err, "unable to locate '%s'", argv[i]);
    499487                }
    500488            }
    501             CFArrayAppendValue((CFMutableArrayRef)LSPEC.itemURLs, itemURL);
     489            CFArrayAppendValue((CFMutableArrayRef)ITEMS, itemURL);
    502490            // don't CFRelease the itemURL because CFArray doesn't retain it by default
    503491            if (argStr != NULL) CFRelease(argStr);
     
    517505        CFRelease(urlString);
    518506    } else {
    519         if (CFURLGetFileSystemRepresentation(url, false, strBuffer, STRBUF_LEN)) {
     507        if (CFURLGetFileSystemRepresentation(url, false, (UInt8 *)strBuffer, STRBUF_LEN)) {
    520508            if (strBuffer[0] == '.' && strBuffer[1] == '/') {
    521509                // remove the leading "./"
     
    598586}
    599587
    600 void printMoreInfoFromURL(CFURLRef url) {
    601     FSRef fsr;
     588void printMoreInfoForRef(FSRef fsr) {
    602589    OSStatus err;
    603590    FSCatalogInfo fscInfo;
    604591
    605     if (!CFURLGetFSRef(url, &fsr)) return;
    606592    err = FSGetCatalogInfo(&fsr, kFSCatInfoNodeFlags | kFSCatInfoAllDates | kFSCatInfoDataSizes | kFSCatInfoRsrcSizes | kFSCatInfoValence, &fscInfo, NULL, NULL, NULL);
    607593    if (err != noErr) osstatusexit(err, "unable to get catalog information for file");
     
    643629
    644630const char *utf8StringFromOSType(OSType osType) {
    645     CFStringRef typeStr = CFStringCreateWithBytes(NULL, (const char *)&osType, 4, CFStringGetSystemEncoding(), false);
     631    CFStringRef typeStr = CFStringCreateWithBytes(NULL, (UInt8 *)&osType, 4, CFStringGetSystemEncoding(), false);
    646632    if (typeStr == NULL) {
    647633        // punt to displaying verbatim
     
    670656        UInt32 intVersion = 0;
    671657        OSStatus err = LSCopyItemInfoForURL(url, kLSRequestAllInfo, &info);
     658        Boolean haveFSRef;
     659        FSRef fsr;
    672660        if (err != noErr) osstatusexit(err, "unable to get information about '%s'", strBuffer);
     661        haveFSRef = CFURLGetFSRef(url, &fsr);
    673662       
    674663        printf("%s: ", strBuffer);
     
    705694            CFStringRef bundleID = NULL;
    706695            if (bundle == NULL && (info.flags & kLSItemInfoIsApplication)) {
    707                 FSRef fsr;
    708                 if (info.flags & kLSItemInfoIsPackage || !CFURLGetFSRef(url, &fsr)) {
     696                if (info.flags & kLSItemInfoIsPackage || !haveFSRef) {
    709697                    printf("\t[can't access CFBundle for application]\n");
    710698                } else { // OS X bug causes this to fail when it shouldn't, so fake it
     
    718706                            if (err != noErr && err != resNotFound) osstatusexit(err, "unable to read 'plst' 0 resource");
    719707                        } else {
    720                             CFDataRef plstData = CFDataCreate(NULL, *h, GetHandleSize(h));
     708                            CFDataRef plstData = CFDataCreate(NULL, (UInt8 *)*h, GetHandleSize(h));
    721709                            CFStringRef error;
    722710                            CFPropertyListRef infoPlist = CFPropertyListCreateFromXMLData(NULL, plstData, kCFPropertyListImmutable, &error);
     
    771759                CFRelease(bundleID);
    772760            }
    773         } else {
     761        } else if (haveFSRef) {
    774762            // try to get a version if we can, but don't complain if we can't
    775             FSRef fsr;
    776             if (CFURLGetFSRef(url, &fsr)) {
    777                 SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm);
    778                 if (ResError() == noErr) {
    779                     VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1);
    780                     if (ResError() == noErr && vers != NULL) {
    781                         version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead?
    782                         intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole;
    783                     }
    784                 }
    785                 CloseResFile(resFork);
    786             }
     763            SInt16 resFork = FSOpenResFile(&fsr, fsRdPerm);
     764            if (ResError() == noErr) {
     765                VersRecHndl vers = (VersRecHndl)Get1Resource('vers', 1);
     766                if (ResError() == noErr && vers != NULL) {
     767                    version = CFStringCreateWithPascalString(NULL, vers[0]->shortVersion, CFStringGetSystemEncoding()); // XXX use country code instead?
     768                    intVersion = ((NumVersionVariant)vers[0]->numericVersion).whole;
     769                }
     770            }
     771            CloseResFile(resFork);
    787772        }
    788773       
     
    799784        printf("\tkind: %s\n", utf8StringFromCFStringRef(kind));
    800785        CFRelease(kind);
    801         printMoreInfoFromURL(url);
     786       
     787        if (haveFSRef) {
     788            // content type identifier (UTI)
     789            err = LSCopyItemAttribute(&fsr, kLSRolesAll, kLSItemContentType, (CFTypeRef *)&kind);
     790            if (err == noErr) {
     791                printf("\tcontent type ID: %s\n", utf8StringFromCFStringRef(kind));
     792                CFRelease(kind);
     793            }
     794            printMoreInfoForRef(fsr);
     795        }
    802796    }
    803797}
     
    822816}
    823817
    824 OSStatus openFromURLSpec() {
    825 #ifndef BROKEN_LSOPENFROMURLSPEC
    826     return LSOpenFromURLSpec(&LSPEC, NULL);
    827 #else
    828     LSLaunchFSRefSpec spec = {NULL, 0, NULL, LSPEC.passThruParams,
    829                               LSPEC.launchFlags, LSPEC.asyncRefCon};
    830     CFIndex urlIndex, urlCount = LSPEC.itemURLs ? CFArrayGetCount(LSPEC.itemURLs) : 0;
    831     FSRef *itemRefs = malloc(urlCount * sizeof(FSRef));
    832     CFURLRef url;
    833     CFStringRef scheme, fileScheme = CFSTR("file");
    834     int itemIndex = 0;
    835     OSStatus err;
    836 
    837     for (urlIndex = 0 ; urlIndex < urlCount ; urlIndex++) {
    838         url = CFArrayGetValueAtIndex(LSPEC.itemURLs, urlIndex);
    839         scheme = CFURLCopyScheme(url);
    840         if (CFEqual(scheme, fileScheme)) {
    841             if (CFURLGetFSRef(url, &itemRefs[itemIndex])) {
    842                 itemIndex++;
    843                 CFArrayRemoveValueAtIndex((CFMutableArrayRef)LSPEC.itemURLs, urlIndex);
    844                 urlIndex--;
    845                 urlCount--;
    846             } else {
    847                 fprintf(stderr, "%s: unable to locate: ", APP_NAME);
    848                 printPathFromURL(url, stderr);
    849             }
    850         }
    851         CFRelease(scheme);
    852     }
    853 
    854     if (urlCount > 0 || itemIndex == 0) { /* URLs, or no items */
    855         err = LSOpenFromURLSpec(&LSPEC, NULL);
    856         if (err != noErr)
    857             return err;
    858     }
    859     if (itemIndex > 0) {
    860         FSRef appRef;
    861         spec.numDocs = itemIndex;
    862         spec.itemRefs = itemRefs;
    863         if (LSPEC.appURL != NULL) {
    864             if (!CFURLGetFSRef(LSPEC.appURL, &appRef)) {
    865                 errexit("can't find application");
    866             }
    867             spec.appRef = &appRef;
    868         }
    869         return LSOpenFromRefSpec(&spec, NULL);
    870     }
    871     return noErr;
    872 #endif
     818OSStatus openItems(void) {
     819    if (ITEMS == NULL)
     820        ITEMS = CFArrayCreate(NULL, NULL, 0, NULL);
     821    CFShow(LPARAMS.argv);
     822    return LSOpenURLsWithRole(ITEMS, kLSRolesAll, NULL, &LPARAMS, NULL, 0);
    873823}
    874824
     
    880830
    881831    if (OPTS.action == ACTION_FIND || OPTS.action == ACTION_OPEN) {
    882         if (LSPEC.appURL != NULL) goto findOK; // already have an application URL
    883         err = LSFindApplicationForInfo(OPTS.creator, OPTS.bundleID, OPTS.name, NULL, &LSPEC.appURL);
     832        if (LPARAMS.application != NULL) goto findOK; // already have an application FSRef
     833        err = LSFindApplicationForInfo(OPTS.creator, OPTS.bundleID, OPTS.name, &APPLICATION, NULL);
     834        LPARAMS.application = &APPLICATION;
    884835       
    885836        if (err != noErr) {
     
    887838                OPTS.name = CFStringCreateMutableCopy(NULL, CFStringGetLength(OPTS.name) + 4, OPTS.name);
    888839                CFStringAppend((CFMutableStringRef)OPTS.name, CFSTR(".app"));
    889                 err = LSFindApplicationForInfo(OPTS.creator, OPTS.bundleID, OPTS.name, NULL, &LSPEC.appURL);
     840                err = LSFindApplicationForInfo(OPTS.creator, OPTS.bundleID, OPTS.name, &APPLICATION, NULL);
    890841                if (err == noErr) goto findOK;
    891842            }
    892             osstatusexit(err, "can't locate application", argv[1]);
     843            osstatusexit(err, "can't locate application");
     844        }
    893845        findOK: ;
    894         }
    895846    }
    896847   
    897848    switch (OPTS.action) {
    898849    case ACTION_FIND:
    899         printPathFromURL(LSPEC.appURL, stdout);
     850        printPathFromURL(CFURLCreateFromFSRef(NULL, LPARAMS.application), stdout);
    900851        break;
    901852    case ACTION_OPEN:
    902         err = openFromURLSpec();
    903         if (err != noErr) osstatusexit(err, "can't open application", argv[1]);
     853        err = openItems();
     854        if (err != noErr) osstatusexit(err, "can't open application");
    904855        break;
    905856    case ACTION_FIND_ITEMS:
    906         CFArrayApplyFunction(LSPEC.itemURLs, CFRangeMake(0, CFArrayGetCount(LSPEC.itemURLs)),
     857        CFArrayApplyFunction(ITEMS, CFRangeMake(0, CFArrayGetCount(ITEMS)),
    907858                             (CFArrayApplierFunction) printPathFromURL, stdout);
    908859        break;
    909860    case ACTION_OPEN_ITEMS:
    910         err = openFromURLSpec();
    911         if (err != noErr) osstatusexit(err, "can't open items", argv[1]);
     861        err = openItems();
     862        if (err != noErr) osstatusexit(err, "can't open items");
    912863        break;
    913864    case ACTION_INFO_ITEMS:
    914         CFArrayApplyFunction(LSPEC.itemURLs, CFRangeMake(0, CFArrayGetCount(LSPEC.itemURLs)),
     865        CFArrayApplyFunction(ITEMS, CFRangeMake(0, CFArrayGetCount(ITEMS)),
    915866                             (CFArrayApplierFunction) printInfoFromURL, NULL);
    916867        break;
     
    920871        err = ICStart(&icInst, '\?\?\?\?'); // in case GCC trigraph handling is enabled
    921872        if (err != noErr) osstatusexit(err, "can't initialize Internet Config", argv[1]);
    922         CFArrayApplyFunction(LSPEC.itemURLs, CFRangeMake(0, CFArrayGetCount(LSPEC.itemURLs)),
     873        CFArrayApplyFunction(ITEMS, CFRangeMake(0, CFArrayGetCount(ITEMS)),
    923874                             (CFArrayApplierFunction) launchURL, icInst);
    924875        ICStop(icInst);
Note: See TracChangeset for help on using the changeset viewer.