File:  [WindowsNT SDKs] / ntddk / src / print / lib / fontfile.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/******************************* MODULE HEADER ******************************
 * fontfile.c
 *      Functions associated with generating the combined font file
 *      used with NT printer drivers.  This handles the mechanics of
 *      creating/adding/deleting data in the file.  No attempt is made
 *      to understand the contents of the file.  That is left to
 *      individual drivers.
 *
 *  Copyright (C) 1992 - 1993  Microsoft Corportation.
 *
 *****************************************************************************/


#include        <stddef.h>
#include        <windows.h>

#include        "fontfile.h"            /* File layout details */
#include        "fontgen.h"             /* Globally visible components */
#include        "libproto.h"            /* bWrite() proto */



/*
 *   Local functions.
 */


BOOL  bGetFileHDR( HANDLE, FF_HEADER * );
BOOL  bGetRecHDR( HANDLE, FF_REC_HEADER *, DWORD );
BOOL  bFixInit( HANDLE );               /* Initialise new Fixed file */
void  vFIClean( FID * );                /* Clean up any mess */
BOOL  bDelList( FID *, int * );         /* Delete fonts in current set */
BOOL  bAddFList( FID *, FONTLIST * );   /* Add new fonts to existing */




/******************************* Function Header ****************************
 * pFIOpen()
 *      Function to initialize the internal operations for the font installer
 *      single font file building operations.  The value returned is passed
 *      to other functions here, giving them access to the data required
 *      to complete their tasks.
 *
 * RETURNS:
 *      Pointer to private data,  cast as a (void *);  0 on error.
 *
 * HISTORY:
 *  09:49 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Starting work on it.
 *
 ****************************************************************************/

FID *
pFIOpen( pwstrDataFile, hHeap )
PWSTR   pwstrDataFile;          /* Driver's data file name */
HANDLE  hHeap;                  /* Heap access */
{

    FID    *pFID;               /* For our convenience */
    PWSTR   pwstr;              /* For file name manipulation */

    int     iPtOff;             /* Location of . in file name */
    int     iSize;              /* Determine the size of things */


    /*
     *   Firstly allocate a FID structure from the heap.  We cannot use
     * a stack version as it needs to be persistent.
     */

    if( !(pFID = (FID *)HeapAlloc( hHeap, 0, sizeof( FID ) )) )
    {
#if  DBG
        DbgPrint( "Print!pvFIOpen:  HeapAlloc( FID ) fails!\n" );
#endif

        return  0;              /* Bad news */
    }

    memset( pFID, 0, sizeof( FID ) );           /* Easier clean up */

    pFID->hHeap = hHeap;        /* Keep it for later! */
    pFID->dwID = FID_ID;        /* Make sure we get our own back! */

    /*
     *    We want to generate some file names,  so determine the
     *  length of the input name,  and allocate that much storage
     *  for it.  We do not know what format the name is, so allow
     *  room at the end to add ".fi_": 5 WCHARs including the null.
     */

    iSize = (wcslen( pwstrDataFile ) + 5) * sizeof( WCHAR );

    if( !(pFID->pwstrCurName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) ||
        !(pFID->pwstrFixName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) ||
        !(pFID->pwstrVarName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) )
    {
    
#if  DBG
        DbgPrint( "Print!pvFIOpen: HeapAlloc( pwstrDataFile ) fails!\n" );
#endif
        vFIClean( pFID );

        return  0;
    }
    pwstr = pFID->pwstrCurName;         /* For stuffing around */

    wcscpy( pFID->pwstrCurName, pwstrDataFile );        /* Working copies */
    wcscpy( pFID->pwstrFixName, pwstrDataFile );
    wcscpy( pFID->pwstrVarName, pwstrDataFile );


    /*  Scan from RHS looking for '.': PRESUME THERE IS ONE! */
    iPtOff = wcslen( pwstr );

    while( --iPtOff > 0 )
    {
        if( *(pwstr + iPtOff) == (WCHAR)'.' )
            break;
    }

    if( iPtOff <= 0 )
    {
        iPtOff = wcslen( pwstr );               /* Presume none! */
        *(pwstr + iPtOff) = L'.';
    }
    ++iPtOff;           /* Skip the period */


    
    /*  Generate all 3 names & open the existing file  */
    wcscpy( pFID->pwstrCurName + iPtOff, FILE_FONTS );
    wcscpy( pFID->pwstrFixName + iPtOff, TFILE_FIX );
    wcscpy( pFID->pwstrVarName + iPtOff, TFILE_VAR );


    pFID->hCurFile = CreateFileW( pFID->pwstrCurName, GENERIC_READ,
                                        FILE_SHARE_READ,
                                        NULL, OPEN_EXISTING, 0, 0 );

    /*
     *   Repeat for the two new files:  note that we want to create these,
     * truncate any existing file,  and allow no other access to them
     * while we are manipulating them.  They should be invisible.
     */


    pFID->hFixFile = CreateFileW( pFID->pwstrFixName,
                                        GENERIC_READ | GENERIC_WRITE, 0, NULL,
                                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                                        pFID->hCurFile );

    if( pFID->hFixFile == INVALID_HANDLE_VALUE )
    {
        /*  Bad news  */
#if  DBG
        DbgPrint( "Print!bFIOpen: Fixed file initialisation failure\n" );
#endif


        vFIClean( pFID );

        return  0;
    }


    pFID->hVarFile = CreateFileW( pFID->pwstrVarName,
                                        GENERIC_READ | GENERIC_WRITE, 0, NULL,
                                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                                        pFID->hCurFile );

    if( pFID->hVarFile == INVALID_HANDLE_VALUE )
    {
#if  DBG
        DbgPrint( "Print!bFIOpen: Var file creation failure\n" );
#endif


        vFIClean( pFID );

        return  0;
    }

    return  pFID;
}

