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

/*
 *  MEMALLOC.C
 *
 *    DESCRIPTION
 *
 *      Allocate structures from the various free lists.
 *
 *      Also maintains linked lists of sectors in use on both a system
 *      basis and a per-volume basis.
 *
 *
 *    FUNCTIONS DEFINED
 *
 *      AllocBuf ()         -   Allocate a BUF structure.
 *      GetSearchArray ()   -   Get search string struct from free list.
 *      GetBufList ()       -   Get BUF_LIST struct from free list.
 *      GetPathEntry ()     -   Get PATH_ENTRY struct from free list.
 *      GetVolDesc ()       -   Get VOL_DESC structure from the free list.
 *      GetDirEntry ()      -   Get DIR_ENTRY struct from the free list.
 *      GetRawDirRec ()     -   Get RAW_DIR_REC struct from the free list.
 *      GetPathTable ()     -   Get PATH_TABLE struct from the free list.
 *      GetRawPathISO ()    -   Get RAW_PATH_ISO struct from the free list.
 *      GetFindBufLoc ()    -   Get FIND_BUF_LOC struct from the free list.
 *      GetMountParams ()   -   Get MOUNT_PARAMS struct from the free list.
 *      GetFfrstParams ()   -   Get FFRST_PARAMS struct from the free list.
 *      GetStringBuf ()     -   Get STRING_BUF struct from the free list.
 *      GetListSemBlk ()    -   Get LIST_SEM_BLK struct from the free list.
 *
 *
 *    REVISION HISTORY (in reverse chronological order)
 *    -----------------------------------------------------------------------
 *    9/26/92   Frank Schroeder Added 'GetRawDirRec' routine.
 *
 *    4/19/90   Brian Andrew    Added 'GetListSemBlk' routine.
 *
 *    4/12/90   Brian Andrew    Removed 'ReadBuf', 'FindBuf', 'MultiSectors'.
 *                              Removed 'RemovePTSec', 'RemoveListSec'.
 *
 *    4/9/90    Brian Andrew    Initialized Header information in BUF_LIST
 *                              and PATH_TABLE structures.
 *
 *    4/9/90    Brian Andrew    Added GetStringBuf routine.
 *
 *    4/8/90    Brian Andrew    Added support for semaphore access to lists
 *                              of free data structures.
 *
 *    3/30/90   Brian Andrew    Allocated non-swappable memory in
 *                              MultiSectors to test allocation problem
 *                              in Cruiser.
 *
 *    11/21/89  Brian Andrew    Removed check for reading at least one
 *                              sector in MultiSectors.  OS not
 *                              setting to 0 if error encountered.
 *
 *    11/16/89  Brian Andrew    Added memory allocation for FFRST_PARAMS
 *                              structure.  Added GetFfrstParams.
 *
 *    11/16/89  Brian Andrew    Added memory allocation for MOUNT_PARAMS
 *                              structure.  Added GetMountParams.
 *
 *    11/15/89  Brian Andrew    Added memory structure for FindBuf.  Modified
 *                              FindBuf, added GetFindBufLoc.
 *
 *    11/14/89  Brian Andrew    Added GetRawPathISO to support stack
 *                              optimization for RecoverPathTable.
 *
 *    10/31/89  Brian Andrew    Added heap support for BUF_LIST.
 *
 *    10/10/89  Brian Andrew    Added last sector param to FindBuf.
 *
 *    9/22/89   Brian Andrew    Added STAT parameter to FindBuf.
 *
 *    8/22/89   Brian Andrew    Made RemovePTSec a FAR call.
 *
 *    8/12/89   Brian Andrew    Initiial function descriptions.
 *
 *    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 "cdfs.h"
#include "sem.h"
#include "path.h"
#include "vol.h"
#include "file.h"
#include "buffer.h"
#include "mem.h"
#include "heap.h"
#include "memory.h"
#include "message.h"

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

#include "fsdata.h"
#include "pr_memin.h"
#include "pr_fsini.h"
#include "pr_heap.h"
#include "pr_cache.h"
#include "stdlib.h"

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


USHORT AllocBuf (ppbBuf)
PPBUF    ppbBuf;
{
        USHORT  usRet;

        SEM_REQ (sBuf);

        if (pbGlobalBuf)
        {
                *ppbBuf = pbGlobalBuf;
                pbGlobalBuf = (PBUF)
                                                (((PGEN_LLIST) pbGlobalBuf)->pglNextGenLList);
                SEM_CLEAR (sBuf);

                usRet = NO_ERROR;

        } /* end if list exists */

        else
        {
                SEM_CLEAR (sBuf);

                usRet = GetHeapChunk ((PCHAR FAR *) ppbBuf,
                                                                sizeof (BUF));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*ppbBuf)->pblBufOwner = NULL;
                (*ppbBuf)->fBLOwns = FALSE;
                (*ppbBuf)->cUsers = 0;
                (*ppbBuf)->sSector = NULL;
                (*ppbBuf)->pbPrevBUF = NULL;
                (*ppbBuf)->pbNextBUF = NULL;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tAllocBuf:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end AllocBuf */

