hx_moreprocesses.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:19k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "platform/mac/HX_MoreProcesses.h"
  36. #if defined(_CARBON) || defined(_MAC_UNIX)
  37. #include "platform/mac/MoreFilesX.h"
  38. #endif
  39. #ifndef _MAC_UNIX
  40. #include "hxmm.h"
  41. #endif
  42. #ifndef _MAC_UNIX /* this is defined always true for _MAC_UNIX builds */
  43. Boolean IsRunningNativeOnMacOSX()
  44. {
  45. #ifdef _CARBON
  46. long sysVersion;
  47. OSErr err;
  48. static int zIsNative = 0;
  49. if (zIsNative == 1) return true;
  50. if (zIsNative == -1) return false;
  51. err = Gestalt(gestaltSystemVersion, &sysVersion);
  52. check_noerr(err);
  53. if (err == noErr && sysVersion >= 0x1000)
  54. {
  55. zIsNative = 1;
  56. return true;
  57. }
  58. else
  59. {
  60. zIsNative = -1;
  61. return false;
  62. }
  63. #else
  64. return false;
  65. #endif
  66. }
  67. #endif
  68. Boolean IsMacInCooperativeThread()
  69. {
  70. // stuff that's ok to do at system time is OK to do
  71. // if we're in a cooperative MP task. This includes
  72. // both the main app MP task ("system time") as well
  73. // as thread manager threads.
  74. // This is basically a more OS X friendly way to do
  75. // a HXMM_ATINTERRUPT() check, only it also checks
  76. // against all preemptive threads and not just the
  77. // faux interrupt time for which we've called the
  78. // pnmm interrupt-setting routines.
  79. // MPTaskIsPreemptive(kMPInvalidIDErr) used to work
  80. // for this but fails to compile now that the task
  81. // parameter is opaque. That's why it pulls out the
  82. // actual current task ID.
  83. if ( MPTaskIsPreemptive( MPCurrentTaskID() ) )
  84. {
  85. return false;
  86. }
  87. else
  88. {
  89. return true;
  90. }
  91. }
  92. //
  93. // SameFSSpec
  94. //
  95. // Compares two FSSpec structures and returns true if they point to the same file.
  96. //
  97. Boolean  SameFSSpec(FSSpecPtr   sa,  FSSpecPtr  sb)
  98. {
  99. if (sa->vRefNum==sb->vRefNum)
  100. {
  101. if (sa->parID==sb->parID)
  102. {
  103. if (EqualString(sb->name,sa->name,false,false))
  104. {
  105. return true;
  106. }
  107. }
  108. }
  109. return false;
  110. }
  111. //
  112. // CheckForAppRunningAtPath
  113. //
  114. // Looks through all processes and looks for one with the same path name.
  115. //
  116. /*
  117. Boolean CheckForAppRunningAtPath(Str255 path)
  118. {
  119. OSErr e    = noErr;
  120. ProcessSerialNumber psn    = {kNoProcess, kNoProcess};
  121. Boolean theResult=false;
  122. FSSpec serverSpec;
  123. FSSpec appSpec;
  124. // Get the fsspec of the path.
  125. // Return if there isn't a server at the path.
  126. if (FSMakeFSSpec(0,0,path,&serverSpec)) return false;
  127. while (noErr == (e = GetNextProcess (&psn))) 
  128. {
  129. ProcessInfoRec info;
  130. info.processInfoLength = sizeof (info);
  131. info.processName = nil;
  132. info.processAppSpec = &appSpec;
  133. if (noErr != (e = GetProcessInformation (&psn, &info))) break;
  134. // Check to see if this is the correct 
  135. if (SameFSSpec(&appSpec,&serverSpec)) 
  136. {
  137. theResult=true;
  138. break;
  139. }
  140. continue;
  141. return (theResult);
  142. }
  143. */
  144. //
  145. // CheckForApplicationRunning
  146. //
  147. // Looks through all the processes for one matching the signature passed in the "AppSignature"
  148. // 
  149. Boolean CheckForApplicationRunning(OSType AppSignature) {
  150. OSErr err;
  151. err = GetPSNFromSignature(AppSignature, NULL);
  152. return (err == noErr);
  153. }
  154. Boolean CheckForApplicationRunningFSSpec(OSType AppSignature,FSSpec *spec) {
  155. return GetApplicationSpec(AppSignature, spec);
  156. }
  157. //
  158. // GetPSNSpec
  159. //
  160. // Returns the FSSpec for the related PSN.
  161. // 
  162. Boolean GetPSNSpec(ProcessSerialNumber* psn,FSSpec* theSpec)
  163. {
  164. Boolean theResult= false;
  165. ProcessInfoRec info;
  166. OSErr e=noErr;
  167. info.processInfoLength = sizeof (info);
  168. info.processName = nil;
  169. info.processAppSpec = theSpec;
  170. e=GetProcessInformation (psn, &info);
  171. theResult = e ? false : true;
  172. return theResult;
  173. }
  174. //
  175. // GetApplicationSpec
  176. //
  177. // Looks through all the processes for one matching the signature passed in the "AppSignature"
  178. // Then returns the Application's FSSpec.
  179. // 
  180. Boolean GetApplicationSpec(OSType AppSignature, FSSpec *theSpec) 
  181. {
  182. OSErr e   = noErr;
  183. ProcessSerialNumber psn   = {kNoProcess, kNoProcess};
  184. Boolean theResult=false;
  185. while (noErr == (e = GetNextProcess (&psn))) {
  186. ProcessInfoRec info;
  187. info.processInfoLength = sizeof (info);
  188. info.processName = nil;
  189. info.processAppSpec = theSpec;
  190. if (noErr != (e = GetProcessInformation (&psn, &info))) break;
  191. if (AppSignature != info.processSignature) continue;
  192. theResult=true;
  193. break;
  194. } /* while */
  195. return (theResult);
  196. }
  197. //
  198. // GetCurrentAppSpec
  199. //
  200. // Returns the FSSpec for the currently running application.
  201. // 
  202. Boolean GetCurrentAppSpec(FSSpec *theSpec)
  203. {
  204. OSErr err;
  205. ProcessSerialNumber psn;
  206. ProcessInfoRec pir;
  207. if (theSpec == NULL) return false;
  208. psn.highLongOfPSN = 0;
  209. psn.lowLongOfPSN = kCurrentProcess;
  210. pir.processInfoLength = sizeof(ProcessInfoRec);
  211. pir.processName = nil;
  212. pir.processAppSpec = theSpec;
  213. err = GetProcessInformation (&psn, &pir);
  214. return (err == noErr);
  215. }
  216. //
  217. // GetCurrentAppSignature
  218. //
  219. // Returns the signature for the currently running application.
  220. // 
  221. OSType GetCurrentAppSignature(void)
  222. {
  223. OSErr err;
  224. ProcessSerialNumber psn;
  225. ProcessInfoRec pir;
  226. psn.highLongOfPSN = 0;
  227. psn.lowLongOfPSN = kCurrentProcess;
  228. pir.processInfoLength = sizeof(ProcessInfoRec);
  229. pir.processName = nil;
  230. pir.processAppSpec = nil;
  231. err = GetProcessInformation (&psn, &pir);
  232. if (err == noErr) return pir.processSignature;
  233. else return '????';
  234. }
  235. //
  236. // GetPSNFromSignature returns the ProcessSerialNumber for the
  237. // app with the given signature if the app is running
  238. //
  239. // psn can be nil if the caller only wants to know if the
  240. // app is running
  241. //
  242. OSErr GetPSNFromSignature(OSType signature, ProcessSerialNumber *psn)
  243. {
  244. ProcessSerialNumber currPSN;
  245. ProcessInfoRec currPIR;
  246. OSErr err;
  247. currPSN.lowLongOfPSN = kNoProcess;
  248. currPSN.highLongOfPSN = 0;
  249. do {
  250. err = GetNextProcess(&currPSN);
  251. if (err == noErr)
  252. {
  253. currPIR.processName = NULL;
  254. currPIR.processAppSpec = NULL;
  255. currPIR.processInfoLength = sizeof(ProcessInfoRec);
  256. err = GetProcessInformation(&currPSN, &currPIR);
  257. if (err == noErr && currPIR.processSignature == signature)
  258. {
  259. if (psn) *psn = currPSN;
  260. break;
  261. }
  262. }
  263. } while (err == noErr);
  264. return err;
  265. }
  266. //
  267. // GetSignatureFromPSN returns the signature for the
  268. // app with the given PSN
  269. //
  270. // signature can be nil if the caller only wants to know if the
  271. // app is running
  272. //
  273. OSErr GetSignatureFromPSN(const ProcessSerialNumber *psn, OSType *signature)
  274. {
  275. ProcessSerialNumber currPSN;
  276. ProcessInfoRec currPIR;
  277. OSErr err;
  278. Boolean  bSamePSN;
  279. currPSN.lowLongOfPSN = kNoProcess;
  280. currPSN.highLongOfPSN = 0;
  281. do {
  282. err = GetNextProcess(&currPSN);
  283. if (err == noErr)
  284. {
  285. if (SameProcess(&currPSN, psn, &bSamePSN) == noErr
  286.   && bSamePSN)
  287. {
  288. currPIR.processName = NULL;
  289. currPIR.processAppSpec = NULL;
  290. currPIR.processInfoLength = sizeof(ProcessInfoRec);
  291. err = GetProcessInformation(&currPSN, &currPIR);
  292. if (err == noErr)
  293. {
  294. if (signature) 
  295. {
  296. *signature = currPIR.processSignature;
  297. }
  298. }
  299. break;
  300. }
  301. }
  302. } while (err == noErr);
  303. return err;
  304. }
  305. //
  306. // CountAppSignatures
  307. //
  308. // Looks through all the processes and returns a count of the processes with AppSignature.
  309. //
  310. short CountAppSignatures(OSType AppSignature) {
  311. OSErr e   = noErr;
  312. ProcessSerialNumber psn   = {kNoProcess, kNoProcess};
  313. short theResult=0;
  314. while (noErr == (e = GetNextProcess (&psn))) {
  315. ProcessInfoRec info;
  316. info.processInfoLength = sizeof (info);
  317. info.processName = nil;
  318. info.processAppSpec = nil;
  319. if (noErr != (e = GetProcessInformation (&psn, &info))) break;
  320. if (AppSignature != info.processSignature) continue;
  321. theResult++;
  322. } /* while */
  323. return (theResult);
  324. }
  325. //
  326. // ActivateApplication
  327. //
  328. void ActivateApplication(OSType AppSignature) {
  329. OSErr e   = noErr;
  330. ProcessSerialNumber psn   = {kNoProcess, kNoProcess};
  331. while (noErr == (e = GetNextProcess (&psn))) {
  332. ProcessInfoRec info;
  333. info.processInfoLength = sizeof (info);
  334. info.processName = nil;
  335. info.processAppSpec = nil;
  336. if (noErr != (e = GetProcessInformation (&psn, &info))) break;
  337. if (AppSignature != info.processSignature) continue;
  338. ActivateApplicationPSN(&psn);
  339. break;
  340. } /* while */
  341. }
  342. //
  343. // ActivateApplicationPSN
  344. //
  345. void ActivateApplicationPSN(ProcessSerialNumber *psn) {
  346. if (psn == 0L) return;
  347. SetFrontProcess(psn);
  348. }
  349. //
  350. // FSpLaunchApplication launches a Mac application given a file spec
  351. //
  352. OSErr FSpLaunchApplication (FSSpec *appSpec) {
  353. return FSpLaunchApplicationWithParams(appSpec, NULL, NULL);
  354. }
  355. //
  356. // FSpLaunchApplication launches a Mac application given a file spec
  357. //  and an option Apple Event to include as a launch parameter
  358. //
  359. //  If psn is non-nil, the launched processes' PSN is returned
  360. //
  361. OSErr FSpLaunchApplicationWithParams(FSSpec *appSpec, const AppleEvent *theEvent, ProcessSerialNumber *psn)
  362. {
  363. return FSpLaunchApplicationWithParamsAndFlags(appSpec, theEvent, psn, (launchContinue | launchNoFileFlags));
  364. }
  365. OSErr FSpLaunchApplicationWithParamsAndFlags(FSSpec *appSpec, const AppleEvent *theEvent, ProcessSerialNumber *psn, short launchFlags)
  366. {
  367. OSErr err = noErr;
  368. LaunchParamBlockRec launchPB;
  369. AEDesc paramsDesc;
  370. paramsDesc.dataHandle = NULL;
  371. launchPB.launchBlockID  = extendedBlock;
  372. launchPB.launchEPBLength  = extendedBlockLen;
  373. launchPB.launchFileFlags  = 0;
  374. launchPB.launchControlFlags = launchFlags;
  375. launchPB.launchAppSpec  = appSpec;
  376. launchPB.launchAppParameters  = NULL;
  377. // if we were passed an event, convert and attach that to the launch param block
  378. if (theEvent)
  379. {
  380. err = AECoerceDesc(theEvent, typeAppParameters, &paramsDesc);
  381. if (err == noErr)
  382. {
  383. #if !defined(_CARBON) && !defined(_MAC_UNIX)
  384. HLock(paramsDesc.dataHandle);
  385. #endif
  386. launchPB.launchAppParameters = (AppParametersPtr) *paramsDesc.dataHandle;
  387. }
  388. }
  389. // do the launch
  390. if (err == noErr)
  391. {
  392. err = LaunchApplication(&launchPB);
  393. if (err == noErr && psn != NULL)
  394. {
  395. *psn = launchPB.launchProcessSN;
  396. }
  397. }
  398. // if we had an event to convert and attach, dispose our converted version
  399. if (paramsDesc.dataHandle) (void) AEDisposeDesc(&paramsDesc);
  400. return err;
  401. }
  402. OSErr FSpLaunchApplicationPSN (FSSpec *appSpec,ProcessSerialNumber* psn) {
  403. return FSpLaunchApplicationWithParams(appSpec, NULL, psn);
  404. }
  405. //
  406. // OpenDocumentWithApplication sends an event to the target application
  407. // to open the document, launching the application if necessary.
  408. //
  409. // Unlike sending an Apple event to the finder, this gives us an
  410. // error if the open doesn't happen
  411. //
  412. OSErr OpenDocumentWithApplication(OSType signature, FSSpec *file)
  413. {
  414. OSErr err;
  415. ProcessSerialNumber appPSN;
  416. FSSpec appSpec;
  417. AEDesc targetAddrDesc;
  418. AppleEvent theAppleEvent, theReplyEvent;
  419. AliasHandle fileAlias;
  420. theAppleEvent.dataHandle = NULL; // to facilitate cleanup
  421. targetAddrDesc.dataHandle = NULL;
  422. appPSN.lowLongOfPSN = 0;
  423. fileAlias = NULL;
  424. err = GetPSNFromSignature(signature, &appPSN);
  425. if (err != noErr)
  426. {
  427. // app isn't running, we'll try to launch it
  428. //
  429. // address the event target by the process's signature
  430. err = AECreateDesc(typeApplSignature, &signature, sizeof(DescType), &targetAddrDesc);
  431. }
  432. else
  433. {
  434. // address target by PSN
  435. err = AECreateDesc(typeProcessSerialNumber, &appPSN, sizeof(ProcessSerialNumber), &targetAddrDesc);
  436. }
  437. if (err == noErr)
  438. {
  439. // make the Apple event, stuff in an alias to the file as the direct object
  440. err = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &targetAddrDesc, 
  441. kAutoGenerateReturnID, kAnyTransactionID, &theAppleEvent);
  442. if (err == noErr)
  443. {
  444. err = NewAliasMinimal(file, &fileAlias);
  445. if (err == noErr)
  446. {
  447. HLock((Handle) fileAlias);
  448. err = AEPutParamPtr(&theAppleEvent, keyDirectObject, typeAlias, 
  449. *fileAlias, GetHandleSize((Handle) fileAlias));
  450. }
  451. }
  452. }
  453. if (err == noErr)
  454. {
  455. if (appPSN.lowLongOfPSN)
  456. {
  457. // app is running and we know its PSN, so
  458. // send the event directly to it
  459. err = AESend(&theAppleEvent, &theReplyEvent, kAENoReply, 
  460. kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  461. (void) SetFrontProcess(&appPSN);
  462. }
  463. else
  464. {
  465. // the app isn't running, so launch it with the
  466. // event attached
  467. err = FindApplicationBySignature(signature, &appSpec);
  468. if (err == noErr) 
  469. {
  470. err = FSpLaunchApplicationWithParams(&appSpec, &theAppleEvent, NULL);
  471. }
  472. }
  473. }
  474. if (fileAlias)  DisposeHandle((Handle) fileAlias);
  475. if (theAppleEvent.dataHandle) (void) AEDisposeDesc(&theAppleEvent);
  476. if (targetAddrDesc.dataHandle) (void) AEDisposeDesc(&targetAddrDesc);
  477. return err;
  478. }
  479. //
  480. // LaunchApplicationBySignature finds an application on a local 
  481. // volume and launches it.  theEvent can be null if no Apple
  482. // event should be attached.
  483. //
  484. OSErr LaunchApplicationBySignature(OSType signature, AppleEvent *theEvent)
  485. {
  486. OSErr err;
  487. FSSpec appSpec;
  488. err = FindApplicationBySignature(signature, &appSpec);
  489. if (err == noErr) 
  490. {
  491. err = FSpLaunchApplicationWithParams(&appSpec, theEvent, NULL);
  492. }
  493. return err;
  494. }
  495. //
  496. // FindApplicationBySignature finds an application on a local (not server)
  497. // volume by checking the Desktop Databases of the mounted drives
  498. //
  499. // appSpec can be NULL if the caller is just interested in if the app
  500. // exists or not
  501. //
  502. OSErr FindApplicationBySignature(OSType signature, FSSpec *appSpec)
  503. {
  504. #ifndef _MAC_UNIX
  505. Str63 name;
  506. short volIndex;
  507. short vRefNum;
  508. HParamBlockRec hpb;
  509. DTPBRec dtpb;
  510. GetVolParmsInfoBuffer gvpb;
  511. Boolean foundAppFlag;
  512. Boolean giveUpFlag;
  513. #endif
  514. OSErr err;
  515. #if defined(_CARBON) || defined(_MAC_UNIX)
  516. if (IsRunningNativeOnMacOSX())
  517. {
  518. // Mac OS X; we can't rely on the desktop database, so use launch services
  519. FSRef appRef;
  520. err = GetApplicationFSRefFromSignature(signature, &appRef);
  521. if (err == noErr)
  522. {
  523. err = FSRefMakeFSSpec(&appRef, appSpec);
  524. }
  525. return err;
  526. }
  527. #endif
  528. #if defined(_MAC_UNIX)
  529. return -1; // should never get here
  530. #else
  531. foundAppFlag = false;
  532. giveUpFlag = false;
  533. // step through each volume available
  534. volIndex = 1;
  535. do {
  536. name[0] = 0;
  537. hpb.volumeParam.ioNamePtr = name;
  538. hpb.volumeParam.ioVolIndex = volIndex;
  539. hpb.volumeParam.ioVRefNum = 0;
  540. hpb.volumeParam.ioCompletion = NULL; // shouldn't matter since we're calling sync
  541. err = PBHGetVInfoSync(&hpb);
  542. if (err == noErr)
  543. {
  544. vRefNum = hpb.volumeParam.ioVRefNum;
  545. // check only local volumes for the application
  546. //
  547. // PBHGetVolParms returns vMServerAdr of zero for local volumes
  548. //
  549. // name and vRefNum are already set in param block hpb from the PBHGetVInfo call
  550. hpb.ioParam.ioBuffer = (char *) &gvpb;
  551. hpb.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  552. err = PBHGetVolParmsSync(&hpb);
  553. if (err == noErr && gvpb.vMServerAdr == 0)
  554. {
  555. // now we know this is a valid, local volume; 
  556. // see if it has a desktop database
  557. dtpb.ioNamePtr = NULL;
  558. dtpb.ioVRefNum = vRefNum;
  559. err = PBDTGetPath(&dtpb);
  560. if (err == noErr)
  561. {
  562. // this volume has a desktop database; search it
  563. name[0] = 0;
  564. dtpb.ioNamePtr = name;
  565. dtpb.ioIndex = 0; // get newest application
  566. dtpb.ioFileCreator = signature;
  567. dtpb.ioCompletion = NULL; // shouldn't matter since we're calling sync
  568. // dtpb.ioDTRefNum set by GetPath call
  569. err = PBDTGetAPPLSync(&dtpb);
  570. if (err == noErr)
  571. {
  572. FSSpec foundSpec;
  573. err = FSMakeFSSpec(vRefNum, dtpb.ioAPPLParID, name, &foundSpec);
  574. if (err == noErr)
  575. {
  576. if (appSpec) *appSpec = foundSpec;
  577. // we got the app; bail
  578. foundAppFlag = true;
  579. }
  580. }
  581. }
  582. }
  583. }
  584. else
  585. {
  586. // PBHGetVInfoSync returned an error
  587. giveUpFlag = true;
  588. }
  589. volIndex++;
  590. } while (!giveUpFlag &&!foundAppFlag);
  591. // at this point, we should have noErr indicating that we found
  592. // an app and the FSSpec is valid
  593. return err;
  594. #endif // !defined _MAC_UNIX
  595. }
  596. OSErr SendQuitEventToApplication(ProcessSerialNumber *psn)
  597. {
  598. OSErr err;
  599. AEAddressDesc targetAddrDesc;
  600. AppleEvent theAppleEvent;
  601. AppleEvent replyAppleEvent;
  602. // address target by PSN
  603. err = AECreateDesc(typeProcessSerialNumber, psn, sizeof(ProcessSerialNumber), &targetAddrDesc);
  604. if (err == noErr)
  605. {
  606. // make the quit event
  607. err = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &targetAddrDesc, 
  608. kAutoGenerateReturnID, kAnyTransactionID, &theAppleEvent);
  609. (void) AEDisposeDesc(&targetAddrDesc);
  610. }
  611. if (err == noErr)
  612. {
  613. // send it
  614. err = AESend(&theAppleEvent, &replyAppleEvent, kAENoReply, 
  615. kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
  616. (void) AEDisposeDesc(&theAppleEvent);
  617. }
  618. return err;
  619. }
  620. #if defined(_CARBON) || defined(_MAC_UNIX)
  621. OSStatus GetApplicationFSRefFromSignature(OSType signature, FSRef *outAppFSRef)
  622. {
  623. OSStatus err;
  624. const OSType kAnyFileType = kLSUnknownType;
  625. const CFStringRef kAnyExtension = NULL;
  626. CFURLRef* kDontWantURL = NULL;
  627. if (IsRunningNativeOnMacOSX())
  628. {
  629. err = LSGetApplicationForInfo(kAnyFileType, signature, kAnyExtension, kLSRolesAll, outAppFSRef, kDontWantURL);
  630. }
  631. else
  632. {
  633. FSSpec appSpec;
  634. err = FindApplicationBySignature(signature, &appSpec);
  635. if (err == noErr)
  636. {
  637. err = FSpMakeFSRef(&appSpec, outAppFSRef);
  638. }
  639. }
  640. return err;
  641. }
  642. #endif