/*static char *SCCSID = "@(#)curdir.h   6.1 90/11/17";*/
/*      SCCSID = @(#)curdir.inc  13.6 90/07/17
*/
/* XLATOFF */
#pragma title("Current directory list structure")
/* XLATON  */
/* ASM
BREAK <Current directory list structure>
 */

/****   Current Directory Structure - CDS

    CDS items are used by internal routines to store cluster numbers and
    network identifiers for each logical name. In the case of local devices,
    there is a MEDIA_SWAPPED flag so if there is a potential of the disk
    having been changed, the path must be recracked.

    There are CDS structures kept in an RMP segment (for current directories,
    remote drive connections, JOINs, & SUBSTs).  Permanent CDS structures are
    not kept for current directories at the root of local drives

    CDS structures are also used while processing path names.  These structures
    are kept in DummyCDS, and are either copies of real CDS structures (from
    the RMP segment) or built as needed).  These structures are temporary and
    are used during the path processing only.

    Only Current Directory operations (ChDir, and process termination) and
    special cases (JOIN, SUBST, & remote drives - including Redir) affect the
    CDS structures in the RMP segment.

    Each PTDA has an array (one for each possible drive: A-Z) of CDS handles
    which (if non-zero) are the handles for the RMP CDS which has the current
    directory for each drive.  If one is zero, the current directory is the
    root for that drive.

    CDS handles 0, & 1-26 have special meaning.  0 is an invalid handle.  1-26
    are reserved for special cases (JOIN, SUBST, & remote drives/macros).  All
    other CDS handles are > 26.

      PTDA (CDS)                     Actual CDS structure
     handle table                    --------------------
     ------------
                                              +---------+
                                     (CDS 1)  |C:\ADRIVE| (JOINed drive)
                                              +---------+
                                                 ^
   (Drive)                                    +-------------+
          +--+                       (CDS 14) |B:\LONG\CURR | (SUBST)
     (A) 1| 0|--(no cur dir - root)           +-------------+
     (B) 2|27|--------------\                              ^
     (C) 3|35|-(JOIN)-\      \                +---------------+
         .|  |         \      \      (CDS 26) |\\REMOTE\DRIVE | (REMOTE)
         .|  |          \      \              +---------------+
         .|  |           \      \                            ^
         .|  |            \      \            +-----------+
         .|  |             \      \--(CDS 27) |B:\CURR\DIR| (normal CurDir)
    (N) 14|45|-(SUBST)-\    \                 +-----------+
         .|  |          \    \                   ^
         .|  |           \    \               +-----------------------+
         .|  |          --\----\-----(CDS 33) |\\REMOTE\DRIVE\CURR\DIR| (REMOTE)
         .|  |         /   \    \             +-----------------------+
    (Z) 26|33|-(Redir)/     \    \                           ^
          +--+ (or REMOTE)   \    \           +--------------+
                              \    \-(CDS 35) |C:\ADRIVE\TEMP| (JOINed - to A:)
                               \              +--------------+
                                \                ^
                                 \            +-----------------+
                                  \--(CDS 45) |B:\LONG\CURR\DIR | (SUBST)
                                              +-----------------+
                                                           ^

    (^) indicates the end of the root (see cdi_end, below).

    cd_handle is a handle by which a CDS is looked up in an RMP segment.
    Handles in the range 1-26 are reserved for drive global information:
    JOINs, SUBSTs, and remote drives (macros).  Other handles are used
    for per-process working directories.

    Implementation note:  cdi_end field points to the point in the text
    string where the user may back up to via ..  It is the location of a
    separator character.  For the root, it points at the leading \.  For
    remote (and SUBST) assignments it points at the end (null) of the initial
    assignment:

    A:\     \\foo\bar       \\foo\bar\blech\bozo
      ^              ^               ^
      |              |               |


 ** Structure of a CDS

    The structure for the CDS is arranged as follows:

            - A part that is private to the kernel
            - A file system independent part that may be passed to an
              IFS as part of an FS call.
            - A file system dependent part that a file system can use as
              it wishes - usually designated as a work area. This may also
              be passed to an IFS as part of an FS call.

    The layout of a CDS is as follows:

            -----------------------------
            |   Private to Kernel       |
            |                           |
            |                           |
            |                           |
            -----------------------------
            |   File system dependent   |
            |                           |
            |         cd_fsd            |
            |                           |
            -----------------------------
            | File system independent   |
            |                           |
            |         cd_fsi            |
            |                           |
            -----------------------------

        The way that the various fields are accessed in the kernel depends
        on where they are in the CDS structure. It is possible to specify
        "fields into fields" using MASM as follows:

        e.g. To access the field cdi_hVPB, you would use something
             like
                    MOV     AX,ES:[DI].cd_fsi.cdi_hVPB



  The maximum path lengths in protected mode and the 3x box should be the
  same in order to avoid confusion for the user.
  There is no real need for RMPATHLEN, but it is defined here for reference.

  NOTE: The xxxPATHLEN symbols include the trailing NUL byte in all
        cases.

  WARNING: Be careful of 3xBox structures which refer to MAXPATHLEN.
  MAXPATHLEN for such structures

*/

