home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / apple / DNR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-05  |  15.2 KB  |  556 lines  |  [TEXT/R*ch]

  1. /*
  2.     DNR.c - DNR library for MPW
  3.  
  4.     © Copyright 1988 by Apple Computer.  All rights reserved
  5.     
  6. */
  7.  
  8. /*----------------------------------------------------------
  9.  
  10.     DANGER WILL ROBINSON!!!!
  11.     
  12.     This file started life on the CW DR/3 CD. It was crap.
  13.     I had to hack it to death to get it to work.
  14.     
  15. -----------------------------------------------------------*/
  16.  
  17. #pragma require_prototypes off
  18.  
  19. #define MPW3.0
  20.  
  21. #include <OSUtils.h>
  22. #include <Errors.h>
  23. #include <Files.h>
  24. #include <Resources.h>
  25. #include <Memory.h>
  26. #include <Traps.h>
  27. #include <GestaltEqu.h>
  28. #include <Folders.h>
  29. #include <MixedMode.h>                                        
  30.  
  31.  
  32.  
  33.  
  34. #define OPENRESOLVER    1
  35. #define CLOSERESOLVER    2
  36. #define STRTOADDR        3
  37. #define    ADDRTOSTR        4
  38. #define    ENUMCACHE        5
  39. #define ADDRTONAME        6
  40. #define    HINFO            7
  41. #define MXINFO            8
  42.  
  43. Handle                 codeHndl = nil;
  44. UniversalProcPtr    dnr = nil;
  45.  
  46.  
  47. TrapType GetTrapType(theTrap)
  48. unsigned long theTrap;
  49. {
  50.     if (BitAnd(theTrap, 0x0800) > 0)
  51.         return(ToolTrap);
  52.     else
  53.         return(OSTrap);
  54.     }
  55.     
  56. Boolean TrapAvailable(trap)
  57. unsigned long trap;
  58. {
  59. TrapType trapType = ToolTrap;
  60. unsigned long numToolBoxTraps;
  61.  
  62.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  63.         numToolBoxTraps = 0x200;
  64.     else
  65.         numToolBoxTraps = 0x400;
  66.  
  67.     trapType = GetTrapType(trap);
  68.     if (trapType == ToolTrap) {
  69.         trap = BitAnd(trap, 0x07FF);
  70.         if (trap >= numToolBoxTraps)
  71.             trap = _Unimplemented;
  72.         }
  73.     return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  74.  
  75. }
  76.  
  77. void GetSystemFolder(short *vRefNumP, long *dirIDP)
  78. {
  79.     SysEnvRec info;
  80.     long wdProcID;
  81.     
  82.     SysEnvirons(1, &info);
  83.     if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
  84.         *vRefNumP = 0;
  85.         *dirIDP = 0;
  86.         }
  87.     }
  88.  
  89. void GetCPanelFolder(short *vRefNumP, long *dirIDP)
  90. {
  91.     Boolean hasFolderMgr = false;
  92.     long feature;
  93.     
  94.     if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) 
  95.         hasFolderMgr = true;
  96.     if (!hasFolderMgr) {
  97.         GetSystemFolder(vRefNumP, dirIDP);
  98.         return;
  99.         }
  100.     else {
  101.         if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
  102.             *vRefNumP = 0;
  103.             *dirIDP = 0;
  104.             }
  105.         }
  106.     }
  107.     
  108. /* SearchFolderForDNRP is called to search a folder for files that might 
  109.     contain the 'dnrp' resource */
  110. short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
  111. {
  112.     HParamBlockRec fi;
  113.     Str255 filename;
  114.     short refnum;
  115.     
  116.     fi.fileParam.ioCompletion = nil;
  117.     fi.fileParam.ioNamePtr = filename;
  118.     fi.fileParam.ioVRefNum = vRefNum;
  119.     fi.fileParam.ioDirID = dirID;
  120.     fi.fileParam.ioFDirIndex = 1;
  121.     
  122.     while (PBHGetFInfo(&fi, false) == noErr) {
  123.         /* scan system folder for driver resource files of specific type & creator */
  124.         if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
  125.             fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
  126.             /* found the MacTCP driver file? */
  127.             refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
  128.             if (GetIndResource('dnrp', 1) == NULL)
  129.                 CloseResFile(refnum);
  130.             else
  131.                 return refnum;
  132.             }
  133.         /* check next file in system folder */
  134.         fi.fileParam.ioFDirIndex++;
  135.         fi.fileParam.ioDirID = dirID;    /* PBHGetFInfo() clobbers ioDirID */
  136.         }
  137.     return(-1);
  138.     }    
  139.  
  140.  
  141.  
  142. /* OpenOurRF is called to open the MacTCP driver resources */
  143.  
  144. short OpenOurRF()
  145. {
  146.     short refnum;
  147.     short vRefNum;
  148.     long dirID;
  149.     
  150.     /* first search Control Panels for MacTCP 1.1 */
  151.     GetCPanelFolder(&vRefNum, &dirID);
  152.     refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
  153.     if (refnum != -1) return(refnum);
  154.         
  155.     /* next search System Folder for MacTCP 1.0.x */
  156.     GetSystemFolder(&vRefNum, &dirID);
  157.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  158.     if (refnum != -1) return(refnum);
  159.         
  160.     /* finally, search Control Panels for MacTCP 1.0.x */
  161.     GetCPanelFolder(&vRefNum, &dirID);
  162.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  163.     if (refnum != -1) return(refnum);
  164.         
  165.     return -1;
  166.     }    
  167.  
  168.  
  169.  
  170.  
  171. typedef OSErr (*OpenResolverProcPtr)(long selector, char* fileName);
  172.  
  173. enum {
  174.     uppOpenResolverProcInfo = kCStackBased
  175.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  176.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  177.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  178. };
  179.  
  180. #if USESROUTINEDESCRIPTORS
  181. typedef UniversalProcPtr OpenResolverUPP;
  182.  
  183. #define    NewOpenResolverProc(userRoutine)                        \
  184.         (OpenResolverUPP) NewRoutineDescriptor(userRoutine, uppOpenResolverProcInfo, GetCurrentISA())
  185. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  186.         CallUniversalProc(userRoutine, uppOpenResolverProcInfo, selector, filename)
  187. #else
  188. typedef OpenResolverProcPtr OpenResolverUPP;
  189.  
  190. #define    NewOpenResolverProc(userRoutine)                    \
  191.         (OpenResolverUPP)(userRoutine)
  192. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  193.         (*(OpenResolverProcPtr)userRoutine)(selector, filename)
  194. #endif
  195.  
  196.  
  197.  
  198. OSErr OpenResolver(fileName)
  199. char *fileName;
  200. {
  201.     short             refnum;
  202.     OSErr             rc;
  203.     
  204.     if (dnr != nil)
  205.         /* resolver already loaded in */
  206.         return(noErr);
  207.         
  208.     /* open the MacTCP driver to get DNR resources. Search for it based on
  209.        creator & type rather than simply file name */    
  210.     refnum = OpenOurRF();
  211.  
  212.     /* ignore failures since the resource may have been installed in the 
  213.        System file if running on a Mac 512Ke */
  214.        
  215.     /* load in the DNR resource package */
  216.     codeHndl = GetIndResource('dnrp', 1);
  217.     if (codeHndl == nil) {
  218.         /* can't open DNR */
  219.         return(ResError());
  220.     }
  221.     
  222.     DetachResource(codeHndl);
  223.     if (refnum != -1) {
  224.         CloseWD(refnum);
  225.         CloseResFile(refnum);
  226.     }
  227.         
  228.     /* lock the DNR resource since it cannot be reloated while opened */
  229.     HLock(codeHndl);
  230.     dnr = (UniversalProcPtr) *codeHndl;
  231.     
  232.     /* call open resolver */
  233.     rc = CallOpenResolverProc(dnr, OPENRESOLVER, fileName);
  234.     if (rc != noErr) {
  235.         /* problem with open resolver, flush it */
  236.         HUnlock(codeHndl);
  237.         DisposeHandle(codeHndl);
  238.         dnr = nil;
  239.     }
  240.     return(rc);
  241. }
  242.  
  243.  
  244.  
  245. typedef OSErr (*CloseResolverProcPtr)(long selector);
  246.  
  247. enum {
  248.     uppCloseResolverProcInfo = kCStackBased
  249.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  250.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  251. };
  252.  
  253. #if USESROUTINEDESCRIPTORS
  254. typedef UniversalProcPtr CloseResolverUPP;
  255.  
  256. #define    NewCloseResolverProc(userRoutine)                        \
  257.         (CloseResolverUPP) NewRoutineDescriptor(userRoutine, uppCloseResolverProcInfo, GetCurrentISA())
  258. #define    CallCloseResolverProc(userRoutine, selector)    \
  259.         CallUniversalProc(userRoutine, uppCloseResolverProcInfo, selector)
  260. #else
  261. typedef CloseResolverProcPtr CloseResolverUPP;
  262.  
  263. #define    NewCloseResolverProc(userRoutine)                         \
  264.         (CloseResolverUPP)(userRoutine)
  265. #define    CallCloseResolverProc(userRoutine, selector)    \
  266.         (*(CloseResolverProcPtr)userRoutine)(selector)
  267. #endif
  268.  
  269.  
  270.  
  271. OSErr CloseResolver()
  272. {
  273.     if (dnr == nil)
  274.         /* resolver not loaded error */
  275.         return(notOpenErr);
  276.         
  277.     /* call close resolver */
  278.     CallCloseResolverProc(dnr, CLOSERESOLVER);
  279.  
  280.     /* release the DNR resource package */
  281.     HUnlock(codeHndl);
  282.     DisposeHandle(codeHndl);
  283.     dnr = nil;
  284.     return(noErr);
  285. }
  286.  
  287.  
  288.  
  289. typedef struct hostInfo* HostInfoPtr;
  290. typedef OSErr (*StrToAddrProcPtr)(long selector, char* hostName, HostInfoPtr rtnStruct,
  291.                                     long resultProc, char* userData);
  292.                                     
  293. enum {
  294.     uppStrToAddrProcInfo = kCStackBased
  295.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  296.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  297.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  298.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  299.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  300.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  301. };
  302.  
  303. #if USESROUTINEDESCRIPTORS
  304. typedef UniversalProcPtr StrToAddrUPP;
  305.  
  306. #define    NewStrToAddrProc(userRoutine)                        \
  307.         (StrToAddrUPP) NewRoutineDescriptor(userRoutine, uppStrToAddrProcInfo, GetCurrentISA())
  308. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  309.         CallUniversalProc(userRoutine, uppStrToAddrProcInfo, selector, hostName, rtnStruct, resultProc, userData)
  310. #else
  311. typedef StrToAddrProcPtr StrToAddrUPP;
  312.  
  313. #define    NewStrToAddrProc(userRoutine)                        \
  314.         (StrToAddrUPP)(userRoutine)
  315. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  316.         (*(StrToAddrProcPtr)userRoutine)(selector, hostName, rtnStruct, resultProc, userData)
  317. #endif
  318.  
  319.  
  320.  
  321. OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
  322. char *hostName;
  323. struct hostInfo *rtnStruct;
  324. long resultproc;
  325. char *userDataPtr;
  326. {
  327.     OSErr    err;
  328.     if (dnr == nil)
  329.         /* resolver not loaded error */
  330.         return(notOpenErr);
  331.         
  332.     err= CallStrToAddrProc(dnr, STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr);
  333.     return(err);
  334. }
  335.  
  336.  
  337. typedef OSErr (*AddrToStrProcPtr)(long selector, long address, char* hostName);
  338.  
  339. enum {
  340.     uppAddrToStrProcInfo = kCStackBased
  341.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  342.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  343.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  344.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  345. };
  346.  
  347. #if USESROUTINEDESCRIPTORS
  348. typedef UniversalProcPtr AddrToStrUPP;
  349.  
  350. #define    NewAddrToStrProc(userRoutine)                        \
  351.         (AddrToStrUPP) NewRoutineDescriptor(userRoutine, uppAddrToStrProcInfo, GetCurrentISA())
  352. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  353.         CallUniversalProc(userRoutine, uppAddrToStrProcInfo, selector, address, hostName)
  354. #else
  355. typedef AddrToStrProcPtr AddrToStrUPP;
  356.  
  357. #define    NewAddrToStrProc(userRoutine)                        \
  358.         (AddrToStrUPP)(userRoutine)
  359. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  360.         (*(AddrToStrProcPtr)userRoutine)(selector, address, hostName)
  361. #endif
  362.  
  363.     
  364. OSErr AddrToStr(addr, addrStr)
  365. unsigned long addr;
  366. char *addrStr;                                    
  367. {
  368.     if (dnr == nil)
  369.         /* resolver not loaded error */
  370.         return(notOpenErr);
  371.         
  372.     CallAddrToStrProc(dnr, ADDRTOSTR, addr, addrStr);
  373.  
  374.     return(noErr);
  375. }
  376.  
  377.  
  378.  
  379. typedef OSErr (*EnumCacheProcPtr)(long selector, long result, char* userData);
  380.  
  381. enum {
  382.     uppEnumCacheProcInfo = kCStackBased
  383.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  384.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  385.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
  386.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  387. };
  388.  
  389. #if USESROUTINEDESCRIPTORS
  390. typedef UniversalProcPtr EnumCacheUPP;
  391.  
  392. #define    NewEnumCacheProc(userRoutine)                        \
  393.         (EnumCacheUPP) NewRoutineDescriptor(userRoutine, uppEnumCacheProcInfo, GetCurrentISA())
  394. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  395.         CallUniversalProc(userRoutine, uppEnumCacheProcInfo, selector, result, userData)
  396. #else
  397. typedef EnumCacheProcPtr EnumCacheUPP;
  398.  
  399. #define    NewEnumCacheProc(userRoutine)                        \
  400.         (EnumCacheUPP)(userRoutine)
  401. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  402.         (*(EnumCacheProcPtr)userRoutine)(selector, result, userData)
  403. #endif
  404.  
  405.  
  406.     
  407. OSErr EnumCache(resultproc, userDataPtr)
  408. long resultproc;
  409. char *userDataPtr;
  410. {
  411.     if (dnr == nil)
  412.         /* resolver not loaded error */
  413.         return(notOpenErr);
  414.         
  415.     return(CallEnumCacheProc(dnr, ENUMCACHE, resultproc, userDataPtr));
  416. }
  417.  
  418.  
  419.  
  420. typedef OSErr (*AddrToNameProcPtr)(long selector, unsigned long addr, struct hostInfo* rtnStruct,
  421.                                     long resultProc, char* userData);
  422.  
  423. enum {
  424.     uppAddrToNameProcInfo = kCStackBased
  425.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  426.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  427.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  428.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  429.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  430.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  431.  
  432. };
  433.  
  434. #if USESROUTINEDESCRIPTORS
  435. typedef UniversalProcPtr AddrToNameUPP;
  436.  
  437. #define    NewAddrToNameProc(userRoutine)                        \
  438.         (AddrToNameUPP) NewRoutineDescriptor(userRoutine, uppAddrToNameProcInfo, GetCurrentISA())
  439. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  440.         CallUniversalProc(userRoutine, uppAddrToNameProcInfo, selector, addr, rtnStruct, resultProc, userData)
  441. #else
  442. typedef AddrToNameProcPtr AddrToNameUPP;
  443.  
  444. #define    NewAddrToNameProc(userRoutine)                        \
  445.         (AddrToNameUPP)(userRoutine)
  446. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  447.         (*(AddrToNameProcPtr)userRoutine)(selector, addr, rtnStruct, resultProc, userData)
  448. #endif
  449.  
  450.     
  451.     
  452. OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
  453. unsigned long addr;
  454. struct hostInfo *rtnStruct;
  455. long resultproc;
  456. char *userDataPtr;                                    
  457. {
  458.     if (dnr == nil)
  459.         /* resolver not loaded error */
  460.         return(notOpenErr);
  461.         
  462.     return(CallAddrToNameProc(dnr, ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
  463. }
  464.  
  465.  
  466. typedef struct returnRec *ReturnRecPtr;
  467. typedef OSErr (*HInfoProcPtr)(long selector, char* hostName, ReturnRecPtr returnRecPtr,
  468.                                 long resultProc, char* userData);
  469.  
  470. enum {
  471.     uppHInfoProcInfo = kCStackBased
  472.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  473.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  474.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  475.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  476.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  477.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  478.  
  479. };
  480.  
  481. #if USESROUTINEDESCRIPTORS
  482. typedef UniversalProcPtr HInfoUPP;
  483.  
  484. #define    NewHInfoProc(userRoutine)                        \
  485.         (HInfoUPP) NewRoutineDescriptor(userRoutine, uppHInfoProcInfo, GetCurrentISA())
  486. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  487.         CallUniversalProc(userRoutine, uppHInfoProcInfo, selector, hostName, returnRecPtr, resultProc, userData)
  488. #else
  489. typedef HInfoProcPtr HInfoUPP;
  490.  
  491. #define    NewHInfoProc(userRoutine)                        \
  492.         (HInfoUPP)(userRoutine)
  493. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  494.         (*(HInfoProcPtr)userRoutine)(selector, hostName, returnRecPtr, resultProc, userData)
  495. #endif
  496.  
  497. extern OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  498. char *hostName;
  499. struct returnRec *returnRecPtr;
  500. long resultProc;
  501. char *userDataPtr;
  502. {
  503.     OSErr err;
  504.     if (dnr == nil)
  505.         /* resolver not loaded error */
  506.         return(notOpenErr);
  507.         
  508.     err= CallHInfoProc(dnr, HINFO, hostName, returnRecPtr, resultProc, userDataPtr);
  509.     return(err);
  510. }
  511.  
  512.  
  513.  
  514. typedef OSErr (*MXInfoProcPtr)(long selector, char* hostName, struct returnRec* returnRecPtr,
  515.                                 long resultProc, char* userData);
  516.  
  517. enum {
  518.     uppMXInfoProcInfo = kCStackBased
  519.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  520.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(long)))
  521.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  522.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  523.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  524.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  525.  
  526. };
  527.  
  528. #if USESROUTINEDESCRIPTORS
  529. typedef UniversalProcPtr MXInfoUPP;
  530.  
  531. #define    NewMXInfoProc(userRoutine)                        \
  532.         (MXInfoUPP) NewRoutineDescriptor(userRoutine, uppMXInfoProcInfo, GetCurrentISA())
  533. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  534.         CallUniversalProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)
  535. #else
  536. typedef MXInfoProcPtr MXInfoUPP;
  537.  
  538. #define    NewMXInfoProc(userRoutine)                        \
  539.         (MXInfoUPP)(userRoutine)
  540. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  541.         (*(MXInfoProcPtr)userRoutine)(selector, hostName, returnRecPtr, resultProc, userData)
  542. #endif
  543.     
  544.     
  545. extern OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  546. char *hostName;
  547. struct returnRec *returnRecPtr;
  548. long resultProc;
  549. char *userDataPtr;
  550. {
  551.     if (dnr == nil)
  552.         /* resolver not loaded error */
  553.         return(notOpenErr);
  554.         
  555.     return(CallMXInfoProc(dnr, MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  556. }