File:  [WindowsNT SDKs] / ntddk / src / print / lib / fontread.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 *******************************
 * fontread.c
 *      Functions to assist processing of the data in a common font
 *      installer file format.
 *
 * Copyright (C) 1992 - 1993   Microsoft Corporation.
 *
 *****************************************************************************/

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

#include        "fontread.h"
#include        "libproto.h"            /* bWrite() proto */

#include        "fontfile.h"            /* File layout details */



/******************************** Function Header ****************************
 * iFIOpenRead
 *      Makes the font installer file accessible & memory mapped.  Called
 *      by a driver to gain access to the fonts in the font installer's
 *      output file.
 *
 * RETURNS:
 *      Number of records in the file;  0 for an empty/non-existant file.
 *
 * HISTORY:
 *  13:37 on Sat 12 Jun 1993    -by-    Lindsay Harris   [lindsayh]
 *      Stop using memory mapping as it is unsafe across the net.
 *
 *  13:45 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      First incarnation.
 *
 *****************************************************************************/

int
iFIOpenRead( pFIMem, hHeap, pwstrName )
FI_MEM  *pFIMem;                /* Output goes here */
HANDLE   hHeap;                 /* Need some storage for a short time */
PWSTR    pwstrName;             /* Name of printer data file */
{

    DWORD   dwSize;             /* Size of buffer needed for file name */
    PWSTR   pwstrLocal;



    pFIMem->hFont = INVALID_HANDLE_VALUE;      /* No data until we have it */
    pFIMem->pbBase = NULL;

    /*
     *   First map the file to memory.  However,  we do need firstly to
     * generate the file name of interest.  This is based on the data
     * file name for this type of printer.
     *   Allocate more storage than is indicated:  we MAY want to add
     * a prefix to the file name rather than replace the existing one.
     */


    dwSize = sizeof( WCHAR ) * (wcslen( pwstrName ) + 1 + 4);

    if( pwstrLocal = (PWSTR)HeapAlloc( hHeap, 0, dwSize ) )
    {
        /*  Got the memory,  so fiddle the file name to our standard */

        int    iPtOff;             /* Location of '.' */


        FF_HEADER  ffh;          /* Read in to determine memory size needed */



        wcscpy( pwstrLocal, pwstrName );

        /*
         *   Go looking for a '.' - if not found,  append to string.
         */

        iPtOff = wcslen( pwstrLocal );

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

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


    
        /*  Generate the name and map the file */
        wcscpy( pwstrLocal + iPtOff, FILE_FONTS );


  
        pFIMem->hFont = CreateFileW( pwstrLocal, GENERIC_READ, FILE_SHARE_READ,
                                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
                                                                   NULL );
  
        HeapFree( hHeap, 0, (LPSTR)pwstrLocal );        /* No longer needed */

        /*
         *   Now for the fun part.   The file header contains the size
         *  of the fixed part of the file.  This is the part containing
         *  the IFIMETRICS etc.  This is the part of the file that causes
         *  great distress to GDI if the network fails when we are mapping
         *  to a remote system.  SO,  we allocate storage for this data
         *  now,  and read the data in.  Then it is safe for ever after.
         */

        if( pFIMem->hFont == INVALID_HANDLE_VALUE )
            return  0;           /*  Probably no file there at all */

        if( !ReadFile( pFIMem->hFont, &ffh, sizeof( ffh ), &dwSize, NULL ) ||
            dwSize != sizeof( ffh ) )
        {
            /*
             *   Bad news on the read,  so fail the call now.
             */

            CloseHandle( pFIMem->hFont );
            pFIMem->hFont = INVALID_HANDLE_VALUE;

            return  0;
        }
        
        dwSize = ffh.ulFixSize + sizeof( ffh );

        pFIMem->pbBase = (BYTE *)GlobalAlloc( GMEM_FIXED, dwSize );


        if( pFIMem->pbBase == NULL )
        {
            /*  Could not get the memory,  so give up now */
            CloseHandle( pFIMem->hFont );
            pFIMem->hFont = INVALID_HANDLE_VALUE;

            return  0;
        }

        /*
         *   We want to read the file header again,  so rewind the file.
         */

        SetFilePointer( pFIMem->hFont,  0, NULL, FILE_BEGIN );

        if( !ReadFile( pFIMem->hFont, pFIMem->pbBase, dwSize, &dwSize, NULL ) ||
            dwSize != dwSize )
        {

            /*   Not good either - cannot read the file again.  */

            GlobalFree( pFIMem->pbBase );
            pFIMem->pbBase = NULL;

            CloseHandle( pFIMem->hFont );
            pFIMem->hFont = INVALID_HANDLE_VALUE;

            return  0;
        }


        return  iFIRewind( pFIMem );    
    }
    else
        return  0;              /* Too bad: oh well, no extra fonts */
}

/******************************** Function Header ****************************
 * bFINextRead()
 *      Updates pFIMem to the next entry in the font installer file.
 *      Returns TRUE if OK, and updates the pointers in pFIMem.
 *
 * RETURNS:
 *      TRUE/FALSE.   FALSE for EOF,  otherwise pFIMem updated.
 *
 * HISTORY:
 *  13:50 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Numero Uno.
 *
 *****************************************************************************/