#define PMPATHLEN     (257 + 3)   /* Path length for protected mode */
#define RMPATHLEN     PMPATHLEN   /* Path length in 3x box */

/*;;BUGBUG RajenS April 27, 1988 - Temporary code.
  ;; This was put in as a DCR in 1.1 and was removed from 1.2. We need
  ;; to put it back.
*/

#define MAXPATHLEN      PMPATHLEN
#define MAXCOMPLEN      255         /* max component length */
/*
  Make sure that RMPATHLEN = PMPATHLEN since we assume this in various
  places.
*/

/* XLATOFF */
#if (RMPATHLEN != PMPATHLEN)
#error RMPATHLEN is not equal to PMPATHLEN
#endif
/* XLATON  */

/* ASM
IF (RMPATHLEN NE PMPATHLEN)
    %out ERROR - RMPATHLEN is not equal to PMPATHLEN
    .ERR
ENDIF
*/
/*
  The same argument does not apply to the length of the CURDIR. In real mode,
  there is an Int 21 function that has documented the fact that it returns
  the current directory in a 64-byte buffer. We therefore have to restrict
  the current directory in real mode to 64 bytes.

  The protect mode length of CURDIR is limited to the length of the maximum
  path length. We make it one less to keep room for a path separator (if
  necessary).

  QCURDIR does not return the 'd:\' part of the string, so the length
  internally in the kernel is 3 more than what the user is allowed to use.
*/

#define PMDIRSTRLEN     PMPATHLEN   /* Protect mode curdir length */
#define RMDIRSTRLEN     (64+3)      /* Real mode curdir length */

#define INT21_47_SUCCESS 0x0100  /* Retn in AX on successful retn from  74507 */
                                 /* Int 21,47 - GetCurrentDirectory     74507 */

#define NUMDRIVE        26          /* Max logical drive number */

/*
  NOTE: The spec states a certain size, but if it turns out that the FAT file
        system specific data requires more space than stated in the spec,
        we allocate more space in the structure and use .errnz's to ensure
        that we don't make it smaller than what is in the spec AND smaller
        than that required for the FAT file system.
*/

#define SPECCDDWORKAREASIZE  8      /* Work area size in spec */
#define CDDWORKAREASIZE      8      /* Size of file system dependent work area */
/* XLATOFF */
#if  (CDDWORKAREASIZE < SPECCDDWORKAREASIZE)
#error
#endif
/* XLATON */
/* ASM
.errnz  (not (CDDWORKAREASIZE ge SPECCDDWORKAREASIZE))
 */

