|
|
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.