/*static char *SCCSID = "@(#)vol.c      6.2 91/01/14";*/
/*      SCCSID = "@(#)vol.c     6.2 91/01/14"
 *
 *      IBM/Microsoft Confidential
 *
 *      Copyright (c) IBM Corporation 1987, 1989
 *      Copyright (c) Microsoft Corporation 1987, 1989
 *
 *      All Rights Reserved
 *
 */


/*
 *  VOL.C
 *
 *    DESCRIPTION
 *
 *      Functions which deal with recognizing volumes for FS_MOUNT.
 *
 *
 *    FUNCTIONS DEFINED
 *
 *      ValidVD ()              -   Searches for a valid volume descriptor.
 *      FreePathTableList ()    -   Frees all the memory use to store a
 *                                      Path Table.
 *      FreeSectorList ()       -   Free a volume's sector list.
 *      FreeVolDepData ()       -   Free the memory allocated on a
 *                                      per-vol basis.
 *      MountCondenseVol ()     -   Translate the volume descriptor into
 *                                      a VOL_DESCRIPT.
 *      VolMount ()             -   Perform the mount operation.
 *
 *
 *
 *  REVISION HISTORY (in reverse chronological order)
 *  -----------------------------------------------------------------------
 *  7/25/92     Frank Schroeder Changed MountCondenseVol to copy copyright,
 *                              abstract, and bibliographic file names from
 *                              ISO or HSG VTOC to VOL_DESC.  Changed parms
 *                              for GetFirstDE so that prdrRawDirRec will
 *                              not be returned.
 *
 *  8/3/90      Brian Andrew    Check that device sector size is something
 *                              the FSD can handle (VolMount).
 *
 *  4/19/90     Brian Andrew    Attach LIST_SEM_BLK on mounting.  Free on
 *                              dismounting.
 *
 *  4/9/90      Brian Andrew    Initialized LIST_SEM_BLK structures in
 *                              VOL_DEP_DATA.
 *
 *  2/7/90      Brian Andrew    Moved VolMount to this file.
 *
 *  11/30/89    Brian Andrew    Modified MountCondenseVol.  Cleaned strings
 *                              to check for valid DBCS and supported
 *                              error code from CopyRawDEtoDE.
 *
 *  11/17/89    Brian Andrew    Replace AppendNull with CopyWithNull.
 *
 *  11/16/89    Brian Andrew    Modified MountCondenseVol to use structure
 *                              pointer for arguements.
 *
 *  11/16/89    Brian Andrew    Modified ValidVD to use structure pointer
 *                              instead of individual variables.
 *
 *  11/14/89    Brian Andrew    Added check for supplemental VD.
 *
 *  11/14/89    Brian Andrew    Added DBCS support (StrnCmpDBCS)
 *
 *  8/10/89     Brian Andrew    Functions for volume mount.
 *
 *  8/4/89      Brian Andrew    Initial Blank Template.
 *
 *
 *  TO DO
 *  -------------------------------------------------------------------------
 */


#define INCL_DOSERRORS
#define INCL_NOPMAPI

#include <os2.h>
#include <fsd.h>
#include <fsh.h>

#include <mscdex.h>
#include "cdfs.h"
#include "sem.h"
#include "path.h"
#include "vol.h"
#include "file.h"
#include "buffer.h"
#include "mem.h"
#include "heap.h"
#include "message.h"

#ifdef STATS_H
#include "stats.h"
#endif

#include "fsdata.h"
#include "pr_strng.h"
#include "pr_vol.h"
#include "pr_memin.h"
#include "pr_dir.h"
#include "pr_dbcs.h"
#include "pr_path.h"
#include "pr_cache.h"
#include "memory.h"

#ifdef DEBUG
#include "pr_DEBUG.h"
#endif


/*
 ***    ValidVD ()          Searches for a valid volume descriptor
 *
 *
 *      Modifies    ppBuf           Stores the sector with the valid VD
 *                  pfISOVol        Flag set TRUE if ISO volume found
 *                  plSectorNumber  Sector where VTOC found
 *
 *
 *          These are fields in the pmpMountParams structure.
 */

