Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Notes > Legacy Documents > Carbon >

Legacy Documentclose button

Important: This document is part of the Legacy section of the ADC Reference Library. This information should not be used for new development.

Current information on this Reference Library topic can be found here:

File Manager Directory Handling Q&As

CONTENTS

This Technical Note contains a collection of archived Q&As relating to a specific topic--questions sent the Developer Support Center (DSC) along with answers from the DSC engineers. Current Q&As can be found on the Macintosh Technical Q&As web site.

[Oct 01 1990]






Back to top

Implementing Macintosh System 7 desktop button

Date Written: 6/22/92

Last reviewed: 6/14/93

We would like to know how to implement a desktop button under System 7 in a dialog other than the standard system Open dialog. Is there an easy way to find the mounted volumes and their icons and the files that are located on the desktop?

___

The items shown at the desktop level by Standard File are the mounted volumes and all items inside the invisible directory named Desktop Folder at the root of the volume. You can find out what items are in the desktop folder by using PBGetCatInfo to enumerate the items in that directory. (For sample code showing the basic technique of indexing through the entries in a directory, see the Macintosh Technical Note "Searching All Directories on an HFS Volume.")

To get a list of volumes, you need to index through the list of volumes with PBHGetVInfo. The snippet code below shows how to do that. To get the icon associated with a specific volume, you need to make control call #21 to the volume's disk driver as documented on page V-470 of Inside Macintosh Volume V. The function GetDiskDriverInfo below shows the proper way to make the control call and safely return the icon and where string (the string that shows where a volume is in the Finder's Get Info dialog box).

FUNCTION GetDiskDriverInfo (driveNumber: Integer;
                                driverRefNum: Integer;
                                VAR iconHandle: Handle;
                                VAR whereString: Str255): OSErr;
VAR
    err: OSerr;
    pb: ParamBlockRec;
