home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sys.mac.programmer
- Path: sparky!uunet!cs.utexas.edu!sun-barr!ames!data.nas.nasa.gov!taligent!kip-50.taligent.com!user
- From: keith@taligent.com (Keith Rollin)
- Subject: Re: Keeping a resource file open forever from an INIT
- Message-ID: <keith-240193180424@kip-50.taligent.com>
- Followup-To: comp.sys.mac.programmer
- Sender: usenet@taligent.com (More Bytes Than You Can Read)
- Organization: Taligent
- References: <2L9WB4WS@cc.swarthmore.edu>
- Date: Mon, 25 Jan 1993 02:21:29 GMT
- Lines: 176
-
- In article <2L9WB4WS@cc.swarthmore.edu>, pbrande1@cc.swarthmore.edu (Philip
- Brandenberger) wrote:
- >
- > Hello all-- I hope this is blatantly FAQ.
- >
- > I am working on an INIT in which I'd like to keep my resource file open
- > forever much as Suitcase/MasterJuggler does for itself and its suitcases and
- > as Carpetbag does also.
- >
- > I gather that the way to do this is to hack at the FCBs, but the whole
- > process is a bit cloudy. If anyone has sample code or a basic description
- > that would be great.
-
- Here's how I do it:
-
- // --------------------
- // A macro for patching traps. Follows my own naming conventions, so it
- // may not be useful for you. But I include it for completeness.
-
- #define PatchTheTrap(trapName, type) \
- old##trapName = (trapName##Proc) Get##type##TrapAddress(_##trapName); \
- Set##type##TrapAddress((long) My##trapName, _##trapName)
-
- // --------------------
- // The relevent parts of my INIT's startup code. I strip the PC according
- // to Technote #245 (I don't know its name under the new TN scheme). I then
- // roll my own RememberA0/SetUpA4, since it saves a few bytes. Next, I
- patch
- // InitAllPacks and remember what file I came from for later. Finally, I
- // restore A4 and leave.
-
- void main()
- {
- Ptr ourAddress;
- Handle ourHandle;
- Handle show;
-
- asm {
- lea @continue,A0 ; Fix up the PC (TN #245)
- move.l A0,D0
- StripAddress ; clean the PC
- move.l D0,A0
- jmp (A0) ; use the new PC
- @continue
-
- move.l A4,-(sp) ; save orig A4
- bsr __GetA4 ; get pointer to save location into A1
- lea main,A4 ; get our A4
- move.l A4,(A1) ; save it so SetUpA4() will work
- move.l A4, ourAddress ; for the RecoverHandle, later
- }
-
- PatchTheTrap(InitAllPacks, Tool);
- RememberMe();
-
- RestoreA4();
- }
-
- // --------------------
- // Remembers the name and location of the file owning the currently active
- // resource map. This is stored in a global variable, which is a snap under
- // THINK C. If you are using MPW, read Technote #256 or develop #12.
-
- static void RememberMe()
- {
- FCBPBRec pb;
- OSErr err;
-
- pb.ioCompletion = nil;
- pb.ioNamePtr = gOurName;
- pb.ioVRefNum = 0;
- pb.ioRefNum = CurResFile();
- pb.ioFCBIndx = 0;
-
- err = PBGetFCBInfoSync(&pb);
-
- gOurVRefNum = pb.ioFCBVRefNum;
- gOurDirID = pb.ioFCBParID;
- }
-
- // --------------------
- // InitAllPacks is called during the launching of an application. I take
- this
- // opportunity to re-open my INIT (since the system closes it after it was
- // called during boot-up time).
-
- static pascal void MyInitAllPacks(void)
- {
- SetUpA4();
-
- oldInitAllPacks();
-
- if (gMyRefNum == 0)
- OpenAndAddMe();
-
- RestoreA4();
- }
-
- // --------------------
- // Tricky routine that opens a resource file and places the resource map
- // BEHIND the system's. I want it behind the system resource file because I
- // want it available even if the program calls UseResFile(0). Doing it this
- // way also means that I only have to open the resource file once instead
- of
- // once per application.
-
- pascal short InlineHOpenResFile(short vRefNum,long dirID,ConstStr255Param
- fileName,
- char permission) = 0xA81A;
-
- static void OpenAndAddMe()
- {
- THz currentZone;
-
- short oldFile;
- short refNum;
- ResMapHandle current = nil;
- ResMapHandle previous = nil;
- ResMapHandle ourParent = nil;
- ResMapHandle us = nil;
- ResMapHandle system = nil;
-
- currentZone = GetZone();
- SetZone(SystemZone());
-
- oldFile = CurResFile();
- refNum = InlineHOpenResFile(gOurVRefNum, gOurDirID, gOurName, fsRdPerm);
- UseResFile(oldFile);
-
- if (refNum != -1) {
-
- current = (ResMapHandle) TopMapHndl;
-
- // First, find us (we should be on top)
-
- while ((current != nil) && ((**current).refNum != refNum)) {
- previous = current;
- current = (**current).nextMap;
- }
- if (current != nil) {
- ourParent = previous;
- us = current;
- }
-
- // Second, find the System
-
- system = (ResMapHandle) SysMapHndl;
-
- if ((us == nil) || (system == nil)) {
- CloseResFile(refNum);
- } else {
- if (ourParent != system) {
-
- //
- // Be sure to perform all these steps so that the
- // resource chain is never inconsistant or circular.
- // If that happens, debuggers like TMON will detonate.
- //
- if ((ResMapHandle) TopMapHndl == us)
- TopMapHndl = (void*) (**us).nextMap;
- if (ourParent)
- (**ourParent).nextMap = (**us).nextMap;
- (**us).nextMap = (**system).nextMap;
- (**system).nextMap = us;
- }
- gMyRefNum = refNum;
- }
- }
- SetZone(currentZone);
- }
-
-
- -----
- Keith Rollin
- Phantom Programmer
- Taligent, Inc.
-