USHORT ValidVD (pmpMountParams)
PMOUNT_PARAMS    pmpMountParams;
{
        PRAW_ISO_VTOC       privRawVol;   /* assume descriptor is ISO         */
        BOOL                fISO;
        BOOL                fHSG;
        USHORT              usRet;
        SECT_NUM            snSector;
        UCHAR               bDescType;
        UCHAR               bVersion;
        PCHAR               pszCurrEsc;
        BOOL                fCurrentUsePrimaryVD;

        /* remember the current volume descriptor choice and escape sequence */
        fCurrentUsePrimaryVD    = fUsePrimaryVD;
        pszCurrEsc              = pszVolEscSeq;

        /* initialize snSector to the first Vol Descriptor */
        snSector = VTOC_ST_SECTOR;

        /* attempt to read the first sector */
        usRet = ReadSector (
                                pmpMountParams->hVPB,
                                &pmpMountParams->pbBuf,
                                snSector * pmpMountParams->pvddVolData->usSectorBase,
                                pmpMountParams->pvddVolData->usSectorBase);

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tValidVD:  ERROR calling ReadBuf -- %d\n", usRet);
        }
#endif

        /* while sector read was successful */
        while (!usRet)
        {

                /* Overlay the descriptor pointer */
                /* Test if this is an ISO Vol Descriptor */
                /* Test if this an HSG VOL Descriptor */
                privRawVol = (PRAW_ISO_VTOC)
                                                OVERLAY_STRUCT (pmpMountParams->pbBuf, VOL_DESC_OFF);

                fISO = !StrnCmpDBCS (ISO_VOL_ID, RV_STD_ID (privRawVol, TRUE),
                                                                VOL_ID_LEN);
                fHSG = !StrnCmpDBCS (HSG_VOL_ID, RV_STD_ID (privRawVol, FALSE),
                                                                VOL_ID_LEN);

                /* If neither, then free the buffer and return ERROR_NOT_SUPPORTED */
                if (!fHSG && !fISO)
                {
                        FREE_BUF (pmpMountParams->pbBuf);
                        usRet = ERROR_NOT_SUPPORTED;
                        break;

                } /* end if neither */

                /* Get the version and the descriptor type */
                bDescType = RV_DESC_TYPE (privRawVol, fISO);
                bVersion = RV_VERSION (privRawVol, fISO);

                /* If version isn't VERSION_1, also return */
                /* ERROR_NOT_SUPPORTED */
                if (bVersion != VERSION_1)
                {
                        FREE_BUF (pmpMountParams->pbBuf);
                        usRet = ERROR_NOT_SUPPORTED;
                        break;

                } /* end if version wrong */

                /* If terminator and supplemental, look for primary */
                else if (bDescType == VOL_TERMINATOR)
                {
                        if (fCurrentUsePrimaryVD)
                        {
                                FREE_BUF (pmpMountParams->pbBuf);
                                usRet = ERROR_NOT_SUPPORTED;
                                break;

                        } /* end if were looking for primary */

                        /* else look for primary */
                        else
                        {
                                snSector = VTOC_ST_SECTOR - 1;
                                fCurrentUsePrimaryVD = TRUE;

#ifdef DEBUG
                                dprintf ("\tValidVD:  No valid supplemental found\n");
#endif
                        } /* end else were looking for supplemental */

                } /* end if terminator found */


                /* If desired descriptor type is VOL_PRIMARY we are done */
                /* Flag is fISO, sector number is snSector */
                else if ((fCurrentUsePrimaryVD) && (bDescType == VOL_PRIMARY))
                {
                        pmpMountParams->fISOVol       = fISO;
                        pmpMountParams->snSectorNumber = snSector;
                        break;

                } /* end if primary */

                /*
                 *  If the desired is supplemental and this is supplemental and
                 *  the escape sequence matches we are done.  Flag is fISO and
                 *  sector number is snSector.
                 */
                else if ((!fCurrentUsePrimaryVD) && (bDescType == VOL_SECONDARY))
                {
                        /* If the escape sequences match, we are done */
                        if (!StrnCmpDBCS (pszCurrEsc,
                                                                RV_CHARSET(privRawVol, fISO),
                                                                istrlen (pszCurrEsc)))
                        {
#ifdef DEBUG
                                dprintf ("\ValidVD:  Found valid supplemental\n");
#endif

                                pmpMountParams->fISOVol = fISO;
                                pmpMountParams->snSectorNumber = snSector;
                                break;

                        } /* end if valid supplemental */

                } /* end else if supplemental found */

                /* Otherwise try to get the next sector */
                FREE_BUF (pmpMountParams->pbBuf);

                if (usRet = ReadSector (
                                                pmpMountParams->hVPB,
                                                &pmpMountParams->pbBuf,
                                                (++snSector) * pmpMountParams->pvddVolData->usSectorBase,
                                                pmpMountParams->pvddVolData->usSectorBase))
                {
#ifdef DEBUG
                        dprintf ("\tValidVD: ERROR calling ReadBuf(2)  -- %d\n", usRet);
#endif
                } /* end if readsector */

        } /* end while sector read was successful */

        return usRet;

} /* end ValidVD */