/****************************** Function Header *****************************
 * bFIClose
 *      Close up operations on the font installer file.  This involves
 *      amalgamating the Fix and Var files,  updating the overall header
 *      and renaming the file after deleting the old one.
 *
 * RETURNS:
 *      TRUE/FALSE - FALSE if any operation fails.
 *
 * HISTORY:
 *  15:01 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Gotta start somewhere
 *
 ***************************************************************************/

BOOL
bFIClose( pFID, bUpdate )
FID    *pFID;           /* The file collection to close */
BOOL    bUpdate;        /* True to make new file THE file */
{

    long   lSize;               /* Bytes copied from variable file */

    
    FF_HEADER  ffh;             /* The overall file header */



    if( pFID->dwID != FID_ID )
    {
#if DBG
        DbgPrint( "Print!bFIClose():  invalid pFID" );
#endif

        return  FALSE;
    }


    /*
     *   If bUpdate,  then reorganise the files:  the existing file is
     * removed, the Var file is appended to the Fix file,  and that
     * composite file is made the new "existing" file.
     */


    if( !bUpdate )
    {
        /*  No updating is to be done  */
        vFIClean( pFID );                       /* Does all the dirty work */

        return  TRUE;                           /* By definition */
    }

    /*
     *   Update is ON!  First read the header from the fixed file, then
     * fill in the missing details.  This amounts to the location of
     * the start of the variable length data in the file.
     */

    if( !bGetFileHDR( pFID->hFixFile, &ffh ) )
    {
        vFIClean( pFID );

        return  FALSE;
    }

    /*
     *   Need to know the size of the fixed file to put in the header.
     */

    lSize = (long)SetFilePointer( pFID->hFixFile, 0, NULL, FILE_END );

    lSize = (lSize + 3) & ~0x3;         /* DWORD multiple */

    ffh.ulVarData = lSize;

    SetFilePointer( pFID->hFixFile, lSize, NULL, FILE_BEGIN );
    SetFilePointer( pFID->hVarFile, 0, NULL, FILE_BEGIN );

    ffh.ulVarSize = lSize = lFICopy( pFID->hFixFile, pFID->hVarFile );
    if( lSize < 0 )
    {
        /*   Some sort of error */
        vFIClean( pFID );

        return  FALSE;
    }

    if( lSize == 0 )
        ffh.ulVarData = 0;              /* NONE! */

    /*
     *   Now write the header back out.
     */

    SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );
    if( !bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) ) )
    {
        /*  Too bad:  throw it all away.  */
        vFIClean( pFID );

        return  FALSE;
    }
    
    /*
     *   No longer need the file handles,  so close them,  and set
     * the values to illegal so that we will not try to free them later.
     * We can also delete the variable part of the file,  since that
     * is now appended to the end of the fixed file.
     */

    CloseHandle( pFID->hFixFile );              /* No longer needed */
    pFID->hFixFile = INVALID_HANDLE_VALUE;      /* Won't be cleaned up */

    CloseHandle( pFID->hVarFile );              /* No longer need this file */
    pFID->hVarFile = INVALID_HANDLE_VALUE;      /* Won't be cleaned up */


    DeleteFileW( pFID->pwstrVarName );


    /*
     *   Now delete the existing file and rename the Fix file to the
     *  proper name!
     */


    if( pFID->hCurFile != INVALID_HANDLE_VALUE )
    {
        /*  Have a current file,  so delete it, close our handle */
        CloseHandle( pFID->hCurFile );
        pFID->hCurFile = INVALID_HANDLE_VALUE;     /* Is now */

        if( !DeleteFileW( pFID->pwstrCurName ) )
        {
            vFIClean( pFID );

            return  FALSE;
        }
    }

    /* RENAME */
    if( !MoveFileW( pFID->pwstrFixName, pFID->pwstrCurName ) )
    {
        /*  BAD NEWS:  we have lost the lot! */

        vFIClean( pFID );

        return  FALSE;
    }

    /*
     *  Clean up whatever is left.
     */

    vFIClean( pFID );


    return  TRUE;
}