BEGIN
    iconHandle := NewHandle(kLargeIconSize);
    IF iconHandle = NIL THEN
        BEGIN    { bail out if memory couldn't be allocated }
            GetDiskDriverInfo := MemError;
            Exit(GetDiskDriverInfo);
        END;

    { get the disk driver info }
    WITH pb DO
        BEGIN
            ioVRefNum := driveNumber;
            ioRefNum := driverRefNum;
            csCode := 21;
        END;
    err := PBControlSync(@pb);
    IF err = noErr THEN
        BEGIN    { no error? then return the info }
            { move the icon into it }
            BlockMove(pb.ioMisc, iconHandle^, kLargeIconSize);

            { copy where information string into a string variable }
            whereString := StringPtr(ORD4(pb.ioMisc) + $100)^;
        END
    ELSE
        BEGIN    { error? then clean up and return no info }
            DisposHandle(iconHandle);
            iconHandle := NIL;
            whereString := '';
        END;
    GetDiskDriverInfo := err;
END;

Here's how you index through the list of volumes to get their names and
how to call the GetDiskDriverInfo function above to get the icon and
"where" string.

VAR
    hPB: HParamBlockRec;
    err: OSerr;
    dErr: OSErr;
    index: Integer;
    gVolName: Str255;
    gIconHandle: Handle;
    gWhereString: Str255;

BEGIN
    index := 1;
    REPEAT
        WITH hPB DO
            BEGIN
                ioNamePtr := @gVolName;
                ioVolIndex := index;
            END;
        err := PBHGetVInfoSync(@hPB);
        IF err = noErr THEN
            BEGIN
                dErr := GetDiskDriverInfo(hPB.ioVDrvInfo, hPB.ioVDRefNum,
                                          gIconHandle, gWhereString);
                IF dErr = noErr THEN
                    BEGIN
               { Do something with the volume name, icon, and where string. }
               { Don't forget to dispose the gIconHandle handle when you're }
               { done with the icon. }
                    END;
            END;
        index := index + 1;
    UNTIL err <> noErr;
END.

If you want to get fancy, you can use the custom icon attacted to some files (for example, alias files to AppleShare volumes). Chapter 9 of Inside Macintosh Volume VI talks about custom icons and alias files on pages 9-28 through 9-32. You can tell if a file or directory has a custom icon by looking at the hasCustomIcon bit in the fdFlags word of the FInfo record returned by PBGetCatInfo (which you call to build the list of files and folders).

Back to top

System 7 and copy-protect bit

Date Written: 4/26/90

Last reviewed: 6/14/93

I need to prevent users from copying my application off a volume. Is there a new equivalent of the old Bozo bit?

___

The Bozo or NoCopy bit was bit 11 in the fdFlags word of the FInfo record. As noted in the Macintosh Technical Note "Finder Flags," this bit hasn't been used for that purpose since System 5. In fact, System 7 reused bit 11 for the isStationery bit. (See Inside Macintosh Volume VI, pages 9-36 and 9-37, for the current list of Finder flag bits.)

There isn't an equivalent of the Bozo bit. However, the System 7 Finder won't copy files that have the copy-protect bit (bit 6) set in the ioFlAttrib field returned by the PBGetCatInfo function. However, the bits in the ioFlAttrib field can't be changed with the PBSetCatInfo function. Instead, they're used to report the state of things set by other parts of the file system.

The copy-protect bit is set by the AppleShare external file system when it finds that a file's copy-protect bit is returned by an AppleTalk Filing Protocol file server. The AppleShare external file system is the only file system we know of that sets the copy-protect bit. There's no way to make the local file system set the copy-protect bit for volumes it controls.

Back to top

How persistent must Macintosh directory IDs be?

Date Date Written: 8/28/92

Last reviewed: 11/1/92

How persistent must directory IDs be? In our external file system, directory IDs are generated starting from fsRtDirID whenever a volume is mounted. When one of our volumes is unmounted and then remounted without rebooting the Macintosh in between, the Finder immediately does a GetCatInfo specifying a directory ID (5, I think it's looking for the Trash folder). This would imply that directory IDs need to persist across dismounts. Is this the case? Is there any way to get the Finder to forget the directory IDs it has stored, besides rebooting?

___

The Macintosh file system only expects directory ID numbers to be fixed while the volume is mounted.

However, other parts of the Macintosh operating system (for example, the Alias Manager and the Finder) and applications expect directory IDs to persist between volume mounts so that they can find a particular directory when a volume is remounted. For example, under System 6, the correct way to store the location of a file is by saving the volume name, the volume's creation date (to help find the volume in the case where it is renamed), and the parent directory ID number. The Alias Manager under System 7 (and under System 6 when QuickTime is installed) uses the same technique when it creates an alias to a file or directory.

The Finder keeps the directory ID numbers of the directories it can find with the FindFolder function in the volume's FndrInfo record, so that's why you're seeing the Finder look for a particular directory ID.

Back to top

Getting folder directory ID based on path name or parent folder

Date Written: 4/26/90

Last reviewed: 6/14/93

Is there any Macintosh routine that gets the directory ID of a folder based on

the path name? How about if I know the parent folder's directory ID?

___

You can call PBGetCatInfo with ioFDirIndex set to zero to get the directory ID of a folder based on the path name. Call PBHGetVInfo to find its vRefNum.

You can also call PBGetCatInfo to get a folder's dirID based on its name and its parent's dirID and vRefNum. Here's an example:

{ given a folder's name, vRefNum, and parent dirID, find its dirID }
FUNCTION GetFolderDirID (parentFolderVRefNum: Integer;
                         parentFolderDirID: LongInt; folderName: Str63;
                         VAR folderDirID: LongInt): OSErr;
  VAR
    myCInfoPBRec: CInfoPBRec;
    retCode: OSErr;
  BEGIN
    myCInfoPBRec.ioCompletion := NIL;
    myCInfoPBRec.ioNamePtr := @folderName;
    myCinfoPBRec.ioVRefNum := parentFolderVRefNum;
    myCInfoPBRec.ioFDirIndex := 0; { use name, vRefNum, dirID }
    myCInfoPBRec.ioDrDirID := parentFolderDirID; { will be changed }

    retCode := PBGetCatInfoSync(@myCInfoPBRec); { IM IV-155 }

    IF retCode = noErr THEN folderDirID := myCInfoPBRec.ioDrDirID;

    GetFolderDirID := retCode;
  END;

Back to top

PBHDelete insights and code snippet

Date Written: 11/28/90

Last reviewed: 2/8/91

Using a synchronous call to delete an empty Macintosh directory using PBHDelete returns a fBsyErr.

___

I don't know exactly what is causing the fBsyErr on your machine, but here's my best guess: The reason you are experiencing this problem is that something has set a working directory to the one you're trying to delete. I was able to get this to happen by setting the current directory in MPW to "foo:temp:" and then trying to delete it. The bad news is that you can't close another process's working directory. There will be cases where your application won't be able to delete the directory until the user resets the default directory in the offending application. Such are the perils of working in a multitasking environment....

Also, I would suggest using a routine like the one included below. It ensures that the specified file is in fact a directory, and supplies a vRefNum and DirID to PBHDelete, which I feel is safer than just giving a full pathname.

/*
**
**        DirDelete.c
**
**            An MPW tool to delete a directory.
**            Gets the target file from the command line.
**
**            Neil Day
**            MacDTS
**            Apple Computer, Inc.
**            11/29/90
**
*/

#include     <Stdio.h> /* compiler interfaces */
#include     <Files.h>
#include     <Memory.h>
#include    <Strings.h>

#define        DIR_BIT        4

OSErr DirDelete (char *dirName); /* function prototypes */

main (argc,argv)
int argc;
char **argv;
{
    int argCounter;
    OSErr err;

    if (argc < 2) {
        printf ("Format :  DirDelete <file1> [<file2>
        ...  <fileN>]\n");
        return;
    }

    for (argCounter = 1; argCounter < argc; argCounter++) {
        printf ("%s\n",argv[argCounter]);
        err = DirDelete (argv[argCounter]);
        if (err)
            printf ("DirDelete :  got error %d while trying to
            remove %s\n",

                        err,argv[argCounter]);
    }
}

/*
**   DirDelete
**     Deletes a directory given the full pathname to the directory.
**
**     Uses PBGetCatInfo to retrieve the vRefNum and DirID of the directory
**     and its status flags.  Checks to see that the specified file is
**     in fact a directory, and deletes it if it is...
**
*/
OSErr DirDelete (dirName)
char *dirName;
{
    OSErr err;
    CInfoPBPtr Info;
    HParmBlkPtr delete_me;

    err = noErr;

    Info = (CInfoPBPtr) NewPtrClear (sizeof(CInfoPBRec));
    Info->hFileInfo.ioNamePtr = c2pstr(dirName);

    delete_me = (HParmBlkPtr) NewPtrClear (sizeof (HParamBlockRec));

    err = PBGetCatInfo (Info,false);

    if ((!err) && ((Info->hFileInfo.ioFlAttrib>>DIR_BIT)
        & 0x01)) {
        delete_me->fileParam.ioVRefNum = Info->hFileInfo.ioVRefNum;
        delete_me->fileParam.ioDirID = Info->hFileInfo.ioDirID;
        err = PBHDelete (delete_me,false);
    }

    DisposPtr ((Ptr)Info);
    DisposPtr ((Ptr)delete_me);
    return err;

Back to top

Working directories and WDRefNum

Date Written: 12/13/90

Last reviewed: 6/14/93

How do I get the directory ID when using HCreateResFile (as described in the Macintosh Technical Note "New Resource Manager Calls." Also, what exactly are working directories, and do I need to be concerned with them, or are they a thing of the past?

___

The directory ID comes indirectly from the Standard File dialogue that the user uses to select an output or input file. Standard File returns a working directory reference number in the ioVRefNum. Use the PBGetWDInfo call to break that up into an ioVRefNum and ioDirID pair.

Working directories are a compatibility item to allow programs written for MFS to run under HFS. Since MFS didn't support directories in any true sense, HFS needed to be able to encode both volume and directory information in the same place. The vRefNum was the most logical spot to do that, and hence the WDRefNum was born. The first and last thing you should do with a WDRefNum is convert it to a vRefNum and DirID pair. For more information on the PBGetWDInfo call, please refer to Inside Macintosh Volume IV, page 159.

X-Ref:

DTS Macintosh Technote "New Resource Manager Calls"

Inside Macintosh Volume IV, File Manager chapter, page 159

Back to top

Getting HFS directories from full pathnames

Date Written: 12/21/90

Last reviewed: 1/16/91

How can I determine Macintosh HFS directories from the full pathnames without going through SFGetFile or opening files?

___

Apple recommends not using full pathnames. They're unwieldy, they take up lots of space, the File Manager doesn't deal with names longer than 255 characters, and they're unnecessary.

However, if you are working with a piece of software other than your own, it may be unavoidable. If so, there are two methods depending on the size of the full pathname:

1. If the full pathname is less than 255 characters, simply get the dirID of the directory by calling PBGetCatInfo.

    VAR
            pbc:          CInfoPBRec;

    BEGIN
            name := 'Chinese Junk:Test:VMCalls:';

            WITH pbc DO BEGIN
                ioCompletion := NIL;
                ioNamePtr := @name;
                ioVRefNum := 0;
                ioFDirIndex := 0;
                ioDrDirID := 0;
            END;
            err := PBGetCatInfo(@pbc, FALSE);

This will return to you the dirID of the folder in ioDrDirID.

2. If the full pathname is longer than 255 characters, you will have to break up the name into smaller parts and get information incrementally. This is shown below. Note that this example is not quite realistic since I store the original full pathname in a Pascal string, which will always be smaller than 255 characters.

VAR
        pbc:                CInfoPBRec;
        pbh:                HParamBlockRec;
        name:               Str255;
        tempname:           Str255;
        vRefNum:            Integer;
        dirID:              LONGINT;
        done:               Boolean;
        lastPos:            Integer;
        curPos:             Integer;

BEGIN
        name := 'Chinese Junk:Test:VMCalls:';

        tempname := name; {PBHGetVInfo modified ioNamePtr string,
        so copy it}
        WITH pbh DO BEGIN
            ioCompletion := NIL;
            ioNamePtr := @tempname;
            ioVRefNum := 0;
            ioVolIndex := 0;
        END;
        err := PBHGetVInfo(@pbh, FALSE);

        vRefNum := pbh.ioVRefNum; {get vRefNum for PBGetCatInfo calls}
        dirID := 0; {init dirID to zero}
        done := FALSE;
        lastPos := 1;

        REPEAT
            curPos := lastPos; {look for the next chunk surrounded
            by colons}
            REPEAT
                curPos := curPos + 1;
                done := curPos >= LENGTH(name);
            UNTIL (name[curPos] = ':') | (done);
            tempname := Copy(name, lastPos, curPos - lastPos + 1);
            lastPos := curPos;
            WITH pbc DO BEGIN
                ioCompletion := NIL;
                ioNamePtr := @tempname;
                ioVRefNum := vRefNum;
                ioFDirIndex := 0;
                ioDirID := dirID;
            END;
            err := PBGetCatInfo(@pbc, FALSE);
            dirID := pbc.ioDrDirID; {get this dirID to use a parent
                                     for next chunk}

            Writeln('err = ', err);
            Writeln('tempName = ', tempname);
            Writeln('ioVRefNum = ', pbc.ioVRefNum);
            Writeln('ioDrDirID = ', pbc.ioDrDirID);
            Writeln('ioDrParID = ', pbc.ioDrParID);

        UNTIL done;
END.

This will give you the following output:

    err =        0
    tempName = Chinese Junk:
    ioVRefNum =       -2
    ioDrDirID =        2
    ioDrParID =        2
    err =        0
    tempName = :Test:
    ioVRefNum =       -2
    ioDrDirID =      271
    ioDrParID =        2
    err =        0
    tempName = :VMCalls:
    ioVRefNum =       -2     <--- this is the vRefNum you want
    ioDrDirID =    26399     <--- this is the dirID you want
    ioDrParID =      271

Back to top

How a new Macintosh directory ID is determined

Date Written: 1/24/91

Last reviewed: 2/14/91

Our Macintosh application moves files between directories on a file system; the directories determine certain actions and are seldom changed; thus, the application keeps a persistent reference to the directories. The current form of this reference is <volume name, path from root>. According to a System 7 lecture, the preferred form for a persistent file reference is <volume name, directory ID, filename>, which reduces to <volume name, directory ID>, the preferred form for a persistent directory reference. The process of throwing folders away and creating new ones could result in a directory ID being reused on an HFS volume. Is this truly a threat, or has the directory allocation scheme been designed to require many transactions before reusing an ID?

___

You are correct in your assumption that many transactions need to take place before a directory ID gets reused. The system does not start with dir ID = 0 and search the hard disk until it finds an ID that's not used. Instead, the ID of the last created folder is in a "last created ID" field on the disk. When the system creates a new folder, it searches with that "last value" + 1. Since these are 32-bit values, you'd have to create over 4 billion folders before you wrap around again to zero.

Back to top

Changing a file's fork without changing last-modified date

Date Written: 7/9/91

Last reviewed: 6/14/93

Inside Macintosh Volume VI, page 2-22, recommends updating the window positions in a file without changing the last modification date and time on the file. How do I alter a file without automatically changing the timestamp?

___

To modify the contents of a file's data or resource fork without changing the last modified date, get the modified date before performing any save operations on the file and restore it when you're done. You can use the PBHGetFInfo and PBHSetFInfo calls to do this. A short Pascal snippet that modifies the contents of a known file's resource fork without modifying its modification date is shown below. The code shows how the parameter block is filled in with the file's information at the start of the routine with a PBHGetFInfo call, and the same data is then used without modification to set the file information at the end of the routine with a PBHSetFInfo. Inside Macintosh Volume IV, page 150, tells you which fields can be changed with PBHSetFInfo.

Procedure DummyResource;

var    a:stringHandle;
    b:Integer;
    fred:str255;
    theBlock:HParamBlockRec;
    anErr:OSErr;

begin
  {Set up the parameter block}
  fred:='anIcon';
  theBlock.ioCompletion:=nil;
  theBlock.ioNamePtr:=@Fred;
  theBlock.ioVRefNum:=0;
  theBlock.ioFDirIndex:=0;
  theBlock.ioDirID:=0;
 {Recover the files info to save the mod date}
  anErr:=PBHGetFInfo(@theBlock,false);
 {modify the resource fork}
  b:=OpenResFile('anIcon');
  a:=StringHandle(GetResource('STR ',128));
  a^^[1]:=char(ord(a^^[1])+1);
  ChangedResource(Handle(a));
  UpdateResFile(b);
  CloseResFile(b);
 {Now restore the original last mod date in the files directory entry.}
  theBlock.ioCompletion:=nil;
  theBlock.ioNamePtr:=@Fred;
  theBlock.ioVRefNum:=0;
  theBlock.ioFDirIndex:=0;
  theBlock.ioDirID:=0;
  anErr:=PBHSetFInfo(@theBlock,false);
end;

Back to top

Code for detecting PBCatSearch support

Date Written: 9/26/91

Last reviewed: 10/15/91

Our code for volume searching using PBCatSearch doesn't work for AppleShare volumes. Do you know how we can make it work?

___

PBCatSearch works only on volumes that support it. If you attempt to use PBCatSearch on a volume that doesn't support it, you'll get a wrgVolTypErr (-123). (This isn't documented in Inside Macintosh Volume VI.)

AppleShare 2.0 volumes (AppleShare 2.0 is an AFP 2.0 server) and volumes supported by some other external file systems do not support PBCatSearch, so you'll have to resort to recursively searching the catalog using a routine similar to the one shown in the Macintosh Technical Note "Searching Volumes--Solutions and Problems" on those volumes. PBCatSearch is supported by AppleShare volumes on System 7 File Sharing servers because File Sharing supports AFP version 2.1 which includes CatSearch as a supported command.

You can use the File Manager call PBHGetVolParms to check a volume for most volume-specific features, including support for PBCatSearch. Here's a short function that shows how to do that:

FUNCTION CatSearchable (vRefNum: Integer): Boolean;
{See if PBCatSearch is supported on the volume specified by vRefNum}
  VAR
    pb: HParamBlockRec;
    infoBuffer: GetVolParmsInfoBuffer;
    err: OSErr;
BEGIN
  WITH pb DO
    BEGIN
      ioNamePtr := NIL;
      ioVRefNum := vRefNum;
      ioBuffer := @infoBuffer;
      ioReqCount := SizeOf(infoBuffer);
    END;
  err := PBHGetVolParms(@pb, FALSE);
  IF err = noErr THEN
    IF BTst(infoBuffer.vMAttrib, bHasCatSearch) THEN
      CatSearchable := TRUE
    ELSE
      CatSearchable := FALSE
  ELSE
    CatSearchable := FALSE;
END;

Back to top

PBHGetDirAccess ioNamePtr (not ioFileName) & ioDirID params

Date Written: 12/20/91

Last reviewed: 6/14/93

Two PBHGetDirAccess parameters listed in Inside Macintosh Volume V, page V-394, ioFileName and ioDirID, aren't in the MPW C 3.2 header files. Can anyone show me the correct way to call this function?

___

The ioFileName parameter is really ioNamePtr (Inside Macintosh Volume V documentation error) and can be found in the ParamBlockHeader. The ioDirID parameter is in the FileParam variant of the ParamBlockRec, so if you just refer to it as myHParamBlockRec.ioDirID, you should be fine. You'll find similar cases in the C include files where you'll need to use two different variants to get to all the fields used by a call.

Back to top

PBGetCatInfo NIL ioNamePtr bug and workaround

Date Written: 3/6/92

Last reviewed: 6/14/93

I'm using PBGetCatInfo to index through the entries in a directory. Because I'm not interested in the names of the directory entries, I set ioNamePtr to NIL. Everything worked great until I tried this on a volume shared with Macintosh File Sharing. After running my program on a shared volume, the system started acting unpredictably. What happened?

___

The problem you reported with PBGetCatInfo is caused by a bug in the Macintosh File Sharing code. It doesn't check for a NIL value in ioNamePtr correctly and always copies the file or folder name found at a particular catalog position to whatever ioNamePtr points to. This means up to 32 bytes starting at location 0 will be trashed if ioNamePtr = NIL. So until this problem is fixed, you should avoid using indexed calls to PBGetCatInfo when ioNamePtr = NIL; ioNamePtr should always point to storage for a Str255.

The AppleShare 3.0 file server does not have this problem, nor does System 7.1 Macintosh File Sharing.

Back to top

Forcing the Macintosh system to switch-launch

Date Written: 11/21/89

Last reviewed: 11/21/90

How can I get my Macintosh application to force the system to switch to the application's disk when the user launches it, like Installer does?

___

This is called switch-launching. You can do what Installer does, setting a Finder flag that tells Finder to switch-launch to the new volume. Set this flag with ResEdit by selecting the application, selecting Get Info from the File menu, then setting the appropriate checkbox. You can also set this with the MPW command:

    SetFile -a A foo

Note that forcing a switch-launch in this way never works if any of the following conditions are true:

* The new volume is not bootable--that is, has no system or Finder or is a volume like an AppleShare volume;

* MultiFinder is running;

* Either the system or Finder on the new volume is an older version than the one currently in use.

If any of these conditions are true and you try to force a switch-launch, the user will get a dialog stating why switch-launching is not possible, and asking if the user wants to proceed with the launch (without the switch) or cancel it.

Because of these limitations, if you plan for your application to be used by others and you depend on this capability, you need to think carefully about the consequences of forcing switch-launching. For example, a user may (and probably will) choose to run MultiFinder. There is no way for you to know if MultiFinder is running, and if you are depending on the switch, strange things may happen. Switch-launching may be even more restricted in the future.

X-Ref:

Macintosh Technical Note "Finder Flags"

Back to top

How can I tell which directory my Macintosh application is in?

Date Written: 5/3/89

Last reviewed: 11/21/90

How can I tell which directory my Macintosh application is in?

___

When an application is started, the default volume is set to the directory that contains the application. GetVol returns the default volume. If the application calls GetVol before changing the default volume, it will have the directory for the folder containing the application.

Back to top

Assembler code for distinguishing between HFS and MFS calls

Date Written: 3/9/92

Last reviewed: 6/14/93

I'm trying to patch the Macintosh _Create trap and save off the volume and directory ID of the file that is being created. How do I tell if the caller has placed a HParamBlkPtr or a ParamBlkPtr in A0 so I'll know whether to treat the ioDirID element as significant?

___

When you're called from the trap dispatcher, the trap word you're being called with is placed in register D1. Since HFS calls can be distinguished from MFS calls by bit 9 being set in the trap word, you can simply see if this bit is set in D1 to determine whether the call is using an HParamBlkPtr. Here's an example in 68000 of how you could check this bit:

createPatch movem.l a0/d0-d1,-(sp) ; save registers
            move.l  d1,d0
            andi.w  #$0200,d0
            beq.s   isCreate
isHCreate   ...
            ...
            bra.s   done
isCreate    ...
            ...
done        movem.l  (sp)+,a0/d0-d1
            move.l  createLink,-(sp)
            rts

Besides checking HFS vs. MFS, you can also use D1 to determine whether or not the call was made asynchronously by checking bit 10 of D1.

Back to top

Downloadables

Acrobat gif

Acrobat version of this Note (84K)

Download


Back to top