/*
 ***    FreePathTableList ()        Returns all the memory used to store
 *                                  a Path Table.
 *
 */

VOID FreePathTableList (pptPathTable)
PPATH_TABLE pptPathTable;
{
        PPATH_TABLE     pptLocalPT;

        pptLocalPT = pptPathTable;

        /* Become a writer for the list */
        BecomeWriter (pptPathTable->plsbSemBlk);

        /* Lock all buffers in the list */
        while (pptLocalPT)
        {
                /* Lock all attached buffers */
                if (pptLocalPT->pbBuf)
                {
                        ((PBUF) pptLocalPT->pbBuf)->cUsers++;
                }

                /* Move to the next sector */
                pptLocalPT = pptLocalPT->pptNextPTSect;
        }

        /* Give up write semaphore */
        DepartWriter (pptPathTable->plsbSemBlk);

        /* Start at top of list again */

        /* Continue until all PATH_TABLEs and attached BUFs are FREEd */
        while (pptPathTable)
        {
                /* If there is an attached Buffer, remove this Path Table */
                /* Then free the buffer */
                if (pptPathTable->pbBuf)
                {
                        RemovePTSec (pptPathTable->pbBuf);
                        FREE_BUF (pptPathTable->pbBuf);

                } /* end if attached buf */

                /* Remember the next PathTable and free the current one */
                pptLocalPT = pptPathTable->pptNextPTSect;
                FREE_PATH_TABLE (pptPathTable);

                /* Point to the next PathTable entry */
                pptPathTable = pptLocalPT;

        } /* end while pptPathTable */

} /* end FreePathTableList */


/*
 ***    FreeSectorList ()       Free a volume's sector list
 *
 *
 */


VOID FreeSectorList (pblSector)
PBUF_LIST   pblSector;
{
        PBUF_LIST   pblLocalBL;

        /* Become a writer for the list */
        BecomeWriter (pblSector->plsbSemBlk);

        /* Lock all buffers in the list */
        while (pblLocalBL)
        {
                /* Lock all attached buffers */
                if (pblLocalBL->pbBuf)
                {
                        ((PBUF) pblLocalBL->pbBuf)->cUsers++;
                }

                /* Move to the next sector */
                pblLocalBL = pblLocalBL->pblNext;
        }

        /* Give up write semaphore */
        DepartWriter (pblSector->plsbSemBlk);

        /* Start at top of list again */

        /* Continue until all BUF_LISTs and attached BUFs are FREEd */
        while (pblSector)
        {
                /* Remove this sector from the in use list */
                /* Then free the buffer */
                if (pblSector->pbBuf)
                {
                        RemoveListSec (pblSector->pbBuf);
                        FREE_BUF (pblSector->pbBuf);
                }

                /* Remember the next SectorList and free the current one */
                pblLocalBL = pblSector->pblNext;
                FREE_BUF_LIST (pblSector);

                /* Point to the next SectorList entry */
                pblSector = pblLocalBL;

        } /* end while pblSector */

} /* end FreeSectorList */


