You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
10 KiB
453 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
osffread.c
|
|
|
|
Abstract:
|
|
|
|
Functions to assist processing of the data of NT 4.0 soft font
|
|
installer file format.
|
|
|
|
Environment:
|
|
|
|
Windows NT Unidrv driver
|
|
|
|
Revision History:
|
|
|
|
12/02/96 -ganeshp-
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifndef WINNT_40
|
|
|
|
// NT 5.0 only
|
|
|
|
|
|
//
|
|
// Local function prototypes.
|
|
//
|
|
|
|
INT
|
|
IFIOpenRead(
|
|
FI_MEM *pFIMem, /* Output goes here */
|
|
PWSTR pwstrName /* Name of printer data file */
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Makes the font installer file accessible & memory mapped. Called
|
|
by a driver to gain access to the fonts in the font installer's
|
|
output file.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
FI_MEM : Font Installer Header
|
|
PWSTR : Font file.
|
|
|
|
Return Value:
|
|
|
|
Number of records in the file; 0 for an empty/non-existant file.
|
|
|
|
Note:
|
|
12-02-96: Created it -ganeshp-
|
|
--*/
|
|
|
|
{
|
|
|
|
INT iRet;
|
|
DWORD dwSize; /* Size of buffer needed for file name */
|
|
PWSTR pwstrLocal;
|
|
|
|
//
|
|
// Initiazlie to ZERO.
|
|
//
|
|
iRet = 0;
|
|
|
|
//
|
|
// Initalize pFIMem
|
|
//
|
|
pFIMem->hFile = NULL; /* No data until we have it */
|
|
pFIMem->pbBase = NULL;
|
|
|
|
//
|
|
// First map the file to memory. However,we do need firstly to
|
|
// generate the file name of interest. This is based on the data
|
|
// file name for this type of printer.
|
|
// Allocate more storage than is indicated: we MAY want to add
|
|
// a prefix to the file name rather than replace the existing one.
|
|
//
|
|
|
|
//
|
|
// Filename + ".fi_" + NULL
|
|
//
|
|
dwSize = sizeof( WCHAR ) * (wcslen( pwstrName ) + 4 + 1);
|
|
|
|
if( pwstrLocal = (PWSTR)MemAllocZ( dwSize ) )
|
|
{
|
|
/* Got the memory, so fiddle the file name to our standard */
|
|
|
|
int iPtOff; /* Location of '.' */
|
|
DWORD dwAttributes;
|
|
|
|
StringCchCopyW(pwstrLocal, dwSize / sizeof(WCHAR), pwstrName);
|
|
|
|
//
|
|
// Go looking for a '.' - if not found, append to string.
|
|
//
|
|
|
|
iPtOff = wcslen( pwstrLocal );
|
|
|
|
while( --iPtOff > 0 )
|
|
{
|
|
if( *(pwstrLocal + iPtOff) == (WCHAR)'.' )
|
|
break;
|
|
}
|
|
|
|
if( iPtOff <= 0 )
|
|
{
|
|
iPtOff = wcslen( pwstrLocal ); /* Presume none! */
|
|
*(pwstrLocal + iPtOff) = L'.';
|
|
}
|
|
++iPtOff; /* Skip the period */
|
|
|
|
//
|
|
// Generate the name and map the file
|
|
//
|
|
StringCchCopyW(pwstrLocal + iPtOff,
|
|
dwSize / sizeof(WCHAR) - iPtOff,
|
|
FILE_FONTS);
|
|
|
|
//
|
|
// Check the existence of soft font file.
|
|
//
|
|
dwAttributes = GetFileAttributes(pwstrLocal);
|
|
|
|
//
|
|
// If the function succeeds, open file. Otherwise return 0.
|
|
//
|
|
if (dwAttributes != 0xffffffff)
|
|
{
|
|
pFIMem->hFile = MapFile( pwstrLocal);
|
|
|
|
if (pFIMem->hFile)
|
|
{
|
|
pFIMem->pbBase = pFIMem->hFile;
|
|
|
|
iRet = IFIRewind( pFIMem );
|
|
}
|
|
}
|
|
|
|
MemFree( pwstrLocal ); /* No longer needed */
|
|
}
|
|
|
|
return iRet;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
BFINextRead(
|
|
FI_MEM *pFIMem
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates pFIMem to the next entry in the font installer file.
|
|
Returns TRUE if OK, and updates the pointers in pFIMem.
|
|
|
|
Arguments:
|
|
|
|
FI_MEM : Font Installer Header
|
|
|
|
Return Value:
|
|
|
|
TRUE/FALSE. FALSE for EOF, otherwise pFIMem updated.
|
|
|
|
Note:
|
|
12-02-96: Created it -ganeshp-
|
|
--*/
|
|
|
|
{
|
|
FF_HEADER *pFFH; /* Overall file header */
|
|
FF_REC_HEADER *pFFRH; /* Per record header */
|
|
|
|
/*
|
|
* Validate that we have valid data.
|
|
*/
|
|
|
|
|
|
if( pFIMem == 0 || pFIMem->hFile == NULL )
|
|
return FALSE; /* Empty file */
|
|
|
|
|
|
pFFH = (FF_HEADER *)pFIMem->pbBase;
|
|
|
|
if( pFFH->ulID != FF_ID )
|
|
{
|
|
ERR(( "UnidrvUI!bFINextRead: FF_HEADER has invalid ID\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* If pFIMem->pvFix == 0, we should return the data from the
|
|
* first record. Otherwise, return the next record in the chain.
|
|
* This is done to avoid the need to have a ReadFirst()/ReadNext()
|
|
* pair of functions.
|
|
*/
|
|
|
|
if( pFIMem->pvFix )
|
|
{
|
|
/*
|
|
* The header is located immediately before the data we last
|
|
* returned for the fixed portion of the record. SO, we back
|
|
* over it to get the header which then gives us the address
|
|
* of the next header.
|
|
*/
|
|
|
|
pFFRH = (FF_REC_HEADER *)((BYTE *)pFIMem->pvFix -
|
|
sizeof( FF_REC_HEADER ));
|
|
|
|
if( pFFRH->ulRID != FR_ID )
|
|
{
|
|
ERR(( "UnidrvUI!bFINextRead: Invalid FF_REC_HEADER ID\n" ));
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* We could check here for EOF on the existing structure, but this
|
|
* is not required BECAUSE THE ulNextOff field will be 0, so when
|
|
* it is added to our current address, we don't move. Hence, the
|
|
* check for the NEW address is OK to detect EOF.
|
|
*/
|
|
|
|
(BYTE *)pFFRH += pFFRH->ulNextOff; /* Next entry */
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Point to the first record. */
|
|
pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);
|
|
}
|
|
|
|
if( pFFRH->ulNextOff == 0 )
|
|
return FALSE;
|
|
|
|
pFIMem->pvFix = (BYTE *)pFFRH + sizeof( FF_REC_HEADER );
|
|
pFIMem->ulFixSize = pFFRH->ulSize;
|
|
|
|
if( pFIMem->ulVarSize = pFFRH->ulVarSize )
|
|
pFIMem->ulVarOff = pFFRH->ulVarOff + pFFH->ulVarData;
|
|
else
|
|
pFIMem->ulVarOff = 0; /* None here */
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
INT
|
|
IFIRewind(
|
|
FI_MEM *pFIMem /* File of importance */
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reset pFIMem to the first font in the file.
|
|
|
|
Arguments:
|
|
|
|
FI_MEM : Font Installer Header
|
|
|
|
Return Value:
|
|
|
|
Number of entries in the file.
|
|
|
|
Note:
|
|
12-02-96: Created it -ganeshp-
|
|
--*/
|
|
|
|
{
|
|
/*
|
|
* Not hard! The pFIMem contains the base address of the file, so we
|
|
* use this to find the address of the first record, and any variable
|
|
* data that corresponds with it.
|
|
*/
|
|
|
|
FF_HEADER *pFFH;
|
|
FF_REC_HEADER *pFFRH;
|
|
|
|
if( pFIMem == 0 || pFIMem->hFile == NULL )
|
|
return 0; /* None! */
|
|
|
|
|
|
/*
|
|
* The location of the first record is specified in the header.
|
|
*/
|
|
|
|
pFFH = (FF_HEADER *)pFIMem->pbBase;
|
|
if( pFFH->ulID != FF_ID )
|
|
{
|
|
ERR(( "UnidrvUI!iFIRewind: FF_HEADER has invalid ID\n" ));
|
|
return 0;
|
|
}
|
|
|
|
pFFRH = (FF_REC_HEADER *)(pFIMem->pbBase + pFFH->ulFixData);
|
|
|
|
if( pFFRH->ulRID != FR_ID )
|
|
{
|
|
ERR(( "UnidrvUI!iFIRewind: Invalid FF_REC_HEADER ID\n" ));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Set the pvFix field in the header to 0. This is used in bFINextRead
|
|
* to mean that the data for the first record should be supplied.
|
|
*/
|
|
pFIMem->pvFix = 0; /* MEANS USE FIRST NEXT READ */
|
|
pFIMem->ulFixSize = 0;
|
|
pFIMem->ulVarOff = 0; /* None here */
|
|
|
|
return pFFH->ulRecCount;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
BFICloseRead(
|
|
FI_MEM *pFIMem /* File/memory we are finished with */
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when finished with this font file.
|
|
|
|
Arguments:
|
|
|
|
FI_MEM : Font Installer Header
|
|
PDEV: Pointer to PDEV
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure.
|
|
|
|
Note:
|
|
12-02-96: Created it -ganeshp-
|
|
--*/
|
|
|
|
{
|
|
/*
|
|
* Easy! All we need do is unmap the file. We have the address too!
|
|
*/
|
|
|
|
BOOL bRet; /* Return code */
|
|
|
|
|
|
if( pFIMem == 0 || pFIMem->hFile == NULL )
|
|
return TRUE; // Nothing there to Free.
|
|
|
|
|
|
bRet = FREEMODULE( pFIMem->hFile);
|
|
pFIMem->hFile = NULL; // Stops freeing more than once
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
PVOID
|
|
MapFile(
|
|
PWSTR pwstr
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
Returns a pointer to the mapped file defined by pwstr.
|
|
|
|
Arguments:
|
|
pwstr UNICODE string containing fully qualified pathname of the
|
|
file to map.
|
|
|
|
Return Value:
|
|
Pointer to mapped memory if success, NULL if error.
|
|
|
|
Note:
|
|
UnmapViewOfFile will have to be called by the user at some point to free up
|
|
this allocation.Macro FREEMODULE can be used for this purpose.
|
|
|
|
11/3/1997 -ganeshp-
|
|
Created it.
|
|
--*/
|
|
|
|
{
|
|
PVOID pv;
|
|
HANDLE hFile, hFileMap;
|
|
|
|
//
|
|
// open the file we are interested in mapping.
|
|
//
|
|
|
|
pv = NULL;
|
|
|
|
if ((hFile = CreateFileW(pwstr,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL))
|
|
!= INVALID_HANDLE_VALUE)
|
|
{
|
|
//
|
|
// create the mapping object.
|
|
//
|
|
|
|
if (hFileMap = CreateFileMappingW(hFile,
|
|
NULL,
|
|
PAGE_READONLY,
|
|
0,
|
|
0,
|
|
(PWSTR)NULL))
|
|
{
|
|
//
|
|
// get the pointer mapped to the desired file.
|
|
//
|
|
|
|
if (!(pv = (PVOID)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0)))
|
|
{
|
|
ERR(("Unidrvui!MapFile: MapViewOfFile failed.\n"));
|
|
}
|
|
|
|
//
|
|
// now that we have our pointer, we can close the file and the
|
|
// mapping object.
|
|
//
|
|
|
|
if (!CloseHandle(hFileMap))
|
|
ERR(("Unidrvui!MapFile: CloseHandle(hFileMap) failed.\n"));
|
|
}
|
|
else
|
|
ERR(("Unidrvui!MapFile:CreateFileMappingW failed: %s\n",pwstr));
|
|
|
|
if (!CloseHandle(hFile))
|
|
ERR(("Unidrvui!MapFile: CloseHandle(hFile) failed.\n"));
|
|
}
|
|
else
|
|
ERR(("Unidrvui!Mapfile:CreateFileW failed for %s\n",pwstr));
|
|
|
|
return(pv);
|
|
}
|
|
|
|
#endif //ifndef WINNT_40
|