Annotation of ntddk/src/print/lib/fontread.c, revision 1.1

1.1     ! root        1: /******************************* MODULE HEADER *******************************
        !             2:  * fontread.c
        !             3:  *      Functions to assist processing of the data in a common font
        !             4:  *      installer file format.
        !             5:  *
        !             6:  * Copyright (C) 1992 - 1993   Microsoft Corporation.
        !             7:  *
        !             8:  *****************************************************************************/
        !             9: 
        !            10: #include        <stddef.h>
        !            11: #include        <windows.h>
        !            12: 
        !            13: #include        "fontread.h"
        !            14: #include        "libproto.h"            /* bWrite() proto */
        !            15: 
        !            16: #include        "fontfile.h"            /* File layout details */
        !            17: 
        !            18: 
        !            19: 
        !            20: /******************************** Function Header ****************************
        !            21:  * iFIOpenRead
        !            22:  *      Makes the font installer file accessible & memory mapped.  Called
        !            23:  *      by a driver to gain access to the fonts in the font installer's
        !            24:  *      output file.
        !            25:  *
        !            26:  * RETURNS:
        !            27:  *      Number of records in the file;  0 for an empty/non-existant file.
        !            28:  *
        !            29:  * HISTORY:
        !            30:  *  13:37 on Sat 12 Jun 1993    -by-    Lindsay Harris   [lindsayh]
        !            31:  *      Stop using memory mapping as it is unsafe across the net.
        !            32:  *
        !            33:  *  13:45 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !            34:  *      First incarnation.
        !            35:  *
        !            36:  *****************************************************************************/
        !            37: 
        !            38: int
        !            39: iFIOpenRead( pFIMem, hHeap, pwstrName )
        !            40: FI_MEM  *pFIMem;                /* Output goes here */
        !            41: HANDLE   hHeap;                 /* Need some storage for a short time */
        !            42: PWSTR    pwstrName;             /* Name of printer data file */
        !            43: {
        !            44: 
        !            45:     DWORD   dwSize;             /* Size of buffer needed for file name */
        !            46:     PWSTR   pwstrLocal;
        !            47: 
        !            48: 
        !            49: 
        !            50:     pFIMem->hFont = INVALID_HANDLE_VALUE;      /* No data until we have it */
        !            51:     pFIMem->pbBase = NULL;
        !            52: 
        !            53:     /*
        !            54:      *   First map the file to memory.  However,  we do need firstly to
        !            55:      * generate the file name of interest.  This is based on the data
        !            56:      * file name for this type of printer.
        !            57:      *   Allocate more storage than is indicated:  we MAY want to add
        !            58:      * a prefix to the file name rather than replace the existing one.
        !            59:      */
        !            60: 
        !            61: 
        !            62:     dwSize = sizeof( WCHAR ) * (wcslen( pwstrName ) + 1 + 4);
        !            63: 
        !            64:     if( pwstrLocal = (PWSTR)HeapAlloc( hHeap, 0, dwSize ) )
        !            65:     {
        !            66:         /*  Got the memory,  so fiddle the file name to our standard */
        !            67: 
        !            68:         int    iPtOff;             /* Location of '.' */
        !            69: 
        !            70: 
        !            71:         FF_HEADER  ffh;          /* Read in to determine memory size needed */
        !            72: 
        !            73: 
        !            74: 
        !            75:         wcscpy( pwstrLocal, pwstrName );
        !            76: 
        !            77:         /*
        !            78:          *   Go looking for a '.' - if not found,  append to string.
        !            79:          */
        !            80: 
        !            81:         iPtOff = wcslen( pwstrLocal );
        !            82: 
        !            83:         while( --iPtOff > 0 )
        !            84:         {
        !            85:             if( *(pwstrLocal + iPtOff) == (WCHAR)'.' )
        !            86:                 break;
        !            87:         }
        !            88: 
        !            89:         if( iPtOff <= 0 )
        !            90:         {
        !            91:             iPtOff = wcslen( pwstrLocal );              /* Presume none! */
        !            92:             *(pwstrLocal + iPtOff) = L'.';
        !            93:         }
        !            94:         ++iPtOff;               /* Skip the period */
        !            95: 
        !            96: 
        !            97:     
        !            98:         /*  Generate the name and map the file */
        !            99:         wcscpy( pwstrLocal + iPtOff, FILE_FONTS );
        !           100: 
        !           101: 
        !           102:   
        !           103:         pFIMem->hFont = CreateFileW( pwstrLocal, GENERIC_READ, FILE_SHARE_READ,
        !           104:                                      NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
        !           105:                                                                    NULL );
        !           106:   
        !           107:         HeapFree( hHeap, 0, (LPSTR)pwstrLocal );        /* No longer needed */
        !           108: 
        !           109:         /*
        !           110:          *   Now for the fun part.   The file header contains the size
        !           111:          *  of the fixed part of the file.  This is the part containing
        !           112:          *  the IFIMETRICS etc.  This is the part of the file that causes
        !           113:          *  great distress to GDI if the network fails when we are mapping
        !           114:          *  to a remote system.  SO,  we allocate storage for this data
        !           115:          *  now,  and read the data in.  Then it is safe for ever after.
        !           116:          */
        !           117: 
        !           118:         if( pFIMem->hFont == INVALID_HANDLE_VALUE )
        !           119:             return  0;           /*  Probably no file there at all */
        !           120: 
        !           121:         if( !ReadFile( pFIMem->hFont, &ffh, sizeof( ffh ), &dwSize, NULL ) ||
        !           122:             dwSize != sizeof( ffh ) )
        !           123:         {
        !           124:             /*
        !           125:              *   Bad news on the read,  so fail the call now.
        !           126:              */
        !           127: 
        !           128:             CloseHandle( pFIMem->hFont );
        !           129:             pFIMem->hFont = INVALID_HANDLE_VALUE;
        !           130: 
        !           131:             return  0;
        !           132:         }
        !           133:         
        !           134:         dwSize = ffh.ulFixSize + sizeof( ffh );
        !           135: 
        !           136:         pFIMem->pbBase = (BYTE *)GlobalAlloc( GMEM_FIXED, dwSize );
        !           137: 
        !           138: 
        !           139:         if( pFIMem->pbBase == NULL )
        !           140:         {
        !           141:             /*  Could not get the memory,  so give up now */
        !           142:             CloseHandle( pFIMem->hFont );
        !           143:             pFIMem->hFont = INVALID_HANDLE_VALUE;
        !           144: 
        !           145:             return  0;
        !           146:         }
        !           147: 
        !           148:         /*
        !           149:          *   We want to read the file header again,  so rewind the file.
        !           150:          */
        !           151: 
        !           152:         SetFilePointer( pFIMem->hFont,  0, NULL, FILE_BEGIN );
        !           153: 
        !           154:         if( !ReadFile( pFIMem->hFont, pFIMem->pbBase, dwSize, &dwSize, NULL ) ||
        !           155:             dwSize != dwSize )
        !           156:         {
        !           157: 
        !           158:             /*   Not good either - cannot read the file again.  */
        !           159: 
        !           160:             GlobalFree( pFIMem->pbBase );
        !           161:             pFIMem->pbBase = NULL;
        !           162: 
        !           163:             CloseHandle( pFIMem->hFont );
        !           164:             pFIMem->hFont = INVALID_HANDLE_VALUE;
        !           165: 
        !           166:             return  0;
        !           167:         }
        !           168: 
        !           169: 
        !           170:         return  iFIRewind( pFIMem );    
        !           171:     }
        !           172:     else
        !           173:         return  0;              /* Too bad: oh well, no extra fonts */
        !           174: }
        !           175: 
        !           176: /******************************** Function Header ****************************
        !           177:  * bFINextRead()
        !           178:  *      Updates pFIMem to the next entry in the font installer file.
        !           179:  *      Returns TRUE if OK, and updates the pointers in pFIMem.
        !           180:  *
        !           181:  * RETURNS:
        !           182:  *      TRUE/FALSE.   FALSE for EOF,  otherwise pFIMem updated.
        !           183:  *
        !           184:  * HISTORY:
        !           185:  *  13:50 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           186:  *      Numero Uno.
        !           187:  *
        !           188:  *****************************************************************************/
        !           189: 
        !           190: BOOL
        !           191: bFINextRead( pFIMem )
        !           192: FI_MEM   *pFIMem;
        !           193: {
        !           194:     FF_HEADER      *pFFH;               /* Overall file header */
        !           195:     FF_REC_HEADER  *pFFRH;              /* Per record header */
        !           196: 
        !           197:     /*
        !           198:      *  Validate that we have valid data.
        !           199:      */
        !           200: 
        !           201: 
        !           202:     if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        !           203:         return  FALSE;                          /* Empty file */
        !           204: 
        !           205:     pFFH = (FF_HEADER *)pFIMem->pbBase;
        !           206: 
        !           207:     if( pFFH->ulID != FF_ID )
        !           208:     {
        !           209:         DbgPrint( "Print!bFINextRead: FF_HEADER has invalid ID\n" );
        !           210: 
        !           211:         return  FALSE;
        !           212:     }
        !           213:     
        !           214:     /*
        !           215:      *   If pFIMem->pvFix == 0, we should return the data from the
        !           216:      * first record.  Otherwise,  return the next record in the chain.
        !           217:      * This is done to avoid the need to have a ReadFirst()/ReadNext()
        !           218:      * pair of functions.
        !           219:      */
        !           220: 
        !           221:     if( pFIMem->pvFix )
        !           222:     {
        !           223:         /*
        !           224:          *   The header is located immediately before the data we last
        !           225:          * returned for the fixed portion of the record.  SO,  we back
        !           226:          * over it to get the header which then gives us the address
        !           227:          * of the next header.
        !           228:          */
        !           229: 
        !           230:         pFFRH = (FF_REC_HEADER *)((BYTE *)pFIMem->pvFix -
        !           231:                                                  sizeof( FF_REC_HEADER ));
        !           232: 
        !           233:         if( pFFRH->ulRID != FR_ID )
        !           234:         {
        !           235:             DbgPrint( "Print!bFINextRead: Invalid FF_REC_HEADER ID\n" );
        !           236: 
        !           237:             return  FALSE;
        !           238:         }
        !           239: 
        !           240:         /*
        !           241:          *   We could check here for EOF on the existing structure, but this
        !           242:          * is not required BECAUSE THE ulNextOff field will be 0, so when
        !           243:          * it is added to our current address,  we don't move.  Hence, the
        !           244:          * check for the NEW address is OK to detect EOF.
        !           245:          */
        !           246: 
        !           247:         (BYTE *)pFFRH += pFFRH->ulNextOff;              /* Next entry */
        !           248: 
        !           249:     }
        !           250:     else
        !           251:     {
        !           252:         /*   Point to the first record.  */
        !           253:         pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);
        !           254:     }
        !           255: 
        !           256:     if( pFFRH->ulNextOff == 0 )
        !           257:         return  FALSE;
        !           258: 
        !           259:     pFIMem->pvFix = (BYTE *)pFFRH + sizeof( FF_REC_HEADER );
        !           260:     pFIMem->ulFixSize = pFFRH->ulSize;
        !           261: 
        !           262:     if( pFIMem->ulVarSize = pFFRH->ulVarSize )
        !           263:         pFIMem->ulVarOff = pFFRH->ulVarOff + pFFH->ulVarData;
        !           264:     else
        !           265:         pFIMem->ulVarOff = 0;              /* None here */
        !           266: 
        !           267: 
        !           268:     return  TRUE;
        !           269: }
        !           270: 
        !           271: /******************************** Function Header ***************************
        !           272:  * bFIRewind
        !           273:  *      Reset pFIMem to the first font in the file.
        !           274:  *
        !           275:  * RETURNS:
        !           276:  *      Number of entries in the file.
        !           277:  *
        !           278:  * HISTORY:
        !           279:  *  13:54 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           280:  *      Start.
        !           281:  *
        !           282:  *****************************************************************************/
        !           283: 
        !           284: int
        !           285: iFIRewind( pFIMem )
        !           286: FI_MEM   *pFIMem;               /* File of importance */
        !           287: {
        !           288:     /*
        !           289:      *  Not hard!  The pFIMem contains the base address of the file, so we
        !           290:      * use this to find the address of the first record,  and any variable
        !           291:      * data that corresponds with it.
        !           292:      */
        !           293: 
        !           294:     FF_HEADER      *pFFH;
        !           295:     FF_REC_HEADER  *pFFRH;
        !           296: 
        !           297:     if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        !           298:         return  0;                              /* None! */
        !           299: 
        !           300: 
        !           301:     /*
        !           302:      *   The location of the first record is specified in the header.
        !           303:      */
        !           304: 
        !           305:     pFFH = (FF_HEADER *)pFIMem->pbBase;
        !           306:     if( pFFH->ulID != FF_ID )
        !           307:     {
        !           308:         DbgPrint( "Print!iFIRewind: FF_HEADER has invalid ID\n" );
        !           309: 
        !           310:         return  0;
        !           311:     }
        !           312: 
        !           313:     pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);
        !           314: 
        !           315:     if( pFFRH->ulRID != FR_ID )
        !           316:     {
        !           317:         DbgPrint( "Print!iFIRewind: Invalid FF_REC_HEADER ID\n" );
        !           318: 
        !           319:         return  0;
        !           320:     }
        !           321: 
        !           322:     /*
        !           323:      *   Set the pvFix field in the header to 0.  This is used in bFINextRead
        !           324:      * to mean that the data for the first record should be supplied.
        !           325:      */
        !           326:     pFIMem->pvFix = 0;          /* MEANS USE FIRST NEXT READ */
        !           327:     pFIMem->ulFixSize = 0;
        !           328:     pFIMem->ulVarOff = 0;       /* None here */
        !           329: 
        !           330:     return  pFFH->ulRecCount;
        !           331: }
        !           332: 
        !           333: 
        !           334: /******************************* Function Header ***************************
        !           335:  * bFICloseRead
        !           336:  *      Called when finished with this font file.
        !           337:  *
        !           338:  * RETURNS:
        !           339:  *      Nothing
        !           340:  *
        !           341:  * HISTORY:
        !           342:  *  15:07 on Sat 12 Jun 1993    -by-    Lindsay Harris   [lindsayh]
        !           343:  *      Can no longer use MapFile,  so free memory and close handles as needed.
        !           344:  *
        !           345:  *  13:56 on Thu 27 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           346:  *      Time t = 0
        !           347:  *
        !           348:  ***************************************************************************/
        !           349: 
        !           350: BOOL
        !           351: bFICloseRead( pFIMem )
        !           352: FI_MEM  *pFIMem;                /* File/memory we are finished with */
        !           353: {
        !           354:     /*
        !           355:      *   Easy!  All we need do is unmap the file.  We have the address too!
        !           356:      */
        !           357: 
        !           358:     BOOL   bRet;                /* Return code */
        !           359: 
        !           360: 
        !           361:     if( pFIMem == 0 || pFIMem->hFont == INVALID_HANDLE_VALUE )
        !           362:         return  TRUE;                   /* Nothing there! */
        !           363:     
        !           364:     bRet = CloseHandle( pFIMem->hFont );
        !           365: 
        !           366: 
        !           367:     /*   Also free our chunk of memory  */
        !           368: 
        !           369:     if( pFIMem->pbBase )
        !           370:     {
        !           371:         /*   Address is valid,  so free it now  */
        !           372: 
        !           373:         GlobalFree( pFIMem->pbBase );
        !           374:         
        !           375:         pFIMem->pbBase = NULL;
        !           376:     }
        !           377: 
        !           378: 
        !           379:     if( bRet )
        !           380:         pFIMem->hFont = INVALID_HANDLE_VALUE; /* Stops freeing more than once */
        !           381: 
        !           382: 
        !           383:     return  bRet;
        !           384: }

unix.superglobalmegacorp.com

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