1/*
2    DNR.c - DNR library for MPW
3
4    (c) Copyright 1988 by Apple Computer.  All rights reserved.
5    PowerPC corrections by Eric Scouten, December 2, 1994.
6
7*/
8
9#define MPW3.0
10
11#include <Carbon.h>
12#if 0
13#include <OSUtils.h>
14#include <Errors.h>
15#include <Files.h>
16#include <Resources.h>
17#include <Memory.h>
18#include <Traps.h>
19#include <Gestalt.h>
20#include <Folders.h>
21#include <MixedMode.h>
22#endif
23
24#define OPENRESOLVER    1L
25#define CLOSERESOLVER   2L
26#define STRTOADDR       3L
27#define ADDRTOSTR       4L
28#define ENUMCACHE       5L
29#define ADDRTONAME      6L
30#define HINFO           7L
31#define MXINFO          8L
32
33Handle              codeHndl = nil;
34UniversalProcPtr    dnr = nil;
35
36enum {
37	NUM_ALT_ADDRS				= 4
38};
39
40struct hostInfo {
41	long							rtnCode;
42	char							cname[255];
43	SInt8							filler;						/* Filler for proper byte alignment	 */
44	unsigned long					addr[NUM_ALT_ADDRS];
45};
46typedef struct hostInfo hostInfo;
47
48static pascal OSErr (*mzSysEnvirons)(int versionRequested, SysEnvRec *theworld);
49static pascal OSErr (*mzGetWDInfo)(short wdRefNum, short *vRefNum, long *dirID, long *procID);
50static pascal UniversalProcPtr (*mzNewRoutineDescriptor) (ProcPtr theProc, ProcInfoType theProcInfo, ISAType theISA);
51static long (*mzCallUniversalProc)(UniversalProcPtr theProcPtr, ProcInfoType theProcInfo, ...);
52
53#define NewRoutineDescriptor mzNewRoutineDescriptor
54#define CallUniversalProc mzCallUniversalProc
55
56void GetSystemFolder(short *vRefNumP, long *dirIDP)
57{
58    SysEnvRec info;
59    long wdProcID;
60
61    mzSysEnvirons(1, &info);
62    if (mzGetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
63        *vRefNumP = 0;
64        *dirIDP = 0;
65        }
66    }
67
68void GetCPanelFolder(short *vRefNumP, long *dirIDP)
69{
70    Boolean hasFolderMgr = false;
71    long feature;
72
73    if (Gestalt(gestaltFindFolderAttr, &feature) == noErr)
74        hasFolderMgr = true;
75    if (!hasFolderMgr) {
76        GetSystemFolder(vRefNumP, dirIDP);
77        return;
78        }
79    else {
80        if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
81            *vRefNumP = 0;
82            *dirIDP = 0;
83            }
84        }
85    }
86
87/* SearchFolderForDNRP is called to search a folder for files that might
88    contain the 'dnrp' resource */
89short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
90{
91    HParamBlockRec fi;
92    Str255 filename;
93    short refnum;
94
95    fi.fileParam.ioCompletion = nil;
96    fi.fileParam.ioNamePtr = filename;
97    fi.fileParam.ioVRefNum = vRefNum;
98    fi.fileParam.ioDirID = dirID;
99    fi.fileParam.ioFDirIndex = 1;
100
101    while (PBHGetFInfoSync(&fi) == noErr) {
102        /* scan system folder for driver resource files of specific type & creator */
103        if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
104            fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
105            /* found the MacTCP driver file? */
106            refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
107            if (GetIndResource('dnrp', 1) == NULL)
108                CloseResFile(refnum);
109            else
110                return refnum;
111            }
112        /* check next file in system folder */
113        fi.fileParam.ioFDirIndex++;
114        fi.fileParam.ioDirID = dirID;   /* PBHGetFInfo() clobbers ioDirID */
115        }
116    return(-1);
117    }
118
119
120
121/* OpenOurRF is called to open the MacTCP driver resources */
122
123short OpenOurRF()
124{
125    short refnum;
126    short vRefNum;
127    long dirID;
128
129    /* first search Control Panels for MacTCP 1.1 */
130    GetCPanelFolder(&vRefNum, &dirID);
131    refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
132    if (refnum != -1) return(refnum);
133
134    /* next search System Folder for MacTCP 1.0.x */
135    GetSystemFolder(&vRefNum, &dirID);
136    refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
137    if (refnum != -1) return(refnum);
138
139    /* finally, search Control Panels for MacTCP 1.0.x */
140    GetCPanelFolder(&vRefNum, &dirID);
141    refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
142    if (refnum != -1) return(refnum);
143
144    return -1;
145    }
146
147
148
149
150typedef OSErr (*OpenResolverProcPtr)(long selector, char* fileName);
151
152enum {
153    uppOpenResolverProcInfo = kCStackBased
154         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
155         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
156         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
157};
158
159#if USESROUTINEDESCRIPTORS
160typedef UniversalProcPtr OpenResolverUPP;
161
162#define NewOpenResolverProc(userRoutine)                        \
163        (OpenResolverUPP) mzNewRoutineDescriptor(userRoutine, uppOpenResolverProcInfo, GetCurrentISA())
164#define CallOpenResolverProc(userRoutine, selector, filename)   \
165        CallUniversalProc(userRoutine, uppOpenResolverProcInfo, selector, filename)
166#else
167typedef OpenResolverProcPtr OpenResolverUPP;
168
169#define NewOpenResolverProc(userRoutine)                    \
170        (OpenResolverUPP)(userRoutine)
171#define CallOpenResolverProc(userRoutine, selector, filename)   \
172        (*userRoutine)(selector, filename)
173#endif
174
175
176
177pascal OSErr OpenResolver(fileName)
178char *fileName;
179{
180    short           refnum;
181    OSErr           rc;
182
183    if (dnr != nil)
184        /* resolver already loaded in */
185        return(noErr);
186
187    /* open the MacTCP driver to get DNR resources. Search for it based on
188       creator & type rather than simply file name */
189    refnum = OpenOurRF();
190
191    /* ignore failures since the resource may have been installed in the
192       System file if running on a Mac 512Ke */
193
194    /* load in the DNR resource package */
195    codeHndl = GetIndResource('dnrp', 1);
196    if (codeHndl == nil) {
197        /* can't open DNR */
198        return(ResError());
199    }
200
201    DetachResource(codeHndl);
202    if (refnum != -1) {
203        CloseResFile(refnum);
204    }
205
206    /* lock the DNR resource since it cannot be reloated while opened */
207    HLock(codeHndl);
208    dnr = (UniversalProcPtr) *codeHndl;
209
210    /* call open resolver */
211    rc = CallOpenResolverProc((OpenResolverUPP) dnr, OPENRESOLVER, fileName);
212    if (rc != noErr) {
213        /* problem with open resolver, flush it */
214        HUnlock(codeHndl);
215        DisposeHandle(codeHndl);
216        dnr = nil;
217    }
218    return(rc);
219}
220
221
222
223typedef OSErr (*CloseResolverProcPtr)(long selector);
224
225enum {
226    uppCloseResolverProcInfo = kCStackBased
227         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
228         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
229};
230
231#if USESROUTINEDESCRIPTORS
232typedef UniversalProcPtr CloseResolverUPP;
233
234#define NewCloseResolverProc(userRoutine)                       \
235        (CloseResolverUPP) mzNewRoutineDescriptor(userRoutine, uppCloseResolverProcInfo, GetCurrentISA())
236#define CallCloseResolverProc(userRoutine, selector)    \
237        CallUniversalProc(userRoutine, uppCloseResolverProcInfo, selector)
238#else
239typedef CloseResolverProcPtr CloseResolverUPP;
240
241#define NewCloseResolverProc(userRoutine)                       \
242        (CloseResolverUPP)(userRoutine)
243#define CallCloseResolverProc(userRoutine, selector)    \
244        (*userRoutine)(selector)
245#endif
246
247
248
249pascal OSErr CloseResolver()
250{
251    if (dnr == nil)
252        /* resolver not loaded error */
253        return(notOpenErr);
254
255    /* call close resolver */
256    CallCloseResolverProc((CloseResolverUPP) dnr, CLOSERESOLVER);
257
258    /* release the DNR resource package */
259    HUnlock(codeHndl);
260    DisposeHandle(codeHndl);
261    dnr = nil;
262    return(noErr);
263}
264
265
266
267
268typedef OSErr (*StrToAddrProcPtr)(long selector, char* hostName, struct hostInfo* rtnStruct,
269                                    long resultProc, char* userData);
270
271enum {
272    uppStrToAddrProcInfo = kCStackBased
273         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
274         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
275         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
276         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
277         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
278         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
279};
280
281#if USESROUTINEDESCRIPTORS
282typedef UniversalProcPtr StrToAddrUPP;
283
284#define NewStrToAddrProc(userRoutine)                       \
285        (StrToAddrUPP) mzNewRoutineDescriptor(userRoutine, uppStrToAddrProcInfo, GetCurrentISA())
286#define CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData) \
287        CallUniversalProc(userRoutine, uppStrToAddrProcInfo, selector, hostName, rtnStruct, resultProc, userData)
288#else
289typedef StrToAddrProcPtr StrToAddrUPP;
290
291#define NewStrToAddrProc(userRoutine)                       \
292        (StrToAddrUPP)(userRoutine)
293#define CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData) \
294        (*userRoutine)(selector, hostName, rtnStruct, resultProc, userData)
295#endif
296
297
298
299pascal OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
300char *hostName;
301struct hostInfo *rtnStruct;
302long resultproc;
303char *userDataPtr;
304{
305    if (dnr == nil)
306        /* resolver not loaded error */
307        return(notOpenErr);
308
309    return(CallStrToAddrProc((StrToAddrUPP) dnr, STRTOADDR, hostName, (void*) rtnStruct,
310                            resultproc, userDataPtr));
311}
312
313
314typedef OSErr (*AddrToStrProcPtr)(long selector, long address, char* hostName);
315
316enum {
317    uppAddrToStrProcInfo = kCStackBased
318         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
319         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
320         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
321         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
322};
323
324#if USESROUTINEDESCRIPTORS
325typedef UniversalProcPtr AddrToStrUPP;
326
327#define NewAddrToStrProc(userRoutine)                       \
328        (AddrToStrUPP) mzNewRoutineDescriptor(userRoutine, uppAddrToStrProcInfo, GetCurrentISA())
329#define CallAddrToStrProc(userRoutine, selector, address, hostName) \
330        CallUniversalProc(userRoutine, uppAddrToStrProcInfo, selector, address, hostName)
331#else
332typedef AddrToStrProcPtr AddrToStrUPP;
333
334#define NewAddrToStrProc(userRoutine)                       \
335        (AddrToStrUPP)(userRoutine)
336#define CallAddrToStrProc(userRoutine, selector, address, hostName) \
337        (*userRoutine)(selector, address, hostName)
338#endif
339
340
341pascal OSErr AddrToStr(addr, addrStr)
342unsigned long addr;
343char *addrStr;
344{
345    if (dnr == nil)
346        /* resolver not loaded error */
347        return(notOpenErr);
348
349    CallAddrToStrProc((AddrToStrUPP) dnr, ADDRTOSTR, addr, addrStr);
350
351    return(noErr);
352}
353
354
355
356typedef OSErr (*EnumCacheProcPtr)(long selector, long result, char* userData);
357
358enum {
359    uppEnumCacheProcInfo = kCStackBased
360         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
361         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
362         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
363         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
364};
365
366#if USESROUTINEDESCRIPTORS
367typedef UniversalProcPtr EnumCacheUPP;
368
369#define NewEnumCacheProc(userRoutine)                       \
370        (EnumCacheUPP) mzNewRoutineDescriptor(userRoutine, uppEnumCacheProcInfo, GetCurrentISA())
371#define CallEnumCacheProc(userRoutine, selector, result, userData)  \
372        CallUniversalProc(userRoutine, uppEnumCacheProcInfo, selector, result, userData)
373#else
374typedef EnumCacheProcPtr EnumCacheUPP;
375
376#define NewEnumCacheProc(userRoutine)                       \
377        (EnumCacheUPP)(userRoutine)
378#define CallEnumCacheProc(userRoutine, selector, result, userData)  \
379        (*userRoutine)(selector, result, userData)
380#endif
381
382
383
384pascal OSErr EnumCache(resultproc, userDataPtr)
385long resultproc;
386char *userDataPtr;
387{
388    if (dnr == nil)
389        /* resolver not loaded error */
390        return(notOpenErr);
391
392    return(CallEnumCacheProc((EnumCacheUPP) dnr, ENUMCACHE, resultproc, userDataPtr));
393}
394
395
396
397typedef OSErr (*AddrToNameProcPtr)(long selector, unsigned long addr, struct hostInfo* rtnStruct,
398                                    long resultProc, char* userData);
399
400enum {
401    uppAddrToNameProcInfo = kCStackBased
402         | RESULT_SIZE(SIZE_CODE(sizeof(long)))
403         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
404         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
405         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
406         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
407         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
408
409};
410
411#if USESROUTINEDESCRIPTORS
412typedef UniversalProcPtr AddrToNameUPP;
413
414#define NewAddrToNameProc(userRoutine)                      \
415        (AddrToNameUPP) mzNewRoutineDescriptor(userRoutine, uppAddrToNameProcInfo, GetCurrentISA())
416#define CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
417        CallUniversalProc(userRoutine, uppAddrToNameProcInfo, selector, addr, rtnStruct, resultProc, userData)
418#else
419typedef AddrToNameProcPtr AddrToNameUPP;
420
421#define NewAddrToNameProc(userRoutine)                      \
422        (AddrToNameUPP)(userRoutine)
423#define CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
424        (*userRoutine)(selector, addr, rtnStruct, resultProc, userData)
425#endif
426
427
428
429pascal OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
430unsigned long addr;
431struct hostInfo *rtnStruct;
432long resultproc;
433char *userDataPtr;
434{
435    if (dnr == nil)
436        /* resolver not loaded error */
437        return(notOpenErr);
438
439    return(CallAddrToNameProc((AddrToNameUPP) dnr, ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
440}
441
442typedef long ResultUPP;
443enum {
444	uppResultProcInfo = kPascalStackBased
445		 | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(struct hostInfo*)))
446		 | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Ptr))),
447      };
448#define NewResultProc(proc) (ResultUPP)mzNewRoutineDescriptor((ProcPtr)proc, uppResultProcInfo, GetCurrentArchitecture())
449