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