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

1.1     ! root        1: /******************************* MODULE HEADER ******************************
        !             2:  * fontfile.c
        !             3:  *      Functions associated with generating the combined font file
        !             4:  *      used with NT printer drivers.  This handles the mechanics of
        !             5:  *      creating/adding/deleting data in the file.  No attempt is made
        !             6:  *      to understand the contents of the file.  That is left to
        !             7:  *      individual drivers.
        !             8:  *
        !             9:  *  Copyright (C) 1992 - 1993  Microsoft Corportation.
        !            10:  *
        !            11:  *****************************************************************************/
        !            12: 
        !            13: 
        !            14: #include        <stddef.h>
        !            15: #include        <windows.h>
        !            16: 
        !            17: #include        "fontfile.h"            /* File layout details */
        !            18: #include        "fontgen.h"             /* Globally visible components */
        !            19: #include        "libproto.h"            /* bWrite() proto */
        !            20: 
        !            21: 
        !            22: 
        !            23: /*
        !            24:  *   Local functions.
        !            25:  */
        !            26: 
        !            27: 
        !            28: BOOL  bGetFileHDR( HANDLE, FF_HEADER * );
        !            29: BOOL  bGetRecHDR( HANDLE, FF_REC_HEADER *, DWORD );
        !            30: BOOL  bFixInit( HANDLE );               /* Initialise new Fixed file */
        !            31: void  vFIClean( FID * );                /* Clean up any mess */
        !            32: BOOL  bDelList( FID *, int * );         /* Delete fonts in current set */
        !            33: BOOL  bAddFList( FID *, FONTLIST * );   /* Add new fonts to existing */
        !            34: 
        !            35: 
        !            36: 
        !            37: 
        !            38: /******************************* Function Header ****************************
        !            39:  * pFIOpen()
        !            40:  *      Function to initialize the internal operations for the font installer
        !            41:  *      single font file building operations.  The value returned is passed
        !            42:  *      to other functions here, giving them access to the data required
        !            43:  *      to complete their tasks.
        !            44:  *
        !            45:  * RETURNS:
        !            46:  *      Pointer to private data,  cast as a (void *);  0 on error.
        !            47:  *
        !            48:  * HISTORY:
        !            49:  *  09:49 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !            50:  *      Starting work on it.
        !            51:  *
        !            52:  ****************************************************************************/
        !            53: 
        !            54: FID *
        !            55: pFIOpen( pwstrDataFile, hHeap )
        !            56: PWSTR   pwstrDataFile;          /* Driver's data file name */
        !            57: HANDLE  hHeap;                  /* Heap access */
        !            58: {
        !            59: 
        !            60:     FID    *pFID;               /* For our convenience */
        !            61:     PWSTR   pwstr;              /* For file name manipulation */
        !            62: 
        !            63:     int     iPtOff;             /* Location of . in file name */
        !            64:     int     iSize;              /* Determine the size of things */
        !            65: 
        !            66: 
        !            67:     /*
        !            68:      *   Firstly allocate a FID structure from the heap.  We cannot use
        !            69:      * a stack version as it needs to be persistent.
        !            70:      */
        !            71: 
        !            72:     if( !(pFID = (FID *)HeapAlloc( hHeap, 0, sizeof( FID ) )) )
        !            73:     {
        !            74: #if  DBG
        !            75:         DbgPrint( "Print!pvFIOpen:  HeapAlloc( FID ) fails!\n" );
        !            76: #endif
        !            77: 
        !            78:         return  0;              /* Bad news */
        !            79:     }
        !            80: 
        !            81:     memset( pFID, 0, sizeof( FID ) );           /* Easier clean up */
        !            82: 
        !            83:     pFID->hHeap = hHeap;        /* Keep it for later! */
        !            84:     pFID->dwID = FID_ID;        /* Make sure we get our own back! */
        !            85: 
        !            86:     /*
        !            87:      *    We want to generate some file names,  so determine the
        !            88:      *  length of the input name,  and allocate that much storage
        !            89:      *  for it.  We do not know what format the name is, so allow
        !            90:      *  room at the end to add ".fi_": 5 WCHARs including the null.
        !            91:      */
        !            92: 
        !            93:     iSize = (wcslen( pwstrDataFile ) + 5) * sizeof( WCHAR );
        !            94: 
        !            95:     if( !(pFID->pwstrCurName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) ||
        !            96:         !(pFID->pwstrFixName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) ||
        !            97:         !(pFID->pwstrVarName = (PWSTR)HeapAlloc( hHeap, 0, iSize )) )
        !            98:     {
        !            99:     
        !           100: #if  DBG
        !           101:         DbgPrint( "Print!pvFIOpen: HeapAlloc( pwstrDataFile ) fails!\n" );
        !           102: #endif
        !           103:         vFIClean( pFID );
        !           104: 
        !           105:         return  0;
        !           106:     }
        !           107:     pwstr = pFID->pwstrCurName;         /* For stuffing around */
        !           108: 
        !           109:     wcscpy( pFID->pwstrCurName, pwstrDataFile );        /* Working copies */
        !           110:     wcscpy( pFID->pwstrFixName, pwstrDataFile );
        !           111:     wcscpy( pFID->pwstrVarName, pwstrDataFile );
        !           112: 
        !           113: 
        !           114:     /*  Scan from RHS looking for '.': PRESUME THERE IS ONE! */
        !           115:     iPtOff = wcslen( pwstr );
        !           116: 
        !           117:     while( --iPtOff > 0 )
        !           118:     {
        !           119:         if( *(pwstr + iPtOff) == (WCHAR)'.' )
        !           120:             break;
        !           121:     }
        !           122: 
        !           123:     if( iPtOff <= 0 )
        !           124:     {
        !           125:         iPtOff = wcslen( pwstr );               /* Presume none! */
        !           126:         *(pwstr + iPtOff) = L'.';
        !           127:     }
        !           128:     ++iPtOff;           /* Skip the period */
        !           129: 
        !           130: 
        !           131:     
        !           132:     /*  Generate all 3 names & open the existing file  */
        !           133:     wcscpy( pFID->pwstrCurName + iPtOff, FILE_FONTS );
        !           134:     wcscpy( pFID->pwstrFixName + iPtOff, TFILE_FIX );
        !           135:     wcscpy( pFID->pwstrVarName + iPtOff, TFILE_VAR );
        !           136: 
        !           137: 
        !           138:     pFID->hCurFile = CreateFileW( pFID->pwstrCurName, GENERIC_READ,
        !           139:                                         FILE_SHARE_READ,
        !           140:                                         NULL, OPEN_EXISTING, 0, 0 );
        !           141: 
        !           142:     /*
        !           143:      *   Repeat for the two new files:  note that we want to create these,
        !           144:      * truncate any existing file,  and allow no other access to them
        !           145:      * while we are manipulating them.  They should be invisible.
        !           146:      */
        !           147: 
        !           148: 
        !           149:     pFID->hFixFile = CreateFileW( pFID->pwstrFixName,
        !           150:                                         GENERIC_READ | GENERIC_WRITE, 0, NULL,
        !           151:                                         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
        !           152:                                         pFID->hCurFile );
        !           153: 
        !           154:     if( pFID->hFixFile == INVALID_HANDLE_VALUE )
        !           155:     {
        !           156:         /*  Bad news  */
        !           157: #if  DBG
        !           158:         DbgPrint( "Print!bFIOpen: Fixed file initialisation failure\n" );
        !           159: #endif
        !           160: 
        !           161: 
        !           162:         vFIClean( pFID );
        !           163: 
        !           164:         return  0;
        !           165:     }
        !           166: 
        !           167: 
        !           168:     pFID->hVarFile = CreateFileW( pFID->pwstrVarName,
        !           169:                                         GENERIC_READ | GENERIC_WRITE, 0, NULL,
        !           170:                                         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
        !           171:                                         pFID->hCurFile );
        !           172: 
        !           173:     if( pFID->hVarFile == INVALID_HANDLE_VALUE )
        !           174:     {
        !           175: #if  DBG
        !           176:         DbgPrint( "Print!bFIOpen: Var file creation failure\n" );
        !           177: #endif
        !           178: 
        !           179: 
        !           180:         vFIClean( pFID );
        !           181: 
        !           182:         return  0;
        !           183:     }
        !           184: 
        !           185:     return  pFID;
        !           186: }
        !           187: 
        !           188: /****************************** Function Header *****************************
        !           189:  * bFIClose
        !           190:  *      Close up operations on the font installer file.  This involves
        !           191:  *      amalgamating the Fix and Var files,  updating the overall header
        !           192:  *      and renaming the file after deleting the old one.
        !           193:  *
        !           194:  * RETURNS:
        !           195:  *      TRUE/FALSE - FALSE if any operation fails.
        !           196:  *
        !           197:  * HISTORY:
        !           198:  *  15:01 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           199:  *      Gotta start somewhere
        !           200:  *
        !           201:  ***************************************************************************/
        !           202: 
        !           203: BOOL
        !           204: bFIClose( pFID, bUpdate )
        !           205: FID    *pFID;           /* The file collection to close */
        !           206: BOOL    bUpdate;        /* True to make new file THE file */
        !           207: {
        !           208: 
        !           209:     long   lSize;               /* Bytes copied from variable file */
        !           210: 
        !           211:     
        !           212:     FF_HEADER  ffh;             /* The overall file header */
        !           213: 
        !           214: 
        !           215: 
        !           216:     if( pFID->dwID != FID_ID )
        !           217:     {
        !           218: #if DBG
        !           219:         DbgPrint( "Print!bFIClose():  invalid pFID" );
        !           220: #endif
        !           221: 
        !           222:         return  FALSE;
        !           223:     }
        !           224: 
        !           225: 
        !           226:     /*
        !           227:      *   If bUpdate,  then reorganise the files:  the existing file is
        !           228:      * removed, the Var file is appended to the Fix file,  and that
        !           229:      * composite file is made the new "existing" file.
        !           230:      */
        !           231: 
        !           232: 
        !           233:     if( !bUpdate )
        !           234:     {
        !           235:         /*  No updating is to be done  */
        !           236:         vFIClean( pFID );                       /* Does all the dirty work */
        !           237: 
        !           238:         return  TRUE;                           /* By definition */
        !           239:     }
        !           240: 
        !           241:     /*
        !           242:      *   Update is ON!  First read the header from the fixed file, then
        !           243:      * fill in the missing details.  This amounts to the location of
        !           244:      * the start of the variable length data in the file.
        !           245:      */
        !           246: 
        !           247:     if( !bGetFileHDR( pFID->hFixFile, &ffh ) )
        !           248:     {
        !           249:         vFIClean( pFID );
        !           250: 
        !           251:         return  FALSE;
        !           252:     }
        !           253: 
        !           254:     /*
        !           255:      *   Need to know the size of the fixed file to put in the header.
        !           256:      */
        !           257: 
        !           258:     lSize = (long)SetFilePointer( pFID->hFixFile, 0, NULL, FILE_END );
        !           259: 
        !           260:     lSize = (lSize + 3) & ~0x3;         /* DWORD multiple */
        !           261: 
        !           262:     ffh.ulVarData = lSize;
        !           263: 
        !           264:     SetFilePointer( pFID->hFixFile, lSize, NULL, FILE_BEGIN );
        !           265:     SetFilePointer( pFID->hVarFile, 0, NULL, FILE_BEGIN );
        !           266: 
        !           267:     ffh.ulVarSize = lSize = lFICopy( pFID->hFixFile, pFID->hVarFile );
        !           268:     if( lSize < 0 )
        !           269:     {
        !           270:         /*   Some sort of error */
        !           271:         vFIClean( pFID );
        !           272: 
        !           273:         return  FALSE;
        !           274:     }
        !           275: 
        !           276:     if( lSize == 0 )
        !           277:         ffh.ulVarData = 0;              /* NONE! */
        !           278: 
        !           279:     /*
        !           280:      *   Now write the header back out.
        !           281:      */
        !           282: 
        !           283:     SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );
        !           284:     if( !bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) ) )
        !           285:     {
        !           286:         /*  Too bad:  throw it all away.  */
        !           287:         vFIClean( pFID );
        !           288: 
        !           289:         return  FALSE;
        !           290:     }
        !           291:     
        !           292:     /*
        !           293:      *   No longer need the file handles,  so close them,  and set
        !           294:      * the values to illegal so that we will not try to free them later.
        !           295:      * We can also delete the variable part of the file,  since that
        !           296:      * is now appended to the end of the fixed file.
        !           297:      */
        !           298: 
        !           299:     CloseHandle( pFID->hFixFile );              /* No longer needed */
        !           300:     pFID->hFixFile = INVALID_HANDLE_VALUE;      /* Won't be cleaned up */
        !           301: 
        !           302:     CloseHandle( pFID->hVarFile );              /* No longer need this file */
        !           303:     pFID->hVarFile = INVALID_HANDLE_VALUE;      /* Won't be cleaned up */
        !           304: 
        !           305: 
        !           306:     DeleteFileW( pFID->pwstrVarName );
        !           307: 
        !           308: 
        !           309:     /*
        !           310:      *   Now delete the existing file and rename the Fix file to the
        !           311:      *  proper name!
        !           312:      */
        !           313: 
        !           314: 
        !           315:     if( pFID->hCurFile != INVALID_HANDLE_VALUE )
        !           316:     {
        !           317:         /*  Have a current file,  so delete it, close our handle */
        !           318:         CloseHandle( pFID->hCurFile );
        !           319:         pFID->hCurFile = INVALID_HANDLE_VALUE;     /* Is now */
        !           320: 
        !           321:         if( !DeleteFileW( pFID->pwstrCurName ) )
        !           322:         {
        !           323:             vFIClean( pFID );
        !           324: 
        !           325:             return  FALSE;
        !           326:         }
        !           327:     }
        !           328: 
        !           329:     /* RENAME */
        !           330:     if( !MoveFileW( pFID->pwstrFixName, pFID->pwstrCurName ) )
        !           331:     {
        !           332:         /*  BAD NEWS:  we have lost the lot! */
        !           333: 
        !           334:         vFIClean( pFID );
        !           335: 
        !           336:         return  FALSE;
        !           337:     }
        !           338: 
        !           339:     /*
        !           340:      *  Clean up whatever is left.
        !           341:      */
        !           342: 
        !           343:     vFIClean( pFID );
        !           344: 
        !           345: 
        !           346:     return  TRUE;
        !           347: }
        !           348: 
        !           349: /******************************** Function Header ***************************
        !           350:  * bFIUpdate
        !           351:  *      Called to integrate changes to the font file.  Caller may delete
        !           352:  *      existing fonts and/or add new ones.  The deleted fonts are
        !           353:  *      passed as an array of integers, each being an index into the
        !           354:  *      existing fonts.  The first is a count of the number of
        !           355:  *      index values following; then comes the zero based index value.
        !           356:  *      New fonts are passed as a linked list of type FONTLIST.
        !           357:  * NOTE:  The master font file is NOT updated by this call.
        !           358:  *
        !           359:  * RETURNS:
        !           360:  *      TRUE/FALSE;  FALSE leaves no permanent changes.
        !           361:  *
        !           362:  * HISOTRY:
        !           363:  *  12:59 on Tue 25 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           364:  *      First version.
        !           365:  *
        !           366:  ****************************************************************************/
        !           367: 
        !           368: BOOL
        !           369: bFIUpdate( pFID, piDel, pFList )
        !           370: FID        *pFID;                       /* Access to our data */
        !           371: int        *piDel;                      /* Array of fonts to delete */
        !           372: FONTLIST   *pFList;                     /* Fonts to add */
        !           373: {
        !           374: 
        !           375:     /*
        !           376:      *    Not much to do!   First step is to copy the fixed part of the
        !           377:      * file to our new fixed file,  deleting fonts as we go. This also
        !           378:      * splits off the variable portion.  Then add whatever new fonts are
        !           379:      * to be added.  We do not amalgamate the file:  that is done at
        !           380:      * bFIClose() time,  giving the caller the chance to abort the whole
        !           381:      * operation.
        !           382:      */
        !           383: 
        !           384:     if( pFID->dwID != FID_ID )
        !           385:     {
        !           386: #if DBG
        !           387:         DbgPrint( "Print!bFIUpdate: pFID is invalid" );
        !           388: #endif
        !           389: 
        !           390:         return FALSE;
        !           391:     }
        !           392: 
        !           393: 
        !           394:     if( !bDelList( pFID, piDel ) )
        !           395:         return  FALSE;
        !           396: 
        !           397:     if( !bAddFList( pFID, pFList ) )
        !           398:         return  FALSE;
        !           399: 
        !           400:     return  TRUE;               /* Made it AOK */
        !           401: }
        !           402: 
        !           403: 
        !           404: /****************************** Function Header ******************************
        !           405:  * bDelList
        !           406:  *      Delete the nominated fonts from the master font file.  DOES NOT UPDATE
        !           407:  *      THE MASTER FILE.  The fonts are nominated by as an array of ints,
        !           408:  *      the first of which is a count of the number of ints following.
        !           409:  *      These values are zero based and represent the number of the font
        !           410:  *      in sequence in the file.
        !           411:  *
        !           412:  * RETURNS:
        !           413:  *      TRUE/FALSE
        !           414:  *
        !           415:  * HISTORY:
        !           416:  *  13:02 on Tue 25 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           417:  *      First version to do something.
        !           418:  *
        !           419:  *****************************************************************************/
        !           420: 
        !           421: BOOL
        !           422: bDelList( pFID, piDel )
        !           423: FID    *pFID;           /* Access to our stuff */
        !           424: int    *piDel;          /* A -1 terminated array of font indices to delete */
        !           425: {
        !           426: 
        !           427: 
        !           428:     ULONG     ulRec;            /* Loop through the records */
        !           429:     DWORD     dwHdrPosn;        /* Position within the file */
        !           430:     DWORD     dwFixPosn;        /* Write position in fixed file */
        !           431:     DWORD     dwVarPosn;        /* Absolute position within variable part */
        !           432:     int       iDelLeft;         /* Number of deletion choices left */
        !           433:     int       iSkip;            /* Number we have dropped */
        !           434: 
        !           435:     BOOL      bDelete;          /* True if this font to be deleted */
        !           436: 
        !           437: 
        !           438:     FF_HEADER   ffh;            /* Contains sizes! */
        !           439:     FF_REC_HEADER  ffrh;
        !           440: 
        !           441:     /*
        !           442:      *   Do we have any to delete?
        !           443:      */
        !           444: 
        !           445:      
        !           446:     if( pFID->hCurFile == INVALID_HANDLE_VALUE )
        !           447:     {
        !           448:         /*   NO existing file,  so create a new empty one!  */
        !           449: 
        !           450:         return   bFixInit( pFID->hFixFile );
        !           451:     }
        !           452: 
        !           453:     if( !bGetFileHDR( pFID->hCurFile, &ffh ) )
        !           454:         return  FALSE;
        !           455: 
        !           456:     if( piDel == NULL || *piDel <= 0 )
        !           457:     {
        !           458:         /*  Just split the master file into two: fixed and variable parts */
        !           459: 
        !           460:         LONG   lSize;
        !           461: 
        !           462: 
        !           463:         SetFilePointer( pFID->hCurFile, 0, NULL, FILE_BEGIN );
        !           464: 
        !           465:         lSize = sizeof( ffh ) + ffh.ulFixSize;
        !           466: 
        !           467:         if( lFInCopy( pFID->hFixFile, pFID->hCurFile, lSize ) != lSize ||
        !           468:             lFInCopy( pFID->hVarFile, pFID->hCurFile, ffh.ulVarSize ) != 
        !           469:                                                           (long)ffh.ulVarSize )
        !           470:         {
        !           471: #if  DBG
        !           472:             DbgPrint( "Print!bDelList: file split fails\n" );
        !           473: #endif
        !           474: 
        !           475:             return  FALSE;
        !           476:         }
        !           477: 
        !           478:         return  TRUE;
        !           479:     }
        !           480: 
        !           481:     /*
        !           482:      *  Another speed up case is the other version:  deleting all fonts!
        !           483:      */
        !           484:     
        !           485:     if( *piDel >= (int)ffh.ulRecCount )
        !           486:     {
        !           487:         /*  Simply create an empty file  */
        !           488: 
        !           489:         return  bFixInit( pFID->hFixFile );
        !           490:     }
        !           491: 
        !           492:     /*
        !           493:      *   Now determine which fonts to delete.  We do this the easy (but
        !           494:      * slower) way, namely to process each record individually.  We
        !           495:      * read the header,  determine whether to delete, and if not, then
        !           496:      * copy the relevant portions to the output files.
        !           497:      */
        !           498: 
        !           499:     dwHdrPosn = ffh.ulFixData;          /* Initial location */
        !           500:     dwFixPosn = ffh.ulFixData;          /* Writing location in fixed file */
        !           501:     dwVarPosn = ffh.ulVarData;          /* Starting location in variable */
        !           502:     iSkip = 0;                          /* Count number we drop off */
        !           503:     iDelLeft = *piDel;                  /* Number to delete */
        !           504:     ffh.ulFixSize = 0;                  /* Count it as we copy */
        !           505: 
        !           506:     for( ulRec = 0; ulRec < ffh.ulRecCount; ++ulRec )
        !           507:     {
        !           508: 
        !           509:         /*  First read the header to read the record size */
        !           510: 
        !           511:         if( !bGetRecHDR( pFID->hCurFile, &ffrh, dwHdrPosn ) )
        !           512:             return  FALSE;                      /* SHOULD NOT HAPPEN */
        !           513: 
        !           514:         if( ffrh.ulNextOff == 0 )
        !           515:         {
        !           516: #if  DBG
        !           517:             DbgPrint( "Print!bDelList: unexpected EOF record at #%ld\n",
        !           518:                                                                     ulRec );
        !           519: #endif
        !           520: 
        !           521:             break;
        !           522:         }
        !           523:         /*
        !           524:          *   Is this on the delete list??
        !           525:          */
        !           526: 
        !           527:         bDelete = FALSE;                /* Assume not */
        !           528: 
        !           529:         if( iDelLeft > 0 )
        !           530:         {
        !           531:             /*   Scan the list,  looking for this index  */
        !           532:             int   iI;
        !           533: 
        !           534:             for( iI = 1; !bDelete && iI <= *piDel; ++iI )
        !           535:             {
        !           536:                 if( *(piDel + iI) == (int)ulRec )
        !           537:                 {
        !           538:                     bDelete = TRUE;
        !           539:                     --iDelLeft;
        !           540:                 }
        !           541:             }
        !           542:         }
        !           543: 
        !           544:         if( bDelete )
        !           545:         {
        !           546:             /*  Skip this one,  so adjust offsets & counts.  */
        !           547:             iSkip++;            /* Reduce count at the end. */
        !           548:         }
        !           549:         else
        !           550:         {
        !           551:             /*
        !           552:              *   First step is to copy the variable part.  This is done
        !           553:              * first as we need to update the data position within the
        !           554:              * header record for the fixed part.  So copy now to find
        !           555:              * out where it is being placed.
        !           556:              */
        !           557:             
        !           558:             dwVarPosn = ffh.ulVarData + ffrh.ulVarOff;  /* Current file posn */
        !           559: 
        !           560:             if( ffrh.ulVarSize )
        !           561:             {
        !           562:                 /*
        !           563:                  *   Data exists,  so set file pointers.  There are two to
        !           564:                  * set.  One is to position the variable data at the dword
        !           565:                  * aligned end of the variable file,  the other is to
        !           566:                  * set the position of the current file pointer to the
        !           567:                  * correct location in that file.
        !           568:                  */
        !           569: 
        !           570:                 /*  First the new variable file */
        !           571: 
        !           572:                 ffrh.ulVarOff = (GetFileSize( pFID->hVarFile, NULL ) +3) & ~0x3;
        !           573:                 SetFilePointer( pFID->hVarFile, ffrh.ulVarOff, NULL,
        !           574:                                                                  FILE_BEGIN );
        !           575: 
        !           576:                 /*  The current file's variable data */
        !           577: 
        !           578:                 SetFilePointer( pFID->hCurFile, dwVarPosn, NULL, FILE_BEGIN );
        !           579: 
        !           580:                 if( lFInCopy( pFID->hVarFile, pFID->hCurFile, ffrh.ulVarSize )
        !           581:                                                 != (long)ffrh.ulVarSize )
        !           582:                 {
        !           583: #if  DBG
        !           584:                     DbgPrint( 
        !           585:                         "Print!bDelList: Write of variable data fails, rec #%ld\n",
        !           586:                                                                  ulRec );
        !           587: #endif
        !           588: 
        !           589:                     return  FALSE;
        !           590:                 }
        !           591:             }
        !           592: 
        !           593:             /*
        !           594:              *   Set the fixed file pointer.  First time this will skip
        !           595:              * the file header we write out at the end.  Second and later
        !           596:              * times,  it will ensure DWORD alignment of the header.
        !           597:              */
        !           598: 
        !           599: 
        !           600:             SetFilePointer( pFID->hCurFile, dwHdrPosn + sizeof( ffrh),
        !           601:                                                          NULL, FILE_BEGIN );
        !           602:             SetFilePointer( pFID->hFixFile, dwFixPosn, NULL, FILE_BEGIN );
        !           603: 
        !           604:             if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
        !           605:             {
        !           606: #if  DBG
        !           607:                 DbgPrint( "Print!bDelList: bWrite of new header, rec %ld\n",
        !           608:                                                                       ulRec );
        !           609: #endif
        !           610: 
        !           611:                 return  FALSE;
        !           612:             }
        !           613: 
        !           614:             /*  And also the actual data part!  */
        !           615: 
        !           616:             if( lFInCopy( pFID->hFixFile, pFID->hCurFile, ffrh.ulSize ) !=
        !           617:                                                           (long)ffrh.ulSize )
        !           618:             {
        !           619: #if  DBG
        !           620:                 DbgPrint(
        !           621:                     "Print!bDelList: Can't copy FIX part of file at rec #%ld\n",
        !           622:                                                                  ulRec );
        !           623: #endif
        !           624: 
        !           625:                 return  FALSE;
        !           626:             }
        !           627:             dwFixPosn += ffrh.ulNextOff;                /* Next location */
        !           628:             ffh.ulFixSize += sizeof( ffrh ) + ffrh.ulSize;
        !           629: 
        !           630:         }
        !           631:         dwHdrPosn += ffrh.ulNextOff;
        !           632:     }
        !           633: 
        !           634:     /*
        !           635:      *   Need to write the trailing header to our file. This contains
        !           636:      * a zero size, so that is really all that is important.
        !           637:      */
        !           638: 
        !           639:     ffrh.ulNextOff = 0;
        !           640: 
        !           641:     if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
        !           642:         return  FALSE;
        !           643: 
        !           644:     ffh.ulRecCount -= iSkip;            /* The number we dropped! */
        !           645: 
        !           646:     /*
        !           647:      *   Rewrite the header record for the adding code.
        !           648:      */
        !           649: 
        !           650:     SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );
        !           651: 
        !           652:     return  bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) );
        !           653: }
        !           654: 
        !           655: /****************************** Function Header ******************************
        !           656:  * bAddFList
        !           657:  *      Add a list of new fonts to an existing font file.  This is
        !           658:  *      called to add the data to our existing file.  File creation or
        !           659:  *      shrinking is done elsewhere.
        !           660:  *
        !           661:  * RETURNS:
        !           662:  *      Number of bytes written to the file; -1 for error.
        !           663:  *
        !           664:  * HISTORY:
        !           665:  *  14:20 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           666:  *      Started working on it.
        !           667:  *
        !           668:  *****************************************************************************/
        !           669: 
        !           670: BOOL
        !           671: bAddFList( pFID, pFList )
        !           672: FID       *pFID;                /* Font installation data */
        !           673: FONTLIST  *pFList;              /* The fonts to be added */
        !           674: {
        !           675: 
        !           676:     DWORD     dwLoc;            /* File location of interest */
        !           677:     DWORD     dwVarLoc;         /* Location in the variable data part */
        !           678:     int       iSize;            /* Number of bytes written by user */
        !           679:     int       iVarSize;         /* Size of variable length portion */
        !           680: 
        !           681: 
        !           682:     FF_HEADER  ffh;             /* The overall file header */
        !           683:     FF_REC_HEADER  ffrh;        /* Per record header */
        !           684: 
        !           685: 
        !           686:     if( pFList == NULL )
        !           687:         return  TRUE;           /* No data, no processing!  */
        !           688: 
        !           689:     /*
        !           690:      *   First step is to step through the file, down the chain of
        !           691:      * records until we reach the end. We append the data there: the
        !           692:      * data consists of a record header plus whatever data the user
        !           693:      * writes and tells us about. We also allow the user the option
        !           694:      * of adding data to variable length part of the file.
        !           695:      */
        !           696: 
        !           697:     if( !bGetFileHDR( pFID->hFixFile, &ffh ) )
        !           698:         return  FALSE;
        !           699: 
        !           700: 
        !           701:     /*   Can now read the file header - it WILL exist!  */
        !           702:     dwLoc = ffh.ulFixData;
        !           703: 
        !           704:     while( bGetRecHDR( pFID->hFixFile, &ffrh, dwLoc ) && ffrh.ulNextOff )
        !           705:         dwLoc += ffrh.ulNextOff;                 /* Next location  */
        !           706: 
        !           707:     /*
        !           708:      *   Can now process the user's list of stuff to write out.
        !           709:      * The writing out is done by user supplied functions - they
        !           710:      * tell us how much was written, we simply update the red tape.
        !           711:      */
        !           712: 
        !           713:     dwVarLoc = SetFilePointer( pFID->hVarFile, 0, NULL, FILE_END );
        !           714: 
        !           715:     for( ; pFList; pFList = (FONTLIST *)pFList->pFLNext )
        !           716:     {
        !           717: 
        !           718:         /*  First write out the header array type data  */
        !           719: 
        !           720:         SetFilePointer( pFID->hFixFile, dwLoc + sizeof( FF_REC_HEADER ),
        !           721:                                                          NULL, FILE_BEGIN );
        !           722: 
        !           723:         iSize = iFIWriteFix( pFID->hFixFile, pFID->hHeap, pFList->pvFixData );
        !           724: 
        !           725:         if( iSize < 0 )
        !           726:             return  FALSE;              /* Bad news */
        !           727: 
        !           728:         ffrh.ulSize = (ULONG)iSize;             /* For the record */
        !           729:         ffh.ulRecCount++;               /* One more! */
        !           730: 
        !           731:         /*
        !           732:          *   Position of next entry:  make it DWORD aligned so that we
        !           733:          * can memory map the file.
        !           734:          */
        !           735:         ffrh.ulNextOff = sizeof( ffrh ) + (iSize + 3) & ~0x3;
        !           736:         ffh.ulFixSize += ffrh.ulNextOff;
        !           737: 
        !           738:         /*
        !           739:          *   The variable length part of the data.  Much the same as
        !           740:          * above,  simply a different function to call.
        !           741:          */
        !           742: 
        !           743:         SetFilePointer( pFID->hVarFile, dwVarLoc, NULL, FILE_BEGIN );
        !           744: 
        !           745:         iVarSize = iFIWriteVar( pFID->hVarFile, pFID->hHeap, pFList->pvVarData );
        !           746: 
        !           747:         if( iVarSize < 0 )      
        !           748:             return  FALSE;                      /* Not good */
        !           749: 
        !           750:         ffrh.ulVarSize = (ULONG)iVarSize;
        !           751:         if( iVarSize > 0 )
        !           752:         {
        !           753:             /*  A zero return means no data - quite legitimate */
        !           754: 
        !           755:             ffrh.ulVarOff = dwVarLoc;
        !           756:             dwVarLoc += (iVarSize + 3) & ~0x3;
        !           757:         }
        !           758:         else
        !           759:             ffrh.ulVarOff = 0;          /* No data for this one. */
        !           760: 
        !           761: 
        !           762:         /*  Finally,  write out the header for the array data  */
        !           763: 
        !           764:         SetFilePointer( pFID->hFixFile, dwLoc, NULL, FILE_BEGIN );
        !           765: 
        !           766:         if( !bWrite( pFID->hFixFile, &ffrh, sizeof( FF_REC_HEADER ) ) )
        !           767:         {
        !           768: #if  DBG
        !           769:             DbgPrint( "Print!bWrite of FF_REC_HEADER fails\n" );
        !           770: #endif
        !           771:             return  FALSE;
        !           772:         }
        !           773: 
        !           774:         /*   Set the file pointer to the location of the next header */
        !           775:         dwLoc += ffrh.ulNextOff;
        !           776:     }
        !           777: 
        !           778:     /*
        !           779:      *  Last step:  write out the final header,  which has ulSize set to
        !           780:      * zero to indicate that it is the terminating record.
        !           781:      */
        !           782: 
        !           783:     ffh.ulVarSize = GetFileSize( pFID->hVarFile, NULL );
        !           784: 
        !           785:     SetFilePointer( pFID->hFixFile, dwLoc, NULL, FILE_BEGIN );
        !           786: 
        !           787:     ffrh.ulNextOff = 0;         /* No more in this chain! */
        !           788: 
        !           789:     if( !bWrite( pFID->hFixFile, &ffrh, sizeof( ffrh ) ) )
        !           790:         return  FALSE;
        !           791: 
        !           792:     /*
        !           793:      *   Finally,  update the master header.
        !           794:      */
        !           795: 
        !           796:     SetFilePointer( pFID->hFixFile, 0, NULL, FILE_BEGIN );
        !           797:     if( !bWrite( pFID->hFixFile, &ffh, sizeof( ffh ) ) )
        !           798:         return  FALSE;
        !           799: 
        !           800:     return  TRUE;
        !           801: }
        !           802: 
        !           803: /******************************** Function Header **************************
        !           804:  * bGetFileHDR
        !           805:  *      Read in the FF_HEADER for the font installer file.  This is
        !           806:  *      always located at the beginning of the file!  Returns TRUE
        !           807:  *      if the read was AOK,  and the structure is verified.
        !           808:  *
        !           809:  * RETURNS:
        !           810:  *      TRUE/FALSE
        !           811:  *
        !           812:  * HISTORY:
        !           813:  *  15:40 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           814:  *      First incarnation.
        !           815:  *
        !           816:  ***************************************************************************/
        !           817: 
        !           818: BOOL
        !           819: bGetFileHDR( hFile, pffh )
        !           820: HANDLE     hFile;                       /* The file */
        !           821: FF_HEADER *pffh;                        /* The header to fill in */
        !           822: {
        !           823:     /*
        !           824:      *  Not hard:  seek to the beginning of the file,  then read in the
        !           825:      * structure there, and VERIFY it!
        !           826:      */
        !           827: 
        !           828:     DWORD  dwIn;                /* Bytes read */
        !           829: 
        !           830: 
        !           831:     SetFilePointer( hFile, 0, NULL, FILE_BEGIN );               /* Start */
        !           832: 
        !           833:     if( !ReadFile( hFile, pffh, sizeof( FF_HEADER ), &dwIn, NULL ) ||
        !           834:         dwIn != sizeof( FF_HEADER ) )
        !           835:     {
        !           836:                 return  FALSE;
        !           837:     }
        !           838:     
        !           839:     return  pffh->ulID == FF_ID;
        !           840: }
        !           841: 
        !           842: 
        !           843: /******************************* Function Header ****************************
        !           844:  * bGetRecHDR
        !           845:  *      Read the FF_REC_HEADER structure at the given location with the
        !           846:  *      file,  and return TRUE if read successfully.  This means the
        !           847:  *      read was AOK,  and the structure is acceptable.
        !           848:  *
        !           849:  * RETURNS:
        !           850:  *      TRUE/FALSE
        !           851:  *
        !           852:  * HISTORY:
        !           853:  *  15:38 on Sat 22 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           854:  *      Starting out.
        !           855:  *
        !           856:  ****************************************************************************/
        !           857: 
        !           858: BOOL
        !           859: bGetRecHDR( hFile, pffrh, dwLoc )
        !           860: HANDLE          hFile;          /* File to read from */
        !           861: FF_REC_HEADER  *pffrh;          /* Structure to fill in */
        !           862: DWORD           dwLoc;          /* Location of data in file: absolute */
        !           863: {
        !           864:     /*
        !           865:      *   Seek to the specified location,  and read in the data there!
        !           866:      * Perform consistency checks as above in bGetFileHDR.
        !           867:      */
        !           868: 
        !           869:     DWORD   dwIn;               /* Bytes read */
        !           870: 
        !           871: 
        !           872:     SetFilePointer( hFile, dwLoc, NULL, FILE_BEGIN );
        !           873: 
        !           874:     if( !ReadFile( hFile, pffrh, sizeof( FF_REC_HEADER ), &dwIn, NULL ) ||
        !           875:         dwIn != sizeof( FF_REC_HEADER ) )
        !           876:     {
        !           877:                 return  FALSE;
        !           878:     }
        !           879: 
        !           880:     return  pffrh->ulRID == FR_ID;
        !           881: }
        !           882: 
        !           883: 
        !           884: /**************************** Function Header ******************************
        !           885:  * bFixInit
        !           886:  *      Writes a no information header into the file.  This means that
        !           887:  *      other functions can proceed on the basis that the file contains
        !           888:  *      valid structures and links.
        !           889:  *
        !           890:  * RETURNS:
        !           891:  *      TRUE/FALSE;  FALSE on failure.
        !           892:  *
        !           893:  * HISTORY:
        !           894:  *  13:39 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           895:  *      Initial
        !           896:  *
        !           897:  ***************************************************************************/
        !           898: 
        !           899: BOOL
        !           900: bFixInit( hFile )
        !           901: HANDLE  hFile;
        !           902: {
        !           903:     /*
        !           904:      *   As a minimum,  the file needs a FF_HEADER and a FF_REC_HEADER
        !           905:      *  structure.  The first contains an offset to the second, and
        !           906:      *  no variable length data start location.  The latter contains
        !           907:      *  a zero size field, indicating no more data.
        !           908:      */
        !           909: 
        !           910:     FF_HEADER      ffh;         /* Overall file header */
        !           911:     FF_REC_HEADER  ffrh;        /* Individual record header */
        !           912: 
        !           913:     /*
        !           914:      *  Initialise the FF_HEADER before writing it out.
        !           915:      */
        !           916: 
        !           917: 
        !           918:     ffh.ulID = FF_ID;
        !           919:     ffh.ulVersion = FF_VERSION;
        !           920:     ffh.ulFixData = sizeof( ffh );              /* Follows us directly */
        !           921:     ffh.ulFixSize = sizeof( ffrh );             /* Bytes in fixed area */
        !           922:     ffh.ulRecCount = 0;                         /* No records yet! */
        !           923:     ffh.ulVarData = 0;                          /* None - YET! */
        !           924:     ffh.ulVarSize = 0;
        !           925: 
        !           926: 
        !           927:     ffrh.ulRID = FR_ID;
        !           928:     ffrh.ulSize = 0;
        !           929:     ffrh.ulNextOff = 0;                 /* EOF for fixed part of file */
        !           930:     ffrh.ulVarOff = 0;
        !           931:     ffrh.ulVarSize = 0;
        !           932: 
        !           933:     if( !bWrite( hFile, &ffh, sizeof( ffh )) ||
        !           934:         !bWrite( hFile, &ffrh, sizeof( ffrh )) )
        !           935:     {
        !           936: #if  DBG
        !           937:         DbgPrint( "Print!bFixInit fails\n" );
        !           938: #endif
        !           939: 
        !           940:         return  FALSE;
        !           941:     }
        !           942: 
        !           943:     return  TRUE;
        !           944: }
        !           945: 
        !           946: /**************************** Function Header ******************************
        !           947:  *  vFIClean
        !           948:  *      The clean up the mess during bail out function.  Removes the 
        !           949:  *      temporary files, frees heap storage and whatever else is
        !           950:  *      required.
        !           951:  *
        !           952:  * RETURNS:
        !           953:  *      Zilch
        !           954:  *
        !           955:  * HISOTRY:
        !           956:  *  13:25 on Mon 24 Feb 1992    -by-    Lindsay Harris   [lindsayh]
        !           957:  *      Start on it - it probably will grow.
        !           958:  *
        !           959:  ***************************************************************************/
        !           960: 
        !           961: void
        !           962: vFIClean( pFID )
        !           963: FID   *pFID;
        !           964: {
        !           965:     /*
        !           966:      *   Need to be slightly careful about what we do. In particular,  NO
        !           967:      * bad memory accesses.
        !           968:      */
        !           969: 
        !           970:     if( pFID->dwID != FID_ID )
        !           971:         return;
        !           972: 
        !           973:     /*
        !           974:      *   Free any temporary files we may have created.  Note that we
        !           975:      * must close the files before we can remove.  Silly idea that is.
        !           976:      */
        !           977: 
        !           978: 
        !           979:     if( pFID->hCurFile != INVALID_HANDLE_VALUE )
        !           980:         CloseHandle( pFID->hCurFile );
        !           981: 
        !           982:     if( pFID->hFixFile != INVALID_HANDLE_VALUE )
        !           983:         CloseHandle( pFID->hFixFile );
        !           984: 
        !           985:     if( pFID->hVarFile != INVALID_HANDLE_VALUE )
        !           986:         CloseHandle( pFID->hVarFile );
        !           987: 
        !           988:     if( pFID->pwstrFixName )
        !           989:     {
        !           990:         DeleteFileW( pFID->pwstrFixName );              /* Ignore failure */
        !           991: 
        !           992:         HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrFixName );
        !           993:         pFID->pwstrFixName = 0;
        !           994:     }
        !           995: 
        !           996:     if( pFID->pwstrVarName )
        !           997:     {
        !           998:         DeleteFileW( pFID->pwstrVarName );
        !           999: 
        !          1000:         HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrVarName );
        !          1001:         pFID->pwstrFixName = 0;
        !          1002:     }
        !          1003: 
        !          1004:     if( pFID->pwstrCurName )
        !          1005:     {
        !          1006:         HeapFree( pFID->hHeap, 0, (LPSTR)pFID->pwstrCurName );
        !          1007:         pFID->pwstrCurName = 0;
        !          1008:     }
        !          1009: 
        !          1010: 
        !          1011:     pFID->dwID = (DWORD)~FID_ID;        /* Invalid in case mem reused */
        !          1012: 
        !          1013:     HeapFree( pFID->hHeap, 0, (LPSTR)pFID );
        !          1014: 
        !          1015:     return;
        !          1016: }

unix.superglobalmegacorp.com

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