/*
 ***    GetSearchArray  ()   --  Get a SEARCH_STRING structure from the free
 *               list.
 *
 *
 *
 */

USHORT GetSearchArray (ppssString)
PPSEARCH_STRING     ppssString;
{
        USHORT  usRet;

        SEM_REQ (sSearchArray);

        if (pssGlobalSS)
        {
                *ppssString = pssGlobalSS;
                pssGlobalSS = (PSEARCH_STRING)
                                                (((PGEN_LLIST) pssGlobalSS)->pglNextGenLList);
                SEM_CLEAR (sSearchArray);

                usRet = NO_ERROR;

        } /* end if list exists */

        else
        {
                SEM_CLEAR (sSearchArray);

                usRet = GetHeapChunk ((PCHAR FAR *) ppssString,
                                                                sizeof (SEARCH_STRING));

        } /* end else get another chunk */

        if (!usRet)
        {
                *((*ppssString)->szName) = '\0';

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetSearchArray:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetSearchArray */


/*
 ***    GetBufList ()   --  Get a BUF_LIST structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetBufList (ppblBufList)
PPBUF_LIST      ppblBufList;
{
        USHORT  usRet;

        SEM_REQ (sBufList);

        if (pblGlobalBL)
        {
                *ppblBufList = pblGlobalBL;
                pblGlobalBL = (PBUF_LIST)
                                                (((PGEN_LLIST) pblGlobalBL)->pglNextGenLList);
                SEM_CLEAR (sBufList);

                usRet = NO_ERROR;

        } /* end if list exists */

        else
        {
                SEM_CLEAR (sBufList);

                usRet = GetHeapChunk ((PCHAR FAR *) ppblBufList,
                                                                sizeof (BUF_LIST));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*ppblBufList)->snSectNum = NULL_BUF;
                (*ppblBufList)->pbBuf = NULL;
                (*ppblBufList)->pblPrev = NULL;
                (*ppblBufList)->pblNext = NULL;
                (*ppblBufList)->usCountPend = 0;
                (*ppblBufList)->sHeaderSem = 0;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetBufList:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetBufList */


/*
 ***    GetPathEntry ()   --  Get a PATH_ENTRY structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetPathEntry (pppePathEntry)
PPPATH_ENTRY     pppePathEntry;
{
        USHORT  usRet;

        SEM_REQ (sPathEntry);

        if (ppeGlobalPE)
        {
                *pppePathEntry = ppeGlobalPE;
                ppeGlobalPE = (PPATH_ENTRY)
                                                (((PGEN_LLIST) ppeGlobalPE)->pglNextGenLList);

                SEM_CLEAR (sPathEntry);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sPathEntry);

                usRet = GetHeapChunk ((PCHAR FAR *) pppePathEntry,
                                                                sizeof (PATH_ENTRY));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*pppePathEntry)->lbLocDir = 0;
                (*pppePathEntry)->clbXAR_Len = 0;
                (*pppePathEntry)->pnParentNum = 0;
                *((*pppePathEntry)->sDirID) = '\0';
                (*pppePathEntry)->pdeDirEntry = NULL;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetPathEntry:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetPathEntry */


/*
 ***    GetVolDesc ()   --  Get a VOL_DESC structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetVolDesc (ppvdVolDesc)
PPVOL_DESC       ppvdVolDesc;
{
        USHORT  usRet;

        SEM_REQ (sVolDesc);

        if (pvdGlobalVD)
        {
                *ppvdVolDesc = pvdGlobalVD;
                pvdGlobalVD = (PVOL_DESC)
                                                (((PGEN_LLIST) pvdGlobalVD)->pglNextGenLList);

                SEM_CLEAR (sVolDesc);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sVolDesc);

                usRet = GetHeapChunk ((PCHAR FAR *) ppvdVolDesc,
                                                                sizeof (VOL_DESC));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetVolDesc:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetVolDesc */


/*
 ***    GetDirEntry ()   --  Get a DIR_ENTRY structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetDirEntry (ppdeDirEntry)
PPDIR_ENTRY     ppdeDirEntry;
{
        USHORT  usRet;

        SEM_REQ (sDirEntry);

        if (pdeGlobalDE)
        {
                *ppdeDirEntry = pdeGlobalDE;
                pdeGlobalDE = (PDIR_ENTRY)
                                                (((PGEN_LLIST) pdeGlobalDE)->pglNextGenLList);

                SEM_CLEAR (sDirEntry);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sDirEntry);

                usRet = GetHeapChunk ((PCHAR FAR *) ppdeDirEntry,
                                                                sizeof (DIR_ENTRY));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*ppdeDirEntry)->snLastSectorFile = NULL_BUF;
                (*ppdeDirEntry)->szFileID[0] = '\0';
                (*ppdeDirEntry)->cbFileIDLen = 0;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetDirEntry:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetDirEntry */


/*
 ***    GetRawDirRec ()   --  Get a RAW_DIR_REC structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetRawDirRec (pprdrRawDirRec)
PPRAW_DIR_REC     pprdrRawDirRec;
{
        USHORT  usRet;

        SEM_REQ (sRawDirRec);

        if (prdrGlobalRDR)
        {
                *pprdrRawDirRec = prdrGlobalRDR;
                prdrGlobalRDR = (PRAW_DIR_REC)(((PGEN_LLIST) prdrGlobalRDR)->pglNextGenLList);

                SEM_CLEAR (sRawDirRec);

                usRet = NO_ERROR;

        } /* end if list exists */

        else
        {
                SEM_CLEAR (sRawDirRec);

                usRet = GetHeapChunk ((PCHAR FAR *) pprdrRawDirRec,sizeof (RAW_DIR_REC));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*pprdrRawDirRec)->cbDirLen = '\0';

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetRawDirRec:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetRawDirRec */


/*
 ***    GetPathTable ()   --  Get a PATH_TABLE structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetPathTable (ppptPathTable)
PPPATH_TABLE        ppptPathTable;
{
        USHORT  usRet;

        SEM_REQ (sPathTable);

        if (pptGlobalPT)
        {
                *ppptPathTable = pptGlobalPT;
                pptGlobalPT = (PPATH_TABLE)
                                                (((PGEN_LLIST) pptGlobalPT)->pglNextGenLList);

                SEM_CLEAR (sPathTable);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sPathTable);

                usRet = GetHeapChunk ((PCHAR FAR *) ppptPathTable,
                                                                sizeof (PATH_TABLE));

        } /* end else get another chunk */

        if (!usRet)
        {
                (*ppptPathTable)->snSectNum = NULL_BUF;
                (*ppptPathTable)->pbBuf = NULL;
                (*ppptPathTable)->pptPrevPTSect = NULL;
                (*ppptPathTable)->pptNextPTSect = NULL;
                (*ppptPathTable)->soPTOffset1 = 0;
                (*ppptPathTable)->pnDirNum1 = 0;
                (*ppptPathTable)->pnDirNum2 = 0;
                (*ppptPathTable)->usCountPend = 0;
                (*ppptPathTable)->sHeaderSem = 0;

                /* Clear the fields in the path entry structure */
                (*ppptPathTable)->pePathEntry.lbLocDir = 0;
                (*ppptPathTable)->pePathEntry.clbXAR_Len = 0;
                (*ppptPathTable)->pePathEntry.pnParentNum = 0;
                (*ppptPathTable)->pePathEntry.sDirID[0] = '\0';
                (*ppptPathTable)->pePathEntry.pdeDirEntry = NULL;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetPathTable:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetPathTable */


/*
 ***    GetRawPathISO ()    --  Get a RAW_PATH_ISO structure from the free
 *              list.
 *
 *
 *
 */

USHORT GetRawPathISO (pprpiRawPath)
PPRAW_PATH_ISO      pprpiRawPath;
{
        USHORT  usRet;

        SEM_REQ (sRawPathISO);

        if (prpiGlobalRPI)
        {
                *pprpiRawPath = prpiGlobalRPI;
                prpiGlobalRPI = (PRAW_PATH_ISO)
                                                (((PGEN_LLIST) prpiGlobalRPI)->pglNextGenLList);

                SEM_CLEAR (sRawPathISO);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sRawPathISO);

                usRet = GetHeapChunk ((PCHAR FAR *) pprpiRawPath,
                                                                sizeof (RAW_PATH_ISO));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetRawPathISO:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetRawPathISO */


/*
 ***    GetFindBufLoc ()    --  Get a FIND_BUF_LOC structure from the free
 *              list.
 *
 */

USHORT GetFindBufLoc (ppfblFindBuf)
PPFIND_BUF_LOC      ppfblFindBuf;
{
        USHORT  usRet;

        SEM_REQ (sFindBufLoc);

        if (pfblGlobalFBL)
        {
                *ppfblFindBuf = pfblGlobalFBL;
                pfblGlobalFBL = (PFIND_BUF_LOC)
                                                (((PGEN_LLIST) pfblGlobalFBL)->pglNextGenLList);

                SEM_CLEAR (sFindBufLoc);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sFindBufLoc);

                usRet = GetHeapChunk ((PCHAR FAR *) ppfblFindBuf,
                                                                sizeof (FIND_BUF_LOC));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetFindBufLoc:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetFindBufLoc */


/*
 ***    GetMountParams ()    --  Get a MOUNT_PARAMS structure from the free
 *              list.
 *
 */

USHORT GetMountParams (ppmpMountParams)
PPMOUNT_PARAMS      ppmpMountParams;
{
        USHORT  usRet;

        SEM_REQ (sMountParams);

        if (pmpGlobalMP)
        {
                *ppmpMountParams = pmpGlobalMP;
                pmpGlobalMP = (MOUNT_PARAMS FAR *)
                                                (((PGEN_LLIST) pmpGlobalMP)->pglNextGenLList);

                SEM_CLEAR (sMountParams);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sMountParams);

                usRet = GetHeapChunk ((PCHAR FAR *) ppmpMountParams,
                                                                sizeof (MOUNT_PARAMS));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetMountParams:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetMountParams */


/*
 ***    GetFfrstParams ()    --  Get a FFRST_PARAMS structure from the free
 *              list.
 *
 */

USHORT GetFfrstParams (ppffpFFirstParams)
PPFFRST_PARAMS      ppffpFFirstParams;
{
        USHORT  usRet;

        SEM_REQ (sFFrstParams);

        if (pffpGlobalFFP)
        {
                *ppffpFFirstParams = pffpGlobalFFP;
                pffpGlobalFFP = (PFFRST_PARAMS)
                                                (((PGEN_LLIST) pffpGlobalFFP)->pglNextGenLList);

                SEM_CLEAR (sFFrstParams);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sFFrstParams);

                usRet = GetHeapChunk ((PCHAR FAR *) ppffpFFirstParams,
                                                                sizeof (FFRST_PARAMS));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetFfrstParams:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetFfrstParams */


/*
 ***    GetStringBuf ()    --  Get a STRING_BUF structure from the free
 *              list.
 *
 */

USHORT GetStringBuf (ppsbStringBuf)
PPSTRING_BUF      ppsbStringBuf;
{
        USHORT  usRet;

        SEM_REQ (sStringBuf);

        if (psbGlobalSB)
        {
                *ppsbStringBuf = psbGlobalSB;
                psbGlobalSB = (PSTRING_BUF)
                                                (((PGEN_LLIST) psbGlobalSB)->pglNextGenLList);

                SEM_CLEAR (sStringBuf);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sStringBuf);

                usRet = GetHeapChunk ((PCHAR FAR *) ppsbStringBuf,
                                                                sizeof (STRING_BUF));

        } /* end else get another chunk */

#ifdef DEBUG
        if (usRet)
        {
                dprintf ("\tGetStringBuf:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetStringBuf */


/*
 ***    GetListSemBlk ()    --  Get a LIST_SEM_BLK structure from the free
 *              list.
 *
 */

USHORT GetListSemBlk (pplsbSemBlk)
PPLIST_SEM_BLK      pplsbSemBlk;
{
        USHORT  usRet;

        SEM_REQ (sSemBlk);

        if (plsbGlobalLSB)
        {
                *pplsbSemBlk = plsbGlobalLSB;
                plsbGlobalLSB = (PLIST_SEM_BLK)
                                                (((PGEN_LLIST) plsbGlobalLSB)->pglNextGenLList);

                SEM_CLEAR (sSemBlk);

                usRet = NO_ERROR;

        } /* end if  list exists */

        else
        {
                SEM_CLEAR (sSemBlk);

                usRet = GetHeapChunk ((PCHAR FAR *) pplsbSemBlk,
                                                                sizeof (LIST_SEM_BLK));

        } /* end else get another chunk */

        /* Initialize if no error */
        if (!usRet)
        {
                (*pplsbSemBlk)->usCountRead = 0;
                (*pplsbSemBlk)->usCountWrite = 0;
                (*pplsbSemBlk)->sBlockSem = 0;
                (*pplsbSemBlk)->sListSem = 0;

        } /* end if no error */

#ifdef DEBUG
        else
        {
                dprintf ("\tGetListSemBlk:  Not enough memory\n");
        }
#endif

        return usRet;

} /* end GetListSemBlk */