/******************************** Function Header ***************************
 * bFIUpdate
 *      Called to integrate changes to the font file.  Caller may delete
 *      existing fonts and/or add new ones.  The deleted fonts are
 *      passed as an array of integers, each being an index into the
 *      existing fonts.  The first is a count of the number of
 *      index values following; then comes the zero based index value.
 *      New fonts are passed as a linked list of type FONTLIST.
 * NOTE:  The master font file is NOT updated by this call.
 *
 * RETURNS:
 *      TRUE/FALSE;  FALSE leaves no permanent changes.
 *
 * HISOTRY:
 *  12:59 on Tue 25 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      First version.
 *
 ****************************************************************************/

BOOL
bFIUpdate( pFID, piDel, pFList )
FID        *pFID;                       /* Access to our data */
int        *piDel;                      /* Array of fonts to delete */
FONTLIST   *pFList;                     /* Fonts to add */
{

    /*
     *    Not much to do!   First step is to copy the fixed part of the
     * file to our new fixed file,  deleting fonts as we go. This also
     * splits off the variable portion.  Then add whatever new fonts are
     * to be added.  We do not amalgamate the file:  that is done at
     * bFIClose() time,  giving the caller the chance to abort the whole
     * operation.
     */

    if( pFID->dwID != FID_ID )
    {
#if DBG
        DbgPrint( "Print!bFIUpdate: pFID is invalid" );
#endif

        return FALSE;
    }


    if( !bDelList( pFID, piDel ) )
        return  FALSE;

    if( !bAddFList( pFID, pFList ) )
        return  FALSE;

    return  TRUE;               /* Made it AOK */
}


/****************************** Function Header ******************************
 * bDelList
 *      Delete the nominated fonts from the master font file.  DOES NOT UPDATE
 *      THE MASTER FILE.  The fonts are nominated by as an array of ints,
 *      the first of which is a count of the number of ints following.
 *      These values are zero based and represent the number of the font
 *      in sequence in the file.
 *
 * RETURNS:
 *      TRUE/FALSE
 *
 * HISTORY:
 *  13:02 on Tue 25 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      First version to do something.
 *
 *****************************************************************************/

