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