[comp.sys.mac.programmer] out to do PBCatSearch based on type/creator

jyp@wucs1.wustl.edu (Jerome Yvon Plun) (06/18/91)

I am trying to use PBCatSearch to find an application based on its type
('APPL') and creator.  I set ioSearchBits to fsSBFlFndrInfo, create an
appropriate Finder Info record to put in ioSearchInfo1.ioFlFndrInfo and
create another Finder Info record that I stuff with 0's except for the
fields fsType and fsCreator (both set to all 1's) to use as a mask with
ioSearchInfo2.ioFlFndrInfo.
But PBCatSearch seems to return with the first application it finds.

If I use the same setup but search based on the full name of the application,
PBCatSearch finds it correctly (and quickly too!).

Can someone clarify what Apple means by "using fields to hold masks that 
specify which bits are relevant" (last paragraph p 25-20)?

Thanks.  Jerome

Jerome Plun            []  Is it a crime to want something else?
jyp@wucs1.wustl.edu    []  Is it a crime to believe in something different?
Washington University  []  
St Louis, MO           []  "Smalltown England", New Model Army, Vengeance

casseres@apple.com (David Casseres) (06/22/91)

In article <1991Jun18.032741.24056@cec1.wustl.edu>, jyp@wucs1.wustl.edu (Jerome Yvon Plun) writes:
> 
> I am trying to use PBCatSearch to find an application based on its type
> ('APPL') and creator.  I set ioSearchBits to fsSBFlFndrInfo, create an
> appropriate Finder Info record to put in ioSearchInfo1.ioFlFndrInfo and
> create another Finder Info record that I stuff with 0's except for the
> fields fsType and fsCreator (both set to all 1's) to use as a mask with
> ioSearchInfo2.ioFlFndrInfo.
> But PBCatSearch seems to return with the first application it finds.

I found the documentation a bit confusing, so maybe it will be worthwhile
to post the C++ code I finally wound up with after some trial and error,
and which works.  I make no claims as to elegance, performance, etc. (If
you know C but not C++, don't let it scare you.)

The Scan_Volume function scans a specified volume for unlocked files with
type myFavoriteType and creator myFavoriteCreator.  It makes repeated
calls to PBCatSearch until eofErr is returned to indicate the volume has
been exhausted; each call is limited to 10 hits and to 10 milliseconds.
After each call something (not shown) is done with the information
returned by PBCatSearch.

Also, before and after each PBCatSearch call it calls the CheckCancel
function (not shown) which calls the main event loop so that the system
response will not be frozen while the scan is in progress.  CheckCancel
returns true if the user does something that should cause the scan to be
canceled (such as quitting the application).

Boolean Sniffer7::Scan_Volume (short volRefNum)
	
	{
		OSErr						err;
		short						ix;
		Boolean				doneWithVol = false;

		//Number of matches requested on each pass
		short const			kMaxMatches = 10;
		
		//Array of matches from current pass
		FSSpec					theResults[kMaxMatches];
		
		//Scratch buffer for PBCatSearch
		long const			kBufferSize = 1000;
		Handle					hBuffer = NewHandle(kBufferSize);
		
		//Param block for PBCatSearch
		CSParamPtr			catSearchPB = (CSParamPtr)NewPtrClear(sizeof(CSParam));
		
		//PBCatSearch weirdness: a CInfo block to contain (the way we're
		//doing things) the values we want to match
		CInfoPBPtr			spec1 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
		
		//More PBCatSearch weirdness: a 2nd param block to mask the parts
		//of the 1st CInfo block that we consider significant
		CInfoPBPtr			spec2 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
				
		while ((!doneWithVol) && (!CheckCancel()))
			{
			//Every time, make sure the necessary fields are re-inited.
				catSearchPB->ioCompletion = nil;
				catSearchPB->ioNamePtr = nil;
				catSearchPB->ioVRefNum = volRefNum;
				catSearchPB->ioMatchPtr = theResults;
				catSearchPB->ioReqMatchCount = kMaxMatches;
				catSearchPB->ioActMatchCount = 0;
				catSearchPB->ioSearchBits = fsSBFlAttrib + fsSBFlFndrInfo;
				catSearchPB->ioSearchInfo1 = spec1;
				catSearchPB->ioSearchInfo2 = spec2;
				catSearchPB->ioSearchTime = 100;									//10 ms
				HLock(hBuffer);
				catSearchPB->ioOptBuffer = *hBuffer;
				catSearchPB->ioOptBufSize = kBufferSize;
				
				spec1->hFileInfo.ioFlAttrib = 0x00;								//no locked files or dirs
				spec1->hFileInfo.ioFlFndrInfo.fdType = myFavoriteType;
				spec1->hFileInfo.ioFlFndrInfo.fdCreator = myFavoriteCreator;
				
				spec2->hFileInfo.ioFlAttrib = 0x11;										//bits 0 & 4
				spec2->hFileInfo.ioFlFndrInfo.fdType = 0xFFFFFFFF;		//all bits of this field
				spec2->hFileInfo.ioFlFndrInfo.fdCreator = 0xFFFFFFFF;	//all bits of this field
				
				//Call PBCatSearch.  It returns eofErr when it has finished the volume
				//successfully.
				err = PBCatSearchSync(catSearchPB);
				HUnlock(hBuffer);
				if (err && (err != eofErr)) break;
				
				doneWithVol = (err == eofErr);
				if ((!err || doneWithVol) && (catSearchPB->ioActMatchCount > 0))
					for (ix = 0; ix < catSearchPB->ioActMatchCount; ix++)
						{
							if (CheckCancel()) break;
							//Do something useful with theResults[ix]
						}
			}
		DisposPtr((Ptr)spec1);
		DisposPtr((Ptr)spec2);
		DisposPtr((Ptr)catSearchPB);
		DisposHandle(hBuffer);
		return true;
	}

zben@ni.umd.edu (Ben Cranston) (06/28/91)

I'm hacking up MacTCP's dnr.c routine to handle all four permutations of
System 6/7 and MacTCP 1.0.2/1.1b1 and got this code to work for finding
the MacTCP file in the Control Panels folder in order to find the dnrp
resource.  BTW System 6.0.7 vs MacTCP 1.1b1 seems to destroy the system
file fairly reliably on a Mac SE I'm using for testing.

Throw away the GetCPanelFolder subroutine and substitute these two routines
for the existing OpenOurRF routine:


/* FindFile is used to search Sys7 folder for file with specific signature */

short FindFile(FSSpec *myFSS, OSType mytype, OSType mycreator)
{
	CSParam find;
	CInfoPBRec spec1, spec2;
	short err;

	find.ioNamePtr = nil;
	find.ioVRefNum = myFSS->vRefNum;
	find.ioMatchPtr = myFSS;
	find.ioReqMatchCount = 1;
	find.ioSearchBits =
		fsSBFlAttrib + fsSBFlFndrInfo + fsSBFlParID;
	find.ioSearchInfo1 = &spec1;
	find.ioSearchInfo2 = &spec2;
	find.ioSearchTime = 0;
	find.ioCatPosition.initialize = 0;
	find.ioOptBuffer = nil;
	find.ioOptBufSize = 0;
	spec1.hFileInfo.ioFlAttrib = 0;
	spec2.hFileInfo.ioFlAttrib = 0x10;
	spec1.hFileInfo.ioFlFndrInfo.fdType = mytype;
	spec1.hFileInfo.ioFlFndrInfo.fdCreator = mycreator;
	spec2.hFileInfo.ioFlFndrInfo.fdType = 0xFFFFFFFF;
	spec2.hFileInfo.ioFlFndrInfo.fdCreator = 0xFFFFFFFF;
	spec2.hFileInfo.ioFlFndrInfo.fdFlags = 0x0000;
	spec2.hFileInfo.ioFlFndrInfo.fdLocation.h = 0x0000;
	spec2.hFileInfo.ioFlFndrInfo.fdLocation.v = 0x0000;
	spec2.hFileInfo.ioFlFndrInfo.fdFldr = 0x0000;
	spec1.hFileInfo.ioFlParID = myFSS->parID;
	spec2.hFileInfo.ioFlParID = myFSS->parID;	/* ???? */
	err = PBCatSearch(&find,false);
	if (0 < find.ioActMatchCount)
		return(0);
	return(fnfErr);
}


/* OpenOurRF is called to open the MacTCP driver resources */

short OpenOurRF()
{
	Boolean isFolder, wasAlias;
	SysEnvRec info;
	Boolean hasFolderMgr;
	long feature;
	FSSpec myFSS;
	ParamBlockRec fi;
	
	hasFolderMgr = ( TrapAvailable(_GestaltDispatch) &&
			 (noErr==Gestalt(gestaltFindFolderAttr,&feature)) );

	if (hasFolderMgr) {
		if ( FindFolder(kOnSystemDisk, kControlPanelFolderType,
		       kDontCreateFolder, &myFSS.vRefNum, &myFSS.parID
		   ) != noErr)
			return(-1);
		if (noErr != FindFile(&myFSS,'cdev','ztcp'))
			if (noErr != FindFile(&myFSS,'cdev','mtcp'))
				return(-1);
		if (noErr != ResolveAliasFile(&myFSS,true,&isFolder,&wasAlias))
			return(-1);
		return( FSpOpenResFile(&myFSS, fsRdPerm) );
	} else {
		SysEnvirons(1, &info);
		fi.fileParam.ioVRefNum = info.sysVRefNum;
		fi.fileParam.ioNamePtr = &myFSS.name;
		fi.fileParam.ioFDirIndex = 1;	
		while (noErr == PBGetFInfo(&fi,false) ) {
			/* scan sys folder for files of MacTCP type & creator */
			if (fi.fileParam.ioFlFndrInfo.fdType == 'cdev' &&
			    (fi.fileParam.ioFlFndrInfo.fdCreator == 'ztcp' ||
			     fi.fileParam.ioFlFndrInfo.fdCreator == 'mtcp') )
				/* found the MacTCP driver file */
				return( OpenRFPerm(&myFSS.name,info.sysVRefNum,
					fsRdPerm) );
			/* check next file in system folder */
			fi.fileParam.ioFDirIndex++;
		}
	}
	
	return(-1);
}	

I wasn't quite sure what to put into spec2.hFileInfo.ioFlParID for a
parent-ID search.  IM VI was silent on if this is a high-low range, a mask
or it is just ignored.  Anybody from Apple want to comment on this????

DE KA3ZDF K