BOOL
bDelList( pFID, piDel )
FID    *pFID;           /* Access to our stuff */
int    *piDel;          /* A -1 terminated array of font indices to delete */
{


    ULONG     ulRec;            /* Loop through the records */
    DWORD     dwHdrPosn;        /* Position within the file */
    DWORD     dwFixPosn;        /* Write position in fixed file */
    DWORD     dwVarPosn;        /* Absolute position within variable part */
    int       iDelLeft;         /* Number of deletion choices left */
    int       iSkip;            /* Number we have dropped */

    BOOL      bDelete;          /* True if this font to be deleted */


    FF_HEADER   ffh;            /* Contains sizes! */
    FF_REC_HEADER  ffrh;

    /*
     *   Do we have any to delete?
     */

     
    if( pFID->hCurFile == INVALID_HANDLE_VALUE )
    {
        /*   NO existing file,  so create a new empty one!  */

        return   bFixInit( pFID->hFixFile );
    }

    if( !bGetFileHDR( pFID->hCurFile, &ffh ) )
        return  FALSE;

    if( piDel == NULL || *piDel <= 0 )
    {
        /*  Just split the master file into two: fixed and variable parts */

        LONG   lSize;


        SetFilePointer( pFID->hCurFile, 0, NULL, FILE_BEGIN );

        lSize = sizeof( ffh ) + ffh.ulFixSize;

        if( lFInCopy( pFID->hFixFile, pFID->hCurFile, lSize ) != lSize ||
            lFInCopy( pFID->hVarFile, pFID->hCurFile, ffh.ulVarSize ) != 
                                                          (long)ffh.ulVarSize )
        {
#if  DBG
            DbgPrint( "Print!bDelList: file split fails\n" );
#endif

            return  FALSE;
        }

        return  TRUE;
    }

    /*
     *  Another speed up case is the other version:  deleting all fonts!
     */
    
    if( *piDel >= (int)ffh.ulRecCount )
    {
        /*  Simply create an empty file  */

        return  bFixInit( pFID->hFixFile );
    }

    /*
     *   Now determine which fonts to delete.  We do this the easy (but
     * slower) way, namely to process each record individually.  We
     * read the header,  determine whether to delete, and if not, then
     * copy the relevant portions to the output files.
     */

    dwHdrPosn = ffh.ulFixData;          /* Initial location */
    dwFixPosn = ffh.ulFixData;          /* Writing location in fixed file */
    dwVarPosn = ffh.ulVarData;          /* Starting location in variable */
    iSkip = 0;                          /* Count number we drop off */
    iDelLeft = *piDel;                  /* Number to delete */
    ffh.ulFixSize = 0;                  /* Count it as we copy */

    for( ulRec = 0; ulRec < ffh.ulRecCount; ++ulRec )
    {

        /*  First read the header to read the record size */

        if( !bGetRecHDR( pFID->hCurFile, &ffrh, dwHdrPosn ) )
            return  FALSE;                      /* SHOULD NOT HAPPEN */

        if( ffrh.ulNextOff == 0 )
        {
#if  DBG
            DbgPrint( "Print!bDelList: unexpected EOF record at #%ld\n",
                                                                    ulRec );
#endif

            break;
        }
        /*
         *   Is this on the delete list??
         */

        bDelete = FALSE;                /* Assume not */

        if( iDelLeft > 0 )
        {
            /*   Scan the list,  looking for this index  */
            int   iI;

            for( iI = 1; !bDelete && iI <= *piDel; ++iI )
            {
                if( *(piDel + iI) == (int)ulRec )
                {
                    bDelete = TRUE;
                    --iDelLeft;
                }
            }
        }

        if( bDelete )
        {
            /*  Skip this one,  so adjust offsets & counts.  */
            iSkip++;            /* Reduce count at the end. */
        }
        else
        {
            /*
             *   First step is to copy the variable part.  This is done
             * first as we need to update the data position within the
             * header record for the fixed part.  So copy now to find
             * out where it is being placed.
             */
            
            dwVarPosn = ffh.ulVarData + ffrh.ulVarOff;  /* Current file posn */

            if( ffrh.ulVarSize )
            {
                /*
                 *   Data exists,  so set file pointers.  There are two to
                 * set.  One is to position the variable data at the dword
                 * aligned end of the variable file,  the other is to
                 * set the position of the current file pointer to the
                 * correct location in that file.
                 */

                /*  First the new variable file */

                ffrh.ulVarOff = (GetFileSize( pFID->hVarFile, NULL ) +3) & ~0x3;
                SetFilePointer( pFID->hVarFile, ffrh.ulVarOff, NULL,
                                                                 FILE_BEGIN );

                /*  The current file's variable data */

                SetFilePointer( pFID->hCurFile, dwVarPosn, NULL, FILE_BEGIN );

                if( lFInCopy( pFID->hVarFile, pFID->hCurFile, ffrh.ulVarSize )
                                                != (long)ffrh.ulVarSize )
                {
#if  DBG
                    DbgPrint( 
                        "Print!bDelList: Write of variable data fails, rec #%ld\n",
                                                                 ulRec );
#endif

                    return  FALSE;
                }
            }

            /*
             *   Set the fixed file pointer.  First time this will skip
             * the file header we write out at the end.  Second and later
             * times,  it will ensure DWORD alignment of the header.
             */


            SetFilePointer( pFID->hCurFile, dwHdrPosn + sizeof( ffrh),
                                                         NULL, FILE_BEGIN );
            SetFilePointer( pFID->hFixFile, dwFixPosn, NULL, FILE_BEGIN );

            if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
            {
#if  DBG
                DbgPrint( "Print!bDelList: bWrite of new header, rec %ld\n",
                                                                      ulRec );
#endif

                return  FALSE;
            }

            /*  And also the actual data part!  */

            if( lFInCopy( pFID->hFixFile, pFID->hCurFile, ffrh.ulSize ) !=
                                                          (long)ffrh.ulSize )
            {
#if  DBG
                DbgPrint(
                    "Print!bDelList: Can't copy FIX part of file at rec #%ld\n",
                                                                 ulRec );
#endif

                return  FALSE;
            }
            dwFixPosn += ffrh.ulNextOff;                /* Next location */
            ffh.ulFixSize += sizeof( ffrh ) + ffrh.ulSize;

        }
        dwHdrPosn += ffrh.ulNextOff;
    }

    /*
     *   Need to write the trailing header to our file. This contains
     * a zero size, so that is really all that is important.
     */

    ffrh.ulNextOff = 0;

    if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
        return  FALSE;

    ffh.ulRecCount -= iSkip;            /* The number we dropped! */

    /*
     *   Rewrite the header record for the adding code.
     */

    SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );

    return  bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) );
}

