]> git.saurik.com Git - wxWidgets.git/blobdiff - src/mac/morefile/MoreDesk.cpp
latest CW additions
[wxWidgets.git] / src / mac / morefile / MoreDesk.cpp
diff --git a/src/mac/morefile/MoreDesk.cpp b/src/mac/morefile/MoreDesk.cpp
new file mode 100644 (file)
index 0000000..74a59fd
--- /dev/null
@@ -0,0 +1,1254 @@
+/*
+**     Apple Macintosh Developer Technical Support
+**
+**     A collection of useful high-level Desktop Manager routines.
+**     If the Desktop Manager isn't available, use the Desktop file
+**     for 'read' operations.
+**
+**     We do more because we can...
+**
+**     by Jim Luther and Nitin Ganatra, Apple Developer Technical Support Emeriti
+**
+**     File:   MoreDesktopMgr.c
+**
+**     Copyright © 1992-1998 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.
+*/
+
+#include <Types.h>
+#include <Errors.h>
+#include <Memory.h>
+#include <Files.h>
+#include <Resources.h>
+#include <Icons.h>
+
+#define        __COMPILINGMOREFILES
+
+#include "MoreFile.h"
+#include "MoreExtr.h"
+#include "Search.h"
+#include "MoreDesk.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_ALIGN_SUPPORTED
+#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_ALIGN_SUPPORTED
+#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 = InlineGetHandleSize((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 ( InlineGetHandleSize((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));
+}
+
+/*****************************************************************************/