/*
  The following structure defines the layout of the file system independent
  fields in the CDS structure.

  WARNING:  If this structure changes, be sure to propagate the changes to
            FSD.H (and be sure the spec is correct!).


  WARNING  The text string has to be the last field in this structure AND
           this structure should be the last part of the structure curdir.
           This is bacause of code in PATH.ASM that compares CDSs to see
           if they have changed. It only scans to the end of the string
           in the CDS, not to the end of the CDS.

*/

typedef struct cdfsi {
ushort_t  cdi_hVPB ;              /* hVPB for the drive mapped to this CDS */
ushort_t  cdi_end ;               /* End of assignment */
uchar_t   cdi_flags ;             /* fs independent flags (see below) */
uchar_t   cdi_text[PMDIRSTRLEN] ; /* Text of assignment and curdir */
} cdfsi ;

#define CDI_END_ROOT     2               /* value for cdi_end for normal case */
                                        /* (Redir & SUBST CDSs are different) */

/*
  Check the code in PATH.ASM and in InitCDS in MACRO.ASM if the following
  change.
*/
/* ASM
.errnz (SIZE cdfsi - cdi_text - PMDIRSTRLEN)
 */

/*
  The following structure defines the layout of the file system dependent
  area in the CDS structure.
*/

typedef struct cdfsd {
uchar_t cdd_work[CDDWORKAREASIZE] ;
} cdfsd ;

/*
  The following structure defines the layout of the CDS structure
*/
typedef struct curdir {
/* Fields used by the kernel for all file systems */
ushort_t  cd_handle ;             /* lookup key for this CDS */
ushort_t  cd_pid ;                /* PID part of lockup key for handles 1-26 */
/* cd_handle and cd_pid MUST be together! */
ushort_t   cd_refcnt ;            /* reference count CDS's */
uchar_t   cd_flags ;              /* See below for definitions */
uchar_t   *cd_devptr ;            /* local pointer to DPB or net device */
ushort_t  cd_OwnerFSC ;           /* Owner FSC.Offst */

/* File system dependent fields (work area) */
cdfsd   cd_fsd ;

/* File system independent fields - MUST be at end of the CDS - See w_ChDir
   in PATH.ASM */
cdfsi cd_fsi ;

} curdir ;

/*
  Ensure that cd_fsi is the last field in the curdir structure.
  NOTE: Check code in PATH.ASM and InitCDS in MACRO.ASM if this changes.
*/
/* ASM
.errnz (SIZE curdir - cd_fsi - SIZE cdfsi)
 */

/* The following structure defines the file system dependent part of the
   CDS for the FAT file system.  It is used by the internal FAT file system
   (in the kernel).
*/

typedef struct cddFATFS {
ushort_t  cddFAT_id ;             /* cluster of current dir */
} cddFATFS ;

/*** cd_flags masks */

#define CD_ISNET        0x80            /* This CDS is for a remote drive */
#define CD_INUSE        0x40            /* This CDS is in use */
#define CD_SPLICE       0x20            /* This CDS is for a JOINed drive */
#define CD_JOIN         CD_SPLICE       /* This CDS is for a JOINed drive */
#define CD_LOCAL        0x10            /* This CDS is for a SUBSTed drive */
#define CD_ISPSEUDOCHAR 0x08            /* This CDS for a pseudo-char dev */
#define CD_ISUNC        0x04            /* This CDS for a UNC name */

/*** cdi_flags masks */

#define CDI_ISVALID       0x80          /* This CDS contains a valid cd_fsd */
#define CDI_ISROOT        0x40          /* This CDS is for a root (no cdfsd) */
#define CDI_MEDIASWAPPED  0x20          /* This CDS may not be valid (forces */
                                        /* validation for local drives) */

/*** ChDir opflag values - used for FS_ChDir interface */

#define CHDIR_SET       0               /* Set new Current Directory */
#define CHDIR_VERIFY    1               /* Verify Current Directory */
#define CHDIR_FREE      2               /* Free Current Directory */
