|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.