From: keith@taligent.com (Keith Rollin)
Subject: Re: Problem writing INIT/cdev
Organization: Taligent
Distribution: comp
Date: Thu, 3 Sep 1992 20:08:55 GMT

In article <Sep.3.01.53.43.1992.13837@math.rutgers.edu>,
landwebe@math.rutgers.edu (Peter Landweber) writes:
> 
> 
> 
>      I am working on an INIT/cdev combination to be used under System
> 7, and I've run into a problem.
>      At startup time, the INIT moves its resource map after the system
> resource map in the linked list, and it patches CloseResFile() to
> ignore the file.  The result is that my file stays open, and its
> resources are always available.  This is similar to what Suitcase II
> does with font suitcases.  So far everything has gone extremely well 
> using this technique.
>      Now, I'm trying to add a "cdev".  The problem is that when the
> finder opens up my file as a Control Panel, it expects my file's
> resource map to be the first in the linked list.  Since the resource
> map is actually at the end of the linked list, the finder crashes.
> 
> So, my questions are:
> 1)  Is there a way for the Finder to open up a Control Panel if the
> file is already open, and its resource map is not at the front of the
> linked list?
> 2)  Is there a way to open a file twice, with two separate resource
> maps?  That way, I could still have one resource map linked after the
> system resource map, and the other at the front of the linked list.
> One of the maps could be read-only if necessary.

I have an INIT/cdev that does the same thing. However, it takes a little
different approach than yours, and it seems to work.

First, I don't patch CloseResFile() to keep my file open. Instead, at INIT time,
I install my code, remember the file I came from, and patch InitAllPacks(). I
remember my file of origin with the following routine.


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;
}


I patch InitAllPacks() so that I can re-open my resource fork just before the
first application is run:


static pascal void	MyInitAllPacks(void)
{
	SetUpA4();
	
	oldInitAllPacks();
	
	if (gMyRefNum == 0)
		OpenAndAddMe();
		
	RestoreA4();
}


OpenAndAddMe() opens the resource fork and shuffles it behind the System file:


typedef struct ResourceMap{
	long		dataOffset;
	long		mapOffset;
	long		dataLength;
	long		mapLength;
	struct ResourceMap	**nextMap;
	short		refNum;
	short		attributes;
	short		typesOffset;
	short		namesOffset;
} ResourceMap, *ResMapPtr, **ResMapHandle;

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);
}

I've checked the resource chain with this setup, and my INIT/cdev file appears
to get opened twice when the cdev is opened.

Hope this helps,

--
Keith Rollin
Phantom Programmer
Taligent, Inc.