BOOL
bFINextRead( pFIMem )
FI_MEM   *pFIMem;
{
    FF_HEADER      *pFFH;               /* Overall file header */
    FF_REC_HEADER  *pFFRH;              /* Per record header */

    /*
     *  Validate that we have valid data.
     */


    if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        return  FALSE;                          /* Empty file */

    pFFH = (FF_HEADER *)pFIMem->pbBase;

    if( pFFH->ulID != FF_ID )
    {
        DbgPrint( "Print!bFINextRead: FF_HEADER has invalid ID\n" );

        return  FALSE;
    }
    
    /*
     *   If pFIMem->pvFix == 0, we should return the data from the
     * first record.  Otherwise,  return the next record in the chain.
     * This is done to avoid the need to have a ReadFirst()/ReadNext()
     * pair of functions.
     */

    if( pFIMem->pvFix )
    {
        /*
         *   The header is located immediately before the data we last
         * returned for the fixed portion of the record.  SO,  we back
         * over it to get the header which then gives us the address
         * of the next header.
         */

        pFFRH = (FF_REC_HEADER *)((BYTE *)pFIMem->pvFix -
                                                 sizeof( FF_REC_HEADER ));

        if( pFFRH->ulRID != FR_ID )
        {
            DbgPrint( "Print!bFINextRead: Invalid FF_REC_HEADER ID\n" );

            return  FALSE;
        }

        /*
         *   We could check here for EOF on the existing structure, but this
         * is not required BECAUSE THE ulNextOff field will be 0, so when
         * it is added to our current address,  we don't move.  Hence, the
         * check for the NEW address is OK to detect EOF.
         */

        (BYTE *)pFFRH += pFFRH->ulNextOff;              /* Next entry */

    }
    else
    {
        /*   Point to the first record.  */
        pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);
    }

    if( pFFRH->ulNextOff == 0 )
        return  FALSE;

    pFIMem->pvFix = (BYTE *)pFFRH + sizeof( FF_REC_HEADER );
    pFIMem->ulFixSize = pFFRH->ulSize;

    if( pFIMem->ulVarSize = pFFRH->ulVarSize )
        pFIMem->ulVarOff = pFFRH->ulVarOff + pFFH->ulVarData;
    else
        pFIMem->ulVarOff = 0;              /* None here */


    return  TRUE;
}

/******************************** Function Header ***************************
 * bFIRewind
 *      Reset pFIMem to the first font in the file.
 *
 * RETURNS:
 *      Number of entries in the file.
 *
 * HISTORY:
 *  13:54 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Start.
 *
 *****************************************************************************/

int
iFIRewind( pFIMem )
FI_MEM   *pFIMem;               /* File of importance */
{
    /*
     *  Not hard!  The pFIMem contains the base address of the file, so we
     * use this to find the address of the first record,  and any variable
     * data that corresponds with it.
     */

    FF_HEADER      *pFFH;
    FF_REC_HEADER  *pFFRH;

    if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        return  0;                              /* None! */


    /*
     *   The location of the first record is specified in the header.
     */

    pFFH = (FF_HEADER *)pFIMem->pbBase;
    if( pFFH->ulID != FF_ID )
    {
        DbgPrint( "Print!iFIRewind: FF_HEADER has invalid ID\n" );

        return  0;
    }

    pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);

    if( pFFRH->ulRID != FR_ID )
    {
        DbgPrint( "Print!iFIRewind: Invalid FF_REC_HEADER ID\n" );

        return  0;
    }

    /*
     *   Set the pvFix field in the header to 0.  This is used in bFINextRead
     * to mean that the data for the first record should be supplied.
     */
    pFIMem->pvFix = 0;          /* MEANS USE FIRST NEXT READ */
    pFIMem->ulFixSize = 0;
    pFIMem->ulVarOff = 0;       /* None here */

    return  pFFH->ulRecCount;
}


/******************************* Function Header ***************************
 * bFICloseRead
 *      Called when finished with this font file.
 *
 * RETURNS:
 *      Nothing
 *
 * HISTORY:
 *  15:07 on Sat 12 Jun 1993    -by-    Lindsay Harris   [lindsayh]
 *      Can no longer use MapFile,  so free memory and close handles as needed.
 *
 *  13:56 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
 *      Time t = 0
 *
 ***************************************************************************/

BOOL
bFICloseRead( pFIMem )
FI_MEM  *pFIMem;                /* File/memory we are finished with */
{
    /*
     *   Easy!  All we need do is unmap the file.  We have the address too!
     */

    BOOL   bRet;                /* Return code */


    if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        return  TRUE;                   /* Nothing there! */
    
    bRet = CloseHandle( pFIMem->hFont );


    /*   Also free our chunk of memory  */

    if( pFIMem->pbBase )
    {
        /*   Address is valid,  so free it now  */

        GlobalFree( pFIMem->pbBase );
        
        pFIMem->pbBase = NULL;
    }


    if( bRet )
        pFIMem->hFont = INVALID_HANDLE_VALUE; /* Stops freeing more than once */


    return  bRet;
}

unix.superglobalmegacorp.com

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