/****************************** Function Header ******************************
 * bAddFList
 *      Add a list of new fonts to an existing font file.  This is
 *      called to add the data to our existing file.  File creation or
 *      shrinking is done elsewhere.
 *
 * RETURNS:
 *      Number of bytes written to the file; -1 for error.
 *
 * HISTORY:
 *  14:20 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Started working on it.
 *
 *****************************************************************************/

BOOL
bAddFList( pFID, pFList )
FID       *pFID;                /* Font installation data */
FONTLIST  *pFList;              /* The fonts to be added */
{

    DWORD     dwLoc;            /* File location of interest */
    DWORD     dwVarLoc;         /* Location in the variable data part */
    int       iSize;            /* Number of bytes written by user */
    int       iVarSize;         /* Size of variable length portion */


    FF_HEADER  ffh;             /* The overall file header */
    FF_REC_HEADER  ffrh;        /* Per record header */


    if( pFList == NULL )
        return  TRUE;           /* No data, no processing!  */

    /*
     *   First step is to step through the file, down the chain of
     * records until we reach the end. We append the data there: the
     * data consists of a record header plus whatever data the user
     * writes and tells us about. We also allow the user the option
     * of adding data to variable length part of the file.
     */

    if( !bGetFileHDR( pFID->hFixFile, &ffh ) )
        return  FALSE;


    /*   Can now read the file header - it WILL exist!  */
    dwLoc = ffh.ulFixData;

    while( bGetRecHDR( pFID->hFixFile, &ffrh, dwLoc ) && ffrh.ulNextOff )
        dwLoc += ffrh.ulNextOff;                 /* Next location  */

    /*
     *   Can now process the user's list of stuff to write out.
     * The writing out is done by user supplied functions - they
     * tell us how much was written, we simply update the red tape.
     */

    dwVarLoc = SetFilePointer( pFID->hVarFile, 0, NULL, FILE_END );

    for( ; pFList; pFList = (FONTLIST *)pFList->pFLNext )
    {

        /*  First write out the header array type data  */

        SetFilePointer( pFID->hFixFile, dwLoc + sizeof( FF_REC_HEADER ),
                                                         NULL, FILE_BEGIN );

        iSize = iFIWriteFix( pFID->hFixFile, pFID->hHeap, pFList->pvFixData );

        if( iSize < 0 )
            return  FALSE;              /* Bad news */

        ffrh.ulSize = (ULONG)iSize;             /* For the record */
        ffh.ulRecCount++;               /* One more! */

        /*
         *   Position of next entry:  make it DWORD aligned so that we
         * can memory map the file.
         */
        ffrh.ulNextOff = sizeof( ffrh ) + (iSize + 3) & ~0x3;
        ffh.ulFixSize += ffrh.ulNextOff;

        /*
         *   The variable length part of the data.  Much the same as
         * above,  simply a different function to call.
         */

        SetFilePointer( pFID->hVarFile, dwVarLoc, NULL, FILE_BEGIN );

        iVarSize = iFIWriteVar( pFID->hVarFile, pFID->hHeap, pFList->pvVarData );

        if( iVarSize < 0 )      
            return  FALSE;                      /* Not good */

        ffrh.ulVarSize = (ULONG)iVarSize;
        if( iVarSize > 0 )
        {
            /*  A zero return means no data - quite legitimate */

            ffrh.ulVarOff = dwVarLoc;
            dwVarLoc += (iVarSize + 3) & ~0x3;
        }
        else
            ffrh.ulVarOff = 0;          /* No data for this one. */


        /*  Finally,  write out the header for the array data  */

        SetFilePointer( pFID->hFixFile, dwLoc, NULL, FILE_BEGIN );

        if( !bWrite( pFID->hFixFile, &ffrh, sizeof( FF_REC_HEADER ) ) )
        {
#if  DBG
            DbgPrint( "Print!bWrite of FF_REC_HEADER fails\n" );
#endif
            return  FALSE;
        }

        /*   Set the file pointer to the location of the next header */
        dwLoc += ffrh.ulNextOff;
    }

    /*
     *  Last step:  write out the final header,  which has ulSize set to
     * zero to indicate that it is the terminating record.
     */

    ffh.ulVarSize = GetFileSize( pFID->hVarFile, NULL );

    SetFilePointer( pFID->hFixFile, dwLoc, NULL, FILE_BEGIN );

    ffrh.ulNextOff = 0;         /* No more in this chain! */

    if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
        return  FALSE;

    /*
     *   Finally,  update the master header.
     */

    SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );
    if( !bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) ) )
        return  FALSE;

    return  TRUE;
}

