+++ /dev/null
-/*
- File: MoreDesktopMgr.c
-
- Contains: A collection of useful high-level Desktop Manager routines.
- If the Desktop Manager is not available, use the Desktop file
- for 'read' operations.
-
- Version: MoreFiles
-
- Copyright: © 1992-2001 by Apple Computer, Inc., all rights reserved.
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- File Ownership:
-
- DRI: Apple Macintosh Developer Technical Support
-
- Other Contact: Apple Macintosh Developer Technical Support
- <http://developer.apple.com/bugreporter/>
-
- Technology: DTS Sample Code
-
- Writers:
-
- (JL) Jim Luther
- (NG) Nitin Ganatra
-
- Change History (most recent first):
-
- <2> 2/7/01 JL Added standard header. Updated names of includes. Updated
- various routines to use new calling convention of the
- MoreFilesExtras accessor functions.
- <1> 12/06/99 JL MoreFiles 1.5.
-*/
-
-#include <MacTypes.h>
-#include <MacErrors.h>
-#include <MacMemory.h>
-#include <Files.h>
-#include <Resources.h>
-#include <Icons.h>
-
-#define __COMPILINGMOREFILES
-
-#include "MoreFiles.h"
-#include "MoreFilesExtras.h"
-#include "Search.h"
-#include "MoreDesktopMgr.h"
-
-/*****************************************************************************/
-
-/* Desktop file notes:
-**
-** ¥ The Desktop file is owned by the Finder and is normally open by the
-** Finder. That means that we only have read-only access to the Desktop
-** file.
-** ¥ Since the Resource Manager doesn't support shared access to resource
-** files and we're using read-only access, we don't ever leave the
-** Desktop file open. We open a path to it, get the data we want out
-** of it, and then close the open path. This is the only safe way to
-** open a resource file with read-only access since some other program
-** could have it open with write access.
-** ¥ The bundle related resources in the Desktop file are normally
-** purgable, so when we're looking through them, we don't bother to
-** release resources we're done looking at - closing the resource file
-** (which we always do) will release them.
-** ¥ Since we can't assume the Desktop file is named "Desktop"
-** (it probably is everywhere but France), we get the Desktop
-** file's name by searching the volume's root directory for a file
-** with fileType == 'FNDR' and creator == 'ERIK'. The only problem with
-** this scheme is that someone could create another file with that type
-** and creator in the root directory and we'd find the wrong file.
-** The chances of this are very slim.
-*/
-
-/*****************************************************************************/
-
-/* local defines */
-
-enum
-{
- kBNDLResType = 'BNDL',
- kFREFResType = 'FREF',
- kIconFamResType = 'ICN#',
- kFCMTResType = 'FCMT',
- kAPPLResType = 'APPL'
-};
-
-/*****************************************************************************/
-
-/* local data structures */
-
-#if PRAGMA_STRUCT_ALIGN
-#pragma options align=mac68k
-#endif
-
-struct IDRec
-{
- short localID;
- short rsrcID;
-};
-typedef struct IDRec IDRec;
-typedef IDRec *IDRecPtr;
-
-struct BundleType
-{
- OSType type; /* 'ICN#' or 'FREF' */
- short count; /* number of IDRecs - 1 */
- IDRec idArray[1];
-};
-typedef struct BundleType BundleType;
-typedef BundleType *BundleTypePtr;
-
-struct BNDLRec
-{
- OSType signature; /* creator type signature */
- short versionID; /* version - should always be 0 */
- short numTypes; /* number of elements in typeArray - 1 */
- BundleType typeArray[1];
-};
-typedef struct BNDLRec BNDLRec;
-typedef BNDLRec **BNDLRecHandle;
-
-struct FREFRec
-{
- OSType fileType; /* file type */
- short iconID; /* icon local ID */
- Str255 fileName; /* file name */
-};
-typedef struct FREFRec FREFRec;
-typedef FREFRec **FREFRecHandle;
-
-struct APPLRec
-{
- OSType creator; /* creator type signature */
- long parID; /* parent directory ID */
- Str255 applName; /* application name */
-};
-typedef struct APPLRec APPLRec;
-typedef APPLRec *APPLRecPtr;
-
-#if PRAGMA_STRUCT_ALIGN
-#pragma options align=reset
-#endif
-
-/*****************************************************************************/
-
-/* static prototypes */
-
-static OSErr GetDesktopFileName(short vRefNum,
- Str255 desktopName);
-
-static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- short *applVRefNum,
- long *applParID,
- Str255 applName);
-
-static OSErr FindBundleGivenCreator(OSType creator,
- BNDLRecHandle *returnBndl);
-
-static OSErr FindTypeInBundle(OSType typeToFind,
- BNDLRecHandle theBndl,
- BundleTypePtr *returnBundleType);
-
-static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType,
- OSType fileType,
- short *iconLocalID);
-
-static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType,
- short iconLocalID,
- short *iconRsrcID);
-
-static OSType DTIconToResIcon(short iconType);
-
-static OSErr GetIconFromDesktopFile(ConstStr255Param volName,
- short vRefNum,
- short iconType,
- OSType fileCreator,
- OSType fileType,
- Handle *iconHandle);
-
-static OSErr GetCommentID(short vRefNum,
- long dirID,
- ConstStr255Param name,
- short *commentID);
-
-static OSErr GetCommentFromDesktopFile(short vRefNum,
- long dirID,
- ConstStr255Param name,
- Str255 comment);
-
-/*****************************************************************************/
-
-/*
-** GetDesktopFileName
-**
-** Get the name of the Desktop file.
-*/
-static OSErr GetDesktopFileName(short vRefNum,
- Str255 desktopName)
-{
- OSErr error;
- HParamBlockRec pb;
- short index;
- Boolean found;
-
- pb.fileParam.ioNamePtr = desktopName;
- pb.fileParam.ioVRefNum = vRefNum;
- pb.fileParam.ioFVersNum = 0;
- index = 1;
- found = false;
- do
- {
- pb.fileParam.ioDirID = fsRtDirID;
- pb.fileParam.ioFDirIndex = index;
- error = PBHGetFInfoSync(&pb);
- if ( error == noErr )
- {
- if ( (pb.fileParam.ioFlFndrInfo.fdType == 'FNDR') &&
- (pb.fileParam.ioFlFndrInfo.fdCreator == 'ERIK') )
- {
- found = true;
- }
- }
- ++index;
- } while ( (error == noErr) && !found );
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTOpen(ConstStr255Param volName,
- short vRefNum,
- short *dtRefNum,
- Boolean *newDTDatabase)
-{
- OSErr error;
- GetVolParmsInfoBuffer volParmsInfo;
- long infoSize;
- DTPBRec pb;
-
- /* Check for volume Desktop Manager support before calling */
- infoSize = sizeof(GetVolParmsInfoBuffer);
- error = HGetVolParms(volName, vRefNum, &volParmsInfo, &infoSize);
- if ( error == noErr )
- {
- if ( hasDesktopMgr(&volParmsInfo) )
- {
- pb.ioNamePtr = (StringPtr)volName;
- pb.ioVRefNum = vRefNum;
- error = PBDTOpenInform(&pb);
- /* PBDTOpenInform informs us if the desktop was just created */
- /* by leaving the low bit of ioTagInfo clear (0) */
- *newDTDatabase = ((pb.ioTagInfo & 1L) == 0);
- if ( error == paramErr )
- {
- error = PBDTGetPath(&pb);
- /* PBDTGetPath doesn't tell us if the database is new */
- /* so assume it is not new */
- *newDTDatabase = false;
- }
- *dtRefNum = pb.ioDTRefNum;
- }
- else
- {
- error = paramErr;
- }
- }
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** GetAPPLFromDesktopFile
-**
-** Get a application's location from the
-** Desktop file's 'APPL' resources.
-*/
-static OSErr GetAPPLFromDesktopFile(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- short *applVRefNum,
- long *applParID,
- Str255 applName)
-{
- OSErr error;
- short realVRefNum;
- Str255 desktopName;
- short savedResFile;
- short dfRefNum;
- Handle applResHandle;
- Boolean foundCreator;
- Ptr applPtr;
- long applSize;
-
- error = DetermineVRefNum(volName, vRefNum, &realVRefNum);
- if ( error == noErr )
- {
- error = GetDesktopFileName(realVRefNum, desktopName);
- if ( error == noErr )
- {
- savedResFile = CurResFile();
- /*
- ** Open the 'Desktop' file in the root directory. (because
- ** opening the resource file could preload unwanted resources,
- ** bracket the call with SetResLoad(s))
- */
- SetResLoad(false);
- dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm);
- SetResLoad(true);
-
- if ( dfRefNum != -1)
- {
- /* Get 'APPL' resource ID 0 */
- applResHandle = Get1Resource(kAPPLResType, 0);
- if ( applResHandle != NULL )
- {
- applSize = GetHandleSize((Handle)applResHandle);
- if ( applSize != 0 ) /* make sure the APPL resource isn't empty */
- {
- foundCreator = false;
- applPtr = *applResHandle;
-
- /* APPL's don't have a count so I have to use the size as the bounds */
- while ( (foundCreator == false) &&
- (applPtr < (*applResHandle + applSize)) )
- {
- if ( ((APPLRecPtr)applPtr)->creator == creator )
- {
- foundCreator = true;
- }
- else
- {
- /* fun with pointer math... */
- applPtr += sizeof(OSType) +
- sizeof(long) +
- ((APPLRecPtr)applPtr)->applName[0] + 1;
- /* application mappings are word aligned within the resource */
- if ( ((unsigned long)applPtr % 2) != 0 )
- {
- applPtr += 1;
- }
- }
- }
- if ( foundCreator == true )
- {
- *applVRefNum = realVRefNum;
- *applParID = ((APPLRecPtr)applPtr)->parID;
- BlockMoveData(((APPLRecPtr)applPtr)->applName,
- applName,
- ((APPLRecPtr)applPtr)->applName[0] + 1);
- /* error is already noErr */
- }
- else
- {
- error = afpItemNotFound; /* didn't find a creator match */
- }
- }
- else
- {
- error = afpItemNotFound; /* no APPL mapping available */
- }
- }
- else
- {
- error = afpItemNotFound; /* no APPL mapping available */
- }
-
- /* restore the resource chain and close the Desktop file */
- UseResFile(savedResFile);
- CloseResFile(dfRefNum);
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTXGetAPPL(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- Boolean searchCatalog,
- short *applVRefNum,
- long *applParID,
- Str255 applName)
-{
- OSErr error;
- UniversalFMPB pb;
- short dtRefNum;
- Boolean newDTDatabase;
- short realVRefNum;
- short index;
- Boolean applFound;
- FSSpec spec;
- long actMatchCount;
-
- /* get the real vRefNum */
- error = DetermineVRefNum(volName, vRefNum, &realVRefNum);
- if ( error == noErr )
- {
- error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase);
- if ( error == noErr )
- {
- if ( !newDTDatabase )
- {
- index = 0;
- applFound = false;
- do
- {
- pb.dtPB.ioNamePtr = applName;
- pb.dtPB.ioDTRefNum = dtRefNum;
- pb.dtPB.ioIndex = index;
- pb.dtPB.ioFileCreator = creator;
- error = PBDTGetAPPLSync(&pb.dtPB);
- if ( error == noErr )
- {
- /* got a match - see if it is valid */
-
- *applVRefNum = realVRefNum; /* get the vRefNum now */
- *applParID = pb.dtPB.ioAPPLParID; /* get the parent ID now */
-
- /* pb.hPB.fileParam.ioNamePtr is already set */
- pb.hPB.fileParam.ioVRefNum = realVRefNum;
- pb.hPB.fileParam.ioFVersNum = 0;
- pb.hPB.fileParam.ioDirID = *applParID;
- pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- if ( PBHGetFInfoSync(&pb.hPB) == noErr )
- {
- if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator == creator) &&
- (pb.hPB.fileParam.ioFlFndrInfo.fdType == 'APPL') )
- {
- applFound = true;
- }
- }
- }
- ++index;
- } while ( (error == noErr) && !applFound );
- if ( error != noErr )
- {
- error = afpItemNotFound;
- }
- }
- else
- {
- /* Desktop database is empty (new), set error to try CatSearch */
- error = afpItemNotFound;
- }
- }
- /* acceptable errors from Desktop Manager to continue are paramErr or afpItemNotFound */
- if ( error == paramErr )
- {
- /* if paramErr, the volume didn't support the Desktop Manager */
- /* try the Desktop file */
-
- error = GetAPPLFromDesktopFile(volName, vRefNum, creator,
- applVRefNum, applParID, applName);
- if ( error == noErr )
- {
- /* got a match - see if it is valid */
-
- pb.hPB.fileParam.ioNamePtr = applName;
- pb.hPB.fileParam.ioVRefNum = *applVRefNum;
- pb.hPB.fileParam.ioFVersNum = 0;
- pb.hPB.fileParam.ioDirID = *applParID;
- pb.hPB.fileParam.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */
- if ( PBHGetFInfoSync(&pb.hPB) == noErr )
- {
- if ( (pb.hPB.fileParam.ioFlFndrInfo.fdCreator != creator) ||
- (pb.hPB.fileParam.ioFlFndrInfo.fdType != 'APPL') )
- {
- error = afpItemNotFound;
- }
- }
- else if ( error == fnfErr )
- {
- error = afpItemNotFound;
- }
- }
- }
- /* acceptable error from DesktopFile code to continue is afpItemNotFound */
- if ( (error == afpItemNotFound) && searchCatalog)
- {
- /* Couldn't be found in the Desktop file either, */
- /* try searching with CatSearch if requested */
-
- error = CreatorTypeFileSearch(NULL, realVRefNum, creator, kAPPLResType, &spec, 1,
- &actMatchCount, true);
- if ( (error == noErr) || (error == eofErr) )
- {
- if ( actMatchCount > 0 )
- {
- *applVRefNum = spec.vRefNum;
- *applParID = spec.parID;
- BlockMoveData(spec.name, applName, spec.name[0] + 1);
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- }
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr FSpDTXGetAPPL(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- Boolean searchCatalog,
- FSSpec *spec)
-{
- return ( DTXGetAPPL(volName, vRefNum, creator, searchCatalog,
- &(spec->vRefNum), &(spec->parID), spec->name) );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTGetAPPL(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- short *applVRefNum,
- long *applParID,
- Str255 applName)
-{
- /* Call DTXGetAPPL with the "searchCatalog" parameter true */
- return ( DTXGetAPPL(volName, vRefNum, creator, true,
- applVRefNum, applParID, applName) );
-}
-
-/*****************************************************************************/
-
-pascal OSErr FSpDTGetAPPL(ConstStr255Param volName,
- short vRefNum,
- OSType creator,
- FSSpec *spec)
-{
- /* Call DTXGetAPPL with the "searchCatalog" parameter true */
- return ( DTXGetAPPL(volName, vRefNum, creator, true,
- &(spec->vRefNum), &(spec->parID), spec->name) );
-}
-
-/*****************************************************************************/
-
-/*
-** FindBundleGivenCreator
-**
-** Search the current resource file for the 'BNDL' resource with the given
-** creator and return a handle to it.
-*/
-static OSErr FindBundleGivenCreator(OSType creator,
- BNDLRecHandle *returnBndl)
-{
- OSErr error;
- short numOfBundles;
- short index;
- BNDLRecHandle theBndl;
-
- error = afpItemNotFound; /* default to not found */
-
- /* Search each BNDL resource until we find the one with a matching creator. */
-
- numOfBundles = Count1Resources(kBNDLResType);
- index = 1;
- *returnBndl = NULL;
-
- while ( (index <= numOfBundles) && (*returnBndl == NULL) )
- {
- theBndl = (BNDLRecHandle)Get1IndResource(kBNDLResType, index);
-
- if ( theBndl != NULL )
- {
- if ( (*theBndl)->signature == creator )
- {
- /* numTypes and typeArray->count will always be the actual count minus 1, */
- /* so 0 in both fields is valid. */
- if ( ((*theBndl)->numTypes >= 0) && ((*theBndl)->typeArray->count >= 0) )
- {
- /* got it */
- *returnBndl = theBndl;
- error = noErr;
- }
- }
- }
-
- index ++;
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** FindTypeInBundle
-**
-** Given a Handle to a BNDL return a pointer to the desired type
-** in it. If the type is not found, or if the type's count < 0,
-** return afpItemNotFound.
-*/
-static OSErr FindTypeInBundle(OSType typeToFind,
- BNDLRecHandle theBndl,
- BundleTypePtr *returnBundleType)
-{
- OSErr error;
- short index;
- Ptr ptrIterator; /* use a Ptr so we can do ugly pointer math */
-
- error = afpItemNotFound; /* default to not found */
-
- ptrIterator = (Ptr)((*theBndl)->typeArray);
- index = 0;
- *returnBundleType = NULL;
-
- while ( (index < ((*theBndl)->numTypes + 1)) &&
- (*returnBundleType == NULL) )
- {
- if ( (((BundleTypePtr)ptrIterator)->type == typeToFind) &&
- (((BundleTypePtr)ptrIterator)->count >= 0) )
- {
- *returnBundleType = (BundleTypePtr)ptrIterator;
- error = noErr;
- }
- else
- {
- ptrIterator += ( sizeof(OSType) +
- sizeof(short) +
- ( sizeof(IDRec) * (((BundleTypePtr)ptrIterator)->count + 1) ) );
- ++index;
- }
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** GetLocalIDFromFREF
-**
-** Given a pointer to a 'FREF' BundleType record, load each 'FREF' resource
-** looking for a matching fileType. If a matching fileType is found, return
-** its icon local ID. If no match is found, return afpItemNotFound as the
-** function result.
-*/
-static OSErr GetLocalIDFromFREF(BundleTypePtr theBundleType,
- OSType fileType,
- short *iconLocalID)
-{
- OSErr error;
- short index;
- IDRecPtr idIterator;
- FREFRecHandle theFref;
-
- error = afpItemNotFound; /* default to not found */
-
- /* For each localID in this type, get the FREF resource looking for fileType */
- index = 0;
- idIterator = &theBundleType->idArray[0];
- *iconLocalID = 0;
-
- while ( (index <= theBundleType->count) && (*iconLocalID == 0) )
- {
- theFref = (FREFRecHandle)Get1Resource(kFREFResType, idIterator->rsrcID);
- if ( theFref != NULL )
- {
- if ( (*theFref)->fileType == fileType )
- {
- *iconLocalID = (*theFref)->iconID;
- error = noErr;
- }
- }
-
- ++idIterator;
- ++index;
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** GetIconRsrcIDFromLocalID
-**
-** Given a pointer to a 'ICN#' BundleType record, look for the IDRec with
-** the localID that matches iconLocalID. If a matching IDRec is found,
-** return the IDRec's rsrcID field value. If no match is found, return
-** afpItemNotFound as the function result.
-*/
-static OSErr GetIconRsrcIDFromLocalID(BundleTypePtr theBundleType,
- short iconLocalID,
- short *iconRsrcID)
-{
- OSErr error;
- short index;
- IDRecPtr idIterator;
-
- error = afpItemNotFound; /* default to not found */
-
- /* Find the rsrcID of the icon family type, given the localID */
- index = 0;
- idIterator = &theBundleType->idArray[0];
- *iconRsrcID = 0;
-
- while ( (index <= theBundleType->count) && (*iconRsrcID == 0) )
- {
- if ( idIterator->localID == iconLocalID )
- {
- *iconRsrcID = idIterator->rsrcID;
- error = noErr;
- }
-
- idIterator ++;
- index ++;
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** DTIconToResIcon
-**
-** Map a Desktop Manager icon type to the corresponding resource type.
-** Return (OSType)0 if there is no corresponding resource type.
-*/
-static OSType DTIconToResIcon(short iconType)
-{
- OSType resType;
-
- switch ( iconType )
- {
- case kLargeIcon:
- resType = large1BitMask;
- break;
- case kLarge4BitIcon:
- resType = large4BitData;
- break;
- case kLarge8BitIcon:
- resType = large8BitData;
- break;
- case kSmallIcon:
- resType = small1BitMask;
- break;
- case kSmall4BitIcon:
- resType = small4BitData;
- break;
- case kSmall8BitIcon:
- resType = small8BitData;
- break;
- default:
- resType = (OSType)0;
- break;
- }
-
- return ( resType );
-}
-
-/*****************************************************************************/
-
-/*
-** GetIconFromDesktopFile
-**
-** INPUT a pointer to a non-existent Handle, because we'll allocate one
-**
-** search each BNDL resource for the right fileCreator and once we get it
-** find the 'FREF' type in BNDL
-** for each localID in the type, open the FREF resource
-** if the FREF is the desired fileType
-** get its icon localID
-** get the ICN# type in BNDL
-** get the icon resource number from the icon localID
-** get the icon resource type from the desktop mgr's iconType
-** get the icon of that type and number
-*/
-static OSErr GetIconFromDesktopFile(ConstStr255Param volName,
- short vRefNum,
- short iconType,
- OSType fileCreator,
- OSType fileType,
- Handle *iconHandle)
-{
- OSErr error;
- short realVRefNum;
- Str255 desktopName;
- short savedResFile;
- short dfRefNum;
- BNDLRecHandle theBndl = NULL;
- BundleTypePtr theBundleType;
- short iconLocalID;
- short iconRsrcID;
- OSType iconRsrcType;
- Handle returnIconHandle;
- char bndlState;
-
- *iconHandle = NULL;
-
- error = DetermineVRefNum(volName, vRefNum, &realVRefNum);
- if ( error == noErr )
- {
- error = GetDesktopFileName(realVRefNum, desktopName);
- if ( error == noErr )
- {
- savedResFile = CurResFile();
-
- /*
- ** Open the 'Desktop' file in the root directory. (because
- ** opening the resource file could preload unwanted resources,
- ** bracket the call with SetResLoad(s))
- */
- SetResLoad(false);
- dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm);
- SetResLoad(true);
-
- if ( dfRefNum != -1 )
- {
- /*
- ** Find the BNDL resource with the specified creator.
- */
- error = FindBundleGivenCreator(fileCreator, &theBndl);
- if ( error == noErr )
- {
- /* Lock the BNDL resource so it won't be purged when other resources are loaded */
- bndlState = HGetState((Handle)theBndl);
- HLock((Handle)theBndl);
-
- /* Find the 'FREF' BundleType record in the BNDL resource. */
- error = FindTypeInBundle(kFREFResType, theBndl, &theBundleType);
- if ( error == noErr )
- {
- /* Find the local ID in the 'FREF' resource with the specified fileType */
- error = GetLocalIDFromFREF(theBundleType, fileType, &iconLocalID);
- if ( error == noErr )
- {
- /* Find the 'ICN#' BundleType record in the BNDL resource. */
- error = FindTypeInBundle(kIconFamResType, theBndl, &theBundleType);
- if ( error == noErr )
- {
- /* Find the icon's resource ID in the 'ICN#' BundleType record */
- error = GetIconRsrcIDFromLocalID(theBundleType, iconLocalID, &iconRsrcID);
- if ( error == noErr )
- {
- /* Map Desktop Manager icon type to resource type */
- iconRsrcType = DTIconToResIcon(iconType);
-
- if ( iconRsrcType != (OSType)0 )
- {
- /* Load the icon */
- returnIconHandle = Get1Resource(iconRsrcType, iconRsrcID);
- if ( returnIconHandle != NULL )
- {
- /* Copy the resource handle, and return the copy */
- HandToHand(&returnIconHandle);
- if ( MemError() == noErr )
- {
- *iconHandle = returnIconHandle;
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- }
- }
- }
- }
- /* Restore the state of the BNDL resource */
- HSetState((Handle)theBndl, bndlState);
- }
- /* Restore the resource chain and close the Desktop file */
- UseResFile(savedResFile);
- CloseResFile(dfRefNum);
- }
- else
- {
- error = ResError(); /* could not open Desktop file */
- }
- }
- if ( (error != noErr) && (error != memFullErr) )
- {
- error = afpItemNotFound; /* force an error we should return */
- }
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTGetIcon(ConstStr255Param volName,
- short vRefNum,
- short iconType,
- OSType fileCreator,
- OSType fileType,
- Handle *iconHandle)
-{
- OSErr error;
- DTPBRec pb;
- short dtRefNum;
- Boolean newDTDatabase;
- Size bufferSize;
-
- *iconHandle = NULL;
- error = DTOpen(volName, vRefNum, &dtRefNum, &newDTDatabase);
- if ( error == noErr )
- {
- /* there was a desktop database and it's now open */
-
- if ( !newDTDatabase ) /* don't bother to look in a new (empty) database */
- {
- /* get the buffer size for the requested icon type */
- switch ( iconType )
- {
- case kLargeIcon:
- bufferSize = kLargeIconSize;
- break;
- case kLarge4BitIcon:
- bufferSize = kLarge4BitIconSize;
- break;
- case kLarge8BitIcon:
- bufferSize = kLarge8BitIconSize;
- break;
- case kSmallIcon:
- bufferSize = kSmallIconSize;
- break;
- case kSmall4BitIcon:
- bufferSize = kSmall4BitIconSize;
- break;
- case kSmall8BitIcon:
- bufferSize = kSmall8BitIconSize;
- break;
- default:
- iconType = 0;
- bufferSize = 0;
- break;
- }
- if ( bufferSize != 0 )
- {
- *iconHandle = NewHandle(bufferSize);
- if ( *iconHandle != NULL )
- {
- HLock(*iconHandle);
-
- pb.ioDTRefNum = dtRefNum;
- pb.ioTagInfo = 0;
- pb.ioDTBuffer = **iconHandle;
- pb.ioDTReqCount = bufferSize;
- pb.ioIconType = iconType;
- pb.ioFileCreator = fileCreator;
- pb.ioFileType = fileType;
- error = PBDTGetIconSync(&pb);
-
- HUnlock(*iconHandle);
-
- if ( error != noErr )
- {
- DisposeHandle(*iconHandle); /* dispose of the allocated memory */
- *iconHandle = NULL;
- }
- }
- else
- {
- error = memFullErr; /* handle could not be allocated */
- }
- }
- else
- {
- error = paramErr; /* unknown icon type requested */
- }
- }
- else
- {
- error = afpItemNotFound; /* the desktop database was empty - nothing to return */
- }
- }
- else
- {
- /* There is no desktop database - try the Desktop file */
-
- error = GetIconFromDesktopFile(volName, vRefNum, iconType,
- fileCreator, fileType, iconHandle);
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTSetComment(short vRefNum,
- long dirID,
- ConstStr255Param name,
- ConstStr255Param comment)
-{
- DTPBRec pb;
- OSErr error;
- short dtRefNum;
- Boolean newDTDatabase;
-
- error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
- if ( error == noErr )
- {
- pb.ioDTRefNum = dtRefNum;
- pb.ioNamePtr = (StringPtr)name;
- pb.ioDirID = dirID;
- pb.ioDTBuffer = (Ptr)&comment[1];
- /* Truncate the comment to 200 characters just in case */
- /* some file system doesn't range check */
- if ( comment[0] <= 200 )
- {
- pb.ioDTReqCount = comment[0];
- }
- else
- {
- pb.ioDTReqCount = 200;
- }
- error = PBDTSetCommentSync(&pb);
- }
- return (error);
-}
-
-/*****************************************************************************/
-
-pascal OSErr FSpDTSetComment(const FSSpec *spec,
- ConstStr255Param comment)
-{
- return (DTSetComment(spec->vRefNum, spec->parID, spec->name, comment));
-}
-
-/*****************************************************************************/
-
-/*
-** GetCommentID
-**
-** Get the comment ID number for the Desktop file's 'FCMT' resource ID from
-** the file or folders fdComment (frComment) field.
-*/
-static OSErr GetCommentID(short vRefNum,
- long dirID,
- ConstStr255Param name,
- short *commentID)
-{
- CInfoPBRec pb;
- OSErr error;
-
- error = GetCatInfoNoName(vRefNum, dirID, name, &pb);
- *commentID = pb.hFileInfo.ioFlXFndrInfo.fdComment;
- return ( error );
-}
-
-/*****************************************************************************/
-
-/*
-** GetCommentFromDesktopFile
-**
-** Get a file or directory's Finder comment field (if any) from the
-** Desktop file's 'FCMT' resources.
-*/
-static OSErr GetCommentFromDesktopFile(short vRefNum,
- long dirID,
- ConstStr255Param name,
- Str255 comment)
-{
- OSErr error;
- short commentID;
- short realVRefNum;
- Str255 desktopName;
- short savedResFile;
- short dfRefNum;
- StringHandle commentHandle;
-
- /* Get the comment ID number */
- error = GetCommentID(vRefNum, dirID, name, &commentID);
- if ( error == noErr )
- {
- if ( commentID != 0 ) /* commentID == 0 means there's no comment */
- {
- error = DetermineVRefNum(name, vRefNum, &realVRefNum);
- if ( error == noErr )
- {
- error = GetDesktopFileName(realVRefNum, desktopName);
- if ( error == noErr )
- {
- savedResFile = CurResFile();
- /*
- ** Open the 'Desktop' file in the root directory. (because
- ** opening the resource file could preload unwanted resources,
- ** bracket the call with SetResLoad(s))
- */
- SetResLoad(false);
- dfRefNum = HOpenResFile(realVRefNum, fsRtDirID, desktopName, fsRdPerm);
- SetResLoad(true);
-
- if ( dfRefNum != -1)
- {
- /* Get the comment resource */
- commentHandle = (StringHandle)Get1Resource(kFCMTResType,commentID);
- if ( commentHandle != NULL )
- {
- if ( GetHandleSize((Handle)commentHandle) > 0 )
- {
- BlockMoveData(*commentHandle, comment, *commentHandle[0] + 1);
- }
- else
- {
- error = afpItemNotFound; /* no comment available */
- }
- }
- else
- {
- error = afpItemNotFound; /* no comment available */
- }
-
- /* restore the resource chain and close the Desktop file */
- UseResFile(savedResFile);
- CloseResFile(dfRefNum);
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- else
- {
- error = afpItemNotFound;
- }
- }
- }
- else
- {
- error = afpItemNotFound; /* no comment available */
- }
- }
-
- return ( error );
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTGetComment(short vRefNum,
- long dirID,
- ConstStr255Param name,
- Str255 comment)
-{
- DTPBRec pb;
- OSErr error;
- short dtRefNum;
- Boolean newDTDatabase;
-
- if (comment != NULL)
- {
- comment[0] = 0; /* return nothing by default */
-
- /* attempt to open the desktop database */
- error = DTOpen(name, vRefNum, &dtRefNum, &newDTDatabase);
- if ( error == noErr )
- {
- /* There was a desktop database and it's now open */
-
- if ( !newDTDatabase )
- {
- pb.ioDTRefNum = dtRefNum;
- pb.ioNamePtr = (StringPtr)name;
- pb.ioDirID = dirID;
- pb.ioDTBuffer = (Ptr)&comment[1];
- /*
- ** IMPORTANT NOTE #1: Inside Macintosh says that comments
- ** are up to 200 characters. While that may be correct for
- ** the HFS file system's Desktop Manager, other file
- ** systems (such as Apple Photo Access) return up to
- ** 255 characters. Make sure the comment buffer is a Str255
- ** or you'll regret it.
- **
- ** IMPORTANT NOTE #2: Although Inside Macintosh doesn't
- ** mention it, ioDTReqCount is a input field to
- ** PBDTGetCommentSync. Some file systems (like HFS) ignore
- ** ioDTReqCount and always return the full comment --
- ** others (like AppleShare) respect ioDTReqCount and only
- ** return up to ioDTReqCount characters of the comment.
- */
- pb.ioDTReqCount = sizeof(Str255) - 1;
- error = PBDTGetCommentSync(&pb);
- if (error == noErr)
- {
- comment[0] = (unsigned char)pb.ioDTActCount;
- }
- }
- }
- else
- {
- /* There is no desktop database - try the Desktop file */
- error = GetCommentFromDesktopFile(vRefNum, dirID, name, comment);
- if ( error != noErr )
- {
- error = afpItemNotFound; /* return an expected error */
- }
- }
- }
- else
- {
- error = paramErr;
- }
-
- return (error);
-}
-
-/*****************************************************************************/
-
-pascal OSErr FSpDTGetComment(const FSSpec *spec,
- Str255 comment)
-{
- return (DTGetComment(spec->vRefNum, spec->parID, spec->name, comment));
-}
-
-/*****************************************************************************/
-
-pascal OSErr DTCopyComment(short srcVRefNum,
- long srcDirID,
- ConstStr255Param srcName,
- short dstVRefNum,
- long dstDirID,
- ConstStr255Param dstName)
-/* The destination volume must support the Desktop Manager for this to work */
-{
- OSErr error;
- Str255 comment;
-
- error = DTGetComment(srcVRefNum, srcDirID, srcName, comment);
- if ( (error == noErr) && (comment[0] > 0) )
- {
- error = DTSetComment(dstVRefNum, dstDirID, dstName, comment);
- }
- return (error);
-}
-
-/*****************************************************************************/
-
-pascal OSErr FSpDTCopyComment(const FSSpec *srcSpec,
- const FSSpec *dstSpec)
-/* The destination volume must support the Desktop Manager for this to work */
-{
- return (DTCopyComment(srcSpec->vRefNum, srcSpec->parID, srcSpec->name,
- dstSpec->vRefNum, dstSpec->parID, dstSpec->name));
-}
-
-/*****************************************************************************/