/*
 *** FreeVolDepData ()      Free the memory allocated on per-vol basis
 *
 *
 */


VOID FreeVolDepData (pvddVolData)
PVOL_DEP_DATA   pvddVolData;
{
        /* free the volume descriptor if allocated */
        if (pvddVolData->pvdVolDesc)
        {
                FREE_VOL_DESC (pvddVolData->pvdVolDesc);
        }

#ifdef DEBUG
        else
        {
                dprintf ("\tFreeVolDepData:  Freeing same descriptor twice\n");
        }
#endif

        /* Free the root DE if allocated */
        if (pvddVolData->pdeRootDir)
        {
                FREE_DIR_ENTRY (pvddVolData->pdeRootDir);
        }

        /* free the Path Table if allocated */
        if (pvddVolData->pptPathTable)
        {
                FreePathTableList (pvddVolData->pptPathTable);

        }

        /* free the Sector List if allocated */
        if (pvddVolData->pblSectorList)
        {
                FreeSectorList (pvddVolData->pblSectorList);

        }

        /* free the LIST_SEM_BLK's if allocated */
        if (pvddVolData->plsbPathTable)
        {
                FREE_LIST_SEM_BLK (pvddVolData->plsbPathTable);

        }

        if (pvddVolData->plsbBufList)
        {
                FREE_LIST_SEM_BLK (pvddVolData->plsbBufList);

        }

        /* Set all the pointers to NULL */
        pvddVolData->pvdVolDesc = NULL;
        pvddVolData->pdeRootDir = NULL;
        pvddVolData->pptPathTable = NULL;
        pvddVolData->pblSectorList = NULL;
        pvddVolData->plsbPathTable    = NULL;
        pvddVolData->plsbBufList      = NULL;
} /* end FreeVolDepData */


/*
 ***  MountCondenseVol ()       Allocate and copy into a VOL_DESCRIPT
 *
 *
 *
 */

USHORT MountCondenseVol (pmpMountParams)
PMOUNT_PARAMS   pmpMountParams;
{
        USHORT              usRet;
        PVOL_DESC           pvdVolDesc;

        /* Try to allocate a VOL_DESCRIPT structure */
        /* If successful, copy the volume descriptor into it */

        if (!(usRet = GetVolDesc (&pvdVolDesc)))
        {
                pvdVolDesc->fISOVol      = pmpMountParams->fISOVol;
                pvdVolDesc->vdtVolType   = RV_DESC_TYPE   (pmpMountParams->privRawISO,
                                                                                                        pmpMountParams->fISOVol);
                pvdVolDesc->clbVolSpace  = RV_VOL_SPACE   (pmpMountParams->privRawISO,
                                                                                                        pmpMountParams->fISOVol);
                pvdVolDesc->vsnSNum      = RV_VS_SNUM     (pmpMountParams->privRawISO,
                                                                                                        pmpMountParams->fISOVol);
                pvdVolDesc->cbLogBlk     = RV_LB_SIZE     (pmpMountParams->privRawISO,
                                                                                                        pmpMountParams->fISOVol);
                pvdVolDesc->cbPTSize     = RV_PATH_SIZE   (pmpMountParams->privRawISO,
                                                                                                        pmpMountParams->fISOVol);
                {
                        USHORT  cbFileIDLen;

                        /* Get the length of the ID filenames */
                        cbFileIDLen = pmpMountParams->fISOVol ?
                                                        ISO_FILE_ID_LEN : HSG_FILE_ID_LEN;

                        /* Copy and null terminate the volume id, check the string */
                        CopyWithNull (pvdVolDesc->szVolID,
                                                RV_VOL_ID(pmpMountParams->privRawISO, pmpMountParams->fISOVol),
                                                VOLUME_ID_LEN);

                        CleanStringDBCS (pvdVolDesc->szVolID, VOLUME_ID_LEN);
                }

                pvdVolDesc->lbPathLoc =
                        RV_PATH_LOC(pmpMountParams->privRawISO, pmpMountParams->fISOVol, 0);
                {
                        USHORT  cbFileLen;  /* length varies between ISO and HSG */

                        /* Get the length of the copyright filename */
                        cbFileLen = pmpMountParams->fISOVol ?
                                                  ISO_CPYR_ID_LEN : HSG_CPYR_ID_LEN;

                        /* Copy and null terminate the copyright filename */
                        CopyWithNull (pvdVolDesc->szCpyr_ID,
                                                RV_CPYR_ID(pmpMountParams->privRawISO, pmpMountParams->fISOVol),
                                                cbFileLen);

                        CleanStringDBCS (pvdVolDesc->szCpyr_ID, cbFileLen);

                        /* Get the length of the abstract filename */
                        cbFileLen = pmpMountParams->fISOVol ?
                                                  ISO_ABST_ID_LEN : HSG_ABST_ID_LEN;

                        /* Copy and null terminate the abstract filename */
                        CopyWithNull (pvdVolDesc->szAbst_ID,
                                                RV_ABST_ID(pmpMountParams->privRawISO, pmpMountParams->fISOVol),
                                                cbFileLen);

                        CleanStringDBCS (pvdVolDesc->szCpyr_ID, cbFileLen);

                        /* Get the length of the bibliographic filename */
                        cbFileLen = pmpMountParams->fISOVol ?
                                                  ISO_BIBL_ID_LEN : HSG_BIBL_ID_LEN;

                        /* Copy and null terminate the bibliographic filename */
                        CopyWithNull (pvdVolDesc->szBibl_ID,
                                                RV_CPYR_ID(pmpMountParams->privRawISO, pmpMountParams->fISOVol),
                                                cbFileLen);

                        CleanStringDBCS (pvdVolDesc->szBibl_ID, cbFileLen);
                }
                {
                        USHORT  usCount;

                        /* Copy the volume creation date */
                        for (usCount = 0; usCount < VOL_CREATE_BYTES; usCount++)
                        {
                                pvdVolDesc->acVolCrDate[usCount] =
                                        RV_CR_DATE (pmpMountParams->privRawISO, pmpMountParams->fISOVol,
                                                                usCount);

                        } /* end for creation date */
                }

                /* Attach the Volume Descriptor to the VOL_DEP_DATA structure */
                pmpMountParams->pvddVolData->pvdVolDesc = pvdVolDesc;

        } /* end if successful VOL_DESCRIPT */

#ifdef DEBUG
        else
        {
                dprintf ("\tMountCondenseVol:   Can't allocate memory\n");
        }
#endif

        return usRet;

} /* end MountCondenseVol */


/***    VolMount () -   Perform the mount operation
 *
 *  DESCRIPTION
 *
 *      This function performs the actual work of the mount process.
 *      It initializes the volume dependent area, it performs the hack
 *      to get around the kernel sending invalid sector size.  It CRC's
 *      the volume descriptor and returns that value and the volume ID via
 *      the volume independent area.
 *
 *      The actual mount process looks for a valid volume descriptor and
 *      if found allocates and stores a condensed volume descriptor.  It
 *      also reads in the path table.
 *
 *      If successful, then the self directory entry in the root directory
 *      is copied into the volume descriptor.
 *
 *
 *  ENTRY
 *
 *      hVPB        =   Volume handle.
 *      pvpfsi      =   Pointer to volume independent data.
 *      pvddVolData =   Pointer to volume dependent data.
 *
 *
 *  EXIT
 *
 *      NO_ERROR if successful mount.
 *      Return value from allocation routines if failures.
 *      Return value from ValidID if failure.
 *      Return value from MountCondenseVol if failure.
 *
 */

USHORT VolMount (hVPB, pvpfsi, pvddVolData)
SHANDLE             hVPB;
PVPFSI              pvpfsi;
PVOL_DEP_DATA       pvddVolData;
{
        USHORT          usRet;
        PMOUNT_PARAMS   pmpMountParams;
        PPATH_ENTRY     ppeRootDirPE;

        /*
         *  Check the sector size to see if we can handle it.
         *  We reject 0 or any value greater than SECTOR_SIZE.  Also
         *  any value which does not divide evenly into SECTOR_SIZE.
         */
        if (!pvpfsi->vpi_bsize  ||
                (pvpfsi->vpi_bsize > SECTOR_SIZE) ||
                (SECTOR_SIZE % pvpfsi->vpi_bsize))
        {
#ifdef DEBUG
                dprintf ("\tVolMount:  Bad sector size  %d\n", pvpfsi->vpi_bsize);
#endif

                return ERROR_NOT_SUPPORTED;
        }

        /* Initialize the volume dependent area */
        pvddVolData->pvdVolDesc       = NULL;
        pvddVolData->pdeRootDir       = NULL;
        pvddVolData->pptPathTable     = NULL;
        pvddVolData->pblSectorList    = NULL;
        pvddVolData->plsbPathTable    = NULL;
        pvddVolData->plsbBufList      = NULL;

        /* Allocate the parameter structure, return error if failure */
        if (!(usRet = GetMountParams (&pmpMountParams)))
        {

                /* Allocate the path entry structure for the root directory */
                if (!(usRet = GetPathEntry (&ppeRootDirPE)))
                {

                        /*
                         *  Allocate and attach the LIST_SEM_BLK for the path table
                         *  and the buflist.  Also allocate and attach the DE for the
                         *  root directory.
                         */
                        if (!(  (usRet = GetListSemBlk (&pvddVolData->plsbPathTable)) ||
                                        (usRet = GetListSemBlk (&pvddVolData->plsbBufList)) ||
                                        (usRet = GetDirEntry   (&pvddVolData->pdeRootDir))))
                        {
                                /* Initialize the parameter structure */
                                pmpMountParams->pvddVolData   = pvddVolData;
                                pmpMountParams->hVPB          = hVPB;

                                /* This check is for drivers that don't return the proper sector size */
                                /* This can be dangerous if sector size is smaller */
                                /*    usSectorSize = ((pvpfsi->vpi_bsize != 512) ? SECTOR_SIZE : 512);*/

                                /* What is the sector size and sector base for this volume */
                                pvddVolData->cbSectorSize = pvpfsi->vpi_bsize;
                                pvddVolData->usSectorBase = SECTOR_SIZE/pvpfsi->vpi_bsize;

                                /* Check for a valid volume descriptor */
                                /* Continue the mount process if no errors */
                                if (!(usRet = ValidVD (pmpMountParams)))
                                {
                                        pmpMountParams->privRawISO = (PRAW_ISO_VTOC)
                                                                                                OVERLAY_STRUCT (pmpMountParams->pbBuf, 0);

                                        /* crc the 2K volume, copy the first 11 bytes of the vol id */
                                        pvpfsi->vpi_vid = crc32 ((PCHAR)
                                                                                                OVERLAY_STRUCT (pmpMountParams->pbBuf,
                                                                                                                                VOL_DESC_OFF),
                                                                                                                                SECTOR_SIZE);

                                        CopyWithNull (pvpfsi->vpi_text,
                                                                RV_VOL_ID  (   pmpMountParams->privRawISO,
                                                                                                pmpMountParams->fISOVol),
                                                                                                VPSFI_ID_LEN);

                                        /* Check string for validity */
                                        CleanStringDBCS (pvpfsi->vpi_text, VPSFI_ID_LEN);

                                        /* Try to copy the volume descriptor */
                                        /* If successful then continue with Path Table */
                                        if (!(usRet = MountCondenseVol (pmpMountParams)))
                                        {
                                                /* Add the path table size to the CRC */
                                                pvpfsi->vpi_vid +=
                                                        pmpMountParams->pvddVolData->pvdVolDesc->cbPTSize;

                                                /* Try to recover the Path Table */
                                                if (!(usRet = RecoverPathTable (pmpMountParams)))
                                                {
                                                        /* Perform last check for duplicate  handle */
                                                        /* Free the volume dependent data if found */
                                                        if (!(FSH_FINDDUPHVPB (hVPB, &pmpMountParams->hOldHVPB)))
                                                        {
                                                                FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                                                dprintf ("\tVolMount:  Duplicate Found\n");
#endif

                                                        } /* end if duplicate found */

                                                        /* Else attach a BufList structure and get root DE */
                                                        else if (!(usRet = GetBufList (&pvddVolData->pblSectorList)))
                                                        {
                                                                /* Point to the semaphore area in the Vol Dep Data */
                                                                pvddVolData->pblSectorList->plsbSemBlk =
                                                                        pvddVolData->plsbBufList;

                                                                /* Get the root DE in the Path Table */
                                                                if (    (usRet = PathEntryNum (
                                                                                                                pvddVolData,
                                                                                                                ROOT_DIR_NUM,
                                                                                                                ppeRootDirPE,
                                                                                                                hVPB))
                                                                                ||
                                                                                /*  Call GetFirstDE to get the root DE */
                                                                                (usRet = GetFirstDE (
                                                                                                                pvddVolData->pdeRootDir,
                                                                                                                ppeRootDirPE,
                                                                                                                pvddVolData,
                                                                                                                hVPB,
                                                                                                                NULL,
                                                                                                                NULL)))
                                                                {
                                                                        FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                                                        dprintf ("\tVolMount:   ERROR, BufList  --  %d\n", usRet);
#endif

                                                                } /* end if error in getting RootDE */

                                                        } /* end else if attach Buflist and RootDE */

                                                        /* Else buflist alloc failed */
                                                        else
                                                        {
                                                                FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                                                dprintf (   "\tVolMount:   GetBufList  --  %d\n",
                                                                                        usRet);
#endif
                                                        } /* end if buflist alloc fails */

                                                } /* end if successful (Path Table) */

                                                /* Else error in getting Path Table */
                                                else
                                                {
                                                        FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                                        dprintf ("\tVolMount:   ERROR, PathTable -- %d\n",
                                                                        usRet);
#endif
                                                }

                                        } /* end if successful MountCondense volume */

                                        /* Else MountCondenseVol failed */
                                        else
                                        {
                                                /* Free the volume structures */
                                                FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                                dprintf (   "\tVolMount:   MountCondense  --  %d\n",
                                                                        usRet);
#endif
                                        }

                                        /* Free up the buffer with the volume */
                                        FREE_BUF (pmpMountParams->pbBuf);


                                } /* end if successful (vol descript) */

                                else
                                {
                                        /* Free the volume data */
                                        FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                        dprintf ("\tVolMount:   ERROR, VolDesc -- %d\n",
                                                                usRet);
#endif
                                }

                        } /* end if allocated volume structures */

                        /* Else free the vol dependent data */
                        else
                        {
                                FreeVolDepData (pvddVolData);

#ifdef DEBUG
                                dprintf (   "\tVolMount:   Volume structures alloc -- %d\n",
                                                        usRet);
#endif
                        } /* end else volume allocations failed */

                        /* Release the PATH_ENTRY structure */
                        FREE_PATH_ENTRY (ppeRootDirPE);

                } /* end if successful PE allocation */

#ifdef DEBUG
                else
                {
                        dprintf ("\tVolMount:  GetPathEntry failed  --  %d\n", usRet);
                }
#endif

                /* Release the MOUNT_PARAMS structure */
                FREE_MOUNT_PARAMS (pmpMountParams);

        } /* end if mount param structure allocation successful */

#ifdef DEBUG
        /* Else print error message */
        else
        {
                dprintf ("\tVolMount:   GetMountParams  %d\n", usRet);

        } /* end else parameter structure allocation fails */
#endif

        return usRet;

} /* end VolMount */