/******************************** Function Header **************************
 * bGetFileHDR
 *      Read in the FF_HEADER for the font installer file.  This is
 *      always located at the beginning of the file!  Returns TRUE
 *      if the read was AOK,  and the structure is verified.
 *
 * RETURNS:
 *      TRUE/FALSE
 *
 * HISTORY:
 *  15:40 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      First incarnation.
 *
 ***************************************************************************/

BOOL
bGetFileHDR( hFile, pffh )
HANDLE     hFile;                       /* The file */
FF_HEADER *pffh;                        /* The header to fill in */
{
    /*
     *  Not hard:  seek to the beginning of the file,  then read in the
     * structure there, and VERIFY it!
     */

    DWORD  dwIn;                /* Bytes read */


    SetFilePointer( hFile, 0, NULL, FILE_BEGIN );               /* Start */

    if( !ReadFile( hFile, pffh, sizeof( FF_HEADER ), &dwIn, NULL ) ||
        dwIn != sizeof( FF_HEADER ) )
    {
                return  FALSE;
    }
    
    return  pffh->ulID == FF_ID;
}


/******************************* Function Header ****************************
 * bGetRecHDR
 *      Read the FF_REC_HEADER structure at the given location with the
 *      file,  and return TRUE if read successfully.  This means the
 *      read was AOK,  and the structure is acceptable.
 *
 * RETURNS:
 *      TRUE/FALSE
 *
 * HISTORY:
 *  15:38 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Starting out.
 *
 ****************************************************************************/

BOOL
bGetRecHDR( hFile, pffrh, dwLoc )
HANDLE          hFile;          /* File to read from */
FF_REC_HEADER  *pffrh;          /* Structure to fill in */
DWORD           dwLoc;          /* Location of data in file: absolute */
{
    /*
     *   Seek to the specified location,  and read in the data there!
     * Perform consistency checks as above in bGetFileHDR.
     */

    DWORD   dwIn;               /* Bytes read */


    SetFilePointer( hFile, dwLoc, NULL, FILE_BEGIN );

    if( !ReadFile( hFile, pffrh, sizeof( FF_REC_HEADER ), &dwIn, NULL ) ||
        dwIn != sizeof( FF_REC_HEADER ) )
    {
                return  FALSE;
    }

    return  pffrh->ulRID == FR_ID;
}


/**************************** Function Header ******************************
 * bFixInit
 *      Writes a no information header into the file.  This means that
 *      other functions can proceed on the basis that the file contains
 *      valid structures and links.
 *
 * RETURNS:
 *      TRUE/FALSE;  FALSE on failure.
 *
 * HISTORY:
 *  13:39 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Initial
 *
 ***************************************************************************/

BOOL
bFixInit( hFile )
HANDLE  hFile;
{
    /*
     *   As a minimum,  the file needs a FF_HEADER and a FF_REC_HEADER
     *  structure.  The first contains an offset to the second, and
     *  no variable length data start location.  The latter contains
     *  a zero size field, indicating no more data.
     */

    FF_HEADER      ffh;         /* Overall file header */
    FF_REC_HEADER  ffrh;        /* Individual record header */

    /*
     *  Initialise the FF_HEADER before writing it out.
     */


    ffh.ulID = FF_ID;
    ffh.ulVersion = FF_VERSION;
    ffh.ulFixData = sizeof( ffh );              /* Follows us directly */
    ffh.ulFixSize = sizeof( ffrh );             /* Bytes in fixed area */
    ffh.ulRecCount = 0;                         /* No records yet! */
    ffh.ulVarData = 0;                          /* None - YET! */
    ffh.ulVarSize = 0;


    ffrh.ulRID = FR_ID;
    ffrh.ulSize = 0;
    ffrh.ulNextOff = 0;                 /* EOF for fixed part of file */
    ffrh.ulVarOff = 0;
    ffrh.ulVarSize = 0;

    if( !bWrite( hFile, &ffh, sizeof( ffh )) ||
        !bWrite( hFile, &ffrh, sizeof( ffrh )) )
    {
#if  DBG
        DbgPrint( "Print!bFixInit fails\n" );
#endif

        return  FALSE;
    }

    return  TRUE;
}

/**************************** Function Header ******************************
 *  vFIClean
 *      The clean up the mess during bail out function.  Removes the 
 *      temporary files, frees heap storage and whatever else is
 *      required.
 *
 * RETURNS:
 *      Zilch
 *
 * HISOTRY:
 *  13:25 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Start on it - it probably will grow.
 *
 ***************************************************************************/

void
vFIClean( pFID )
FID   *pFID;
{
    /*
     *   Need to be slightly careful about what we do. In particular,  NO
     * bad memory accesses.
     */

    if( pFID->dwID != FID_ID )
        return;

    /*
     *   Free any temporary files we may have created.  Note that we
     * must close the files before we can remove.  Silly idea that is.
     */


    if( pFID->hCurFile != INVALID_HANDLE_VALUE )
        CloseHandle( pFID->hCurFile );

    if( pFID->hFixFile != INVALID_HANDLE_VALUE )
        CloseHandle( pFID->hFixFile );

    if( pFID->hVarFile != INVALID_HANDLE_VALUE )
        CloseHandle( pFID->hVarFile );

    if( pFID->pwstrFixName )
    {
        DeleteFileW( pFID->pwstrFixName );              /* Ignore failure */

        HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrFixName );
        pFID->pwstrFixName = 0;
    }

    if( pFID->pwstrVarName )
    {
        DeleteFileW( pFID->pwstrVarName );

        HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrVarName );
        pFID->pwstrFixName = 0;
    }

    if( pFID->pwstrCurName )
    {
        HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrCurName );
        pFID->pwstrCurName = 0;
    }


    pFID->dwID = (DWORD)~FID_ID;        /* Invalid in case mem reused */

    HeapFree( pFID->hHeap, 0, (LPSTR)pFID );

    return;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.