320 lines
9.7 KiB
C
320 lines
9.7 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: fon16.c
|
|
*
|
|
* routines for accessing font resources within *.fon files
|
|
* (win 3.0 16 bit dlls)
|
|
*
|
|
* Created: 08-May-1991 12:55:14
|
|
* Author: Bodin Dresevic [BodinD]
|
|
*
|
|
* Copyright (c) 1990 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "fd.h"
|
|
#include "exehdr.h"
|
|
|
|
// GETS ushort at (PBYTE)pv + off. both pv and off must be even
|
|
|
|
#define US_GET(pv,off) ( *(PUSHORT)((PBYTE)(pv) + (off)) )
|
|
#define S_GET(pv,off) ((SHORT)US_GET((pv),(off)))
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* bInitWinResData
|
|
*
|
|
* Initializes the fields of the WINRESDATA structure so as to make it
|
|
* possible for the user to access *.fnt resources within the
|
|
* corresponding *.fon file
|
|
*
|
|
* The function returns True if *.fnt resources found in the *.fon
|
|
* file, otherwise false (if not an *.fon file or if it contains no
|
|
* *.fnt resources
|
|
*
|
|
*
|
|
* History:
|
|
* 09-May-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
bInitWinResData(
|
|
PVOID pvView,
|
|
COUNT cjView,
|
|
PWINRESDATA pwrd
|
|
)
|
|
{
|
|
PBYTE pjNewExe; // ptr to the beginning of the new exe hdr
|
|
PBYTE pjResType; // ptr to the beginning of TYPEINFO struct
|
|
PBYTE pjResName; // ptr to the beginning of NAMEINFO struct
|
|
ULONG iResID; // resource type id
|
|
|
|
#ifdef DUMPCALL
|
|
DbgPrint("\nbInitWinResData(");
|
|
DbgPrint("\n PFILEVIEW pfvw = %-#8lx", pfvw);
|
|
DbgPrint("\n PWINRESDATA pwrd = %-#8lx", pwrd);
|
|
DbgPrint("\n )\n");
|
|
#endif
|
|
|
|
pwrd->pvView = pvView;
|
|
pwrd->cjView = cjView;
|
|
|
|
// check the magic # at the beginning of the old header
|
|
|
|
if (US_GET(pvView, OFF_e_magic) != EMAGIC)
|
|
return(FALSE);
|
|
|
|
pwrd->dpNewExe = (PTRDIFF)READ_DWORD((PBYTE)pvView + OFF_e_lfanew);
|
|
|
|
// make sure that offset is consistent
|
|
|
|
if ((ULONG)pwrd->dpNewExe > pwrd->cjView)
|
|
return FALSE;
|
|
|
|
pjNewExe = (PBYTE)pvView + pwrd->dpNewExe;
|
|
|
|
if (US_GET(pjNewExe, OFF_ne_magic) != NEMAGIC)
|
|
return(FALSE);
|
|
|
|
pwrd->cjResTab = (ULONG)(US_GET(pjNewExe, OFF_ne_restab) -
|
|
US_GET(pjNewExe, OFF_ne_rsrctab));
|
|
|
|
if (pwrd->cjResTab == 0L)
|
|
{
|
|
//
|
|
// The following test is applied by DOS, so I presume that it is
|
|
// legitimate. The assumption is that the resident name table
|
|
// FOLLOWS the resource table directly, and that if it points to
|
|
// the same location as the resource table, then there are no
|
|
// resources.
|
|
|
|
WARNING("No resources in *.fon file\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
// want offset from pvView, not from pjNewExe => must add dpNewExe
|
|
|
|
pwrd->dpResTab = (PTRDIFF)US_GET(pjNewExe, OFF_ne_rsrctab) + pwrd->dpNewExe;
|
|
|
|
// make sure that offset is consistent
|
|
|
|
if ((ULONG)pwrd->dpResTab > pwrd->cjView)
|
|
return FALSE;
|
|
|
|
// what really lies at the offset OFF_ne_rsrctab is a NEW_RSRC.rs_align field
|
|
// that is used in computing resource data offsets and sizes as a shift factor.
|
|
// This field occupies two bytes on the disk and the first TYPEINFO structure
|
|
// follows right after. We want pwrd->dpResTab to point to the first
|
|
// TYPEINFO structure, so we must add 2 to get there and subtract 2 from
|
|
// the length
|
|
|
|
pwrd->ulShift = (ULONG) US_GET(pvView, pwrd->dpResTab);
|
|
pwrd->dpResTab += 2;
|
|
pwrd->cjResTab -= 2;
|
|
|
|
// Now we want to determine where the resource data is located.
|
|
// The data consists of a RSRC_TYPEINFO structure, followed by
|
|
// an array of RSRC_NAMEINFO structures, which are then followed
|
|
// by a RSRC_TYPEINFO structure, again followed by an array of
|
|
// RSRC_NAMEINFO structures. This continues until an RSRC_TYPEINFO
|
|
// structure which has a 0 in the rt_id field.
|
|
|
|
pjResType = (PBYTE)pvView + pwrd->dpResTab;
|
|
iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
|
|
|
|
while((iResID != 0L) && (iResID != RT_FNT))
|
|
{
|
|
// # of NAMEINFO structures that follow = resources of this type
|
|
|
|
ULONG crn = (ULONG)US_GET(pjResType, OFF_rt_nres);
|
|
|
|
// get ptr to the new TYPEINFO struc and the new resource id
|
|
|
|
pjResType = pjResType + CJ_TYPEINFO + crn * CJ_NAMEINFO;
|
|
iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
|
|
}
|
|
|
|
if (iResID == RT_FNT) // we found the font resource type
|
|
{
|
|
// # of NAMEINFO structures that follow == # of font resources
|
|
|
|
pwrd->cFntRes = (ULONG)US_GET(pjResType, OFF_rt_nres);
|
|
|
|
// this is ptr to the first NAMEINFO struct that follows
|
|
// an RT_FNT TYPEINFO structure
|
|
|
|
pjResName = pjResType + CJ_TYPEINFO;
|
|
pwrd->dpFntTab = (PTRDIFF)(pjResName - (PBYTE)pvView);
|
|
}
|
|
else // iResID == 0L, no font resources found in the font file
|
|
{
|
|
// no font resources
|
|
|
|
pwrd->cFntRes = (ULONG)0;
|
|
pwrd->dpFntTab = (PTRDIFF)0;
|
|
return(FALSE);
|
|
}
|
|
|
|
// make sure that offset is consistent
|
|
|
|
if ((ULONG)pwrd->dpFntTab > pwrd->cjView)
|
|
return FALSE;
|
|
|
|
// Now we search for the FONDIR resource. Windows actually grabs facenames
|
|
// from the FONDIR entries and not the FNT entries. For some wierd fonts this
|
|
// makes a difference. [gerritv]
|
|
|
|
|
|
pjResType = (PBYTE)pvView + pwrd->dpResTab;
|
|
iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
|
|
|
|
while((iResID != 0L) && (iResID != RT_FDIR))
|
|
{
|
|
// # of NAMEINFO structures that follow = resources of this type
|
|
|
|
ULONG crn = (ULONG)US_GET(pjResType, OFF_rt_nres);
|
|
|
|
// get ptr to the new TYPEINFO struc and the new resource id
|
|
|
|
pjResType = pjResType + CJ_TYPEINFO + crn * CJ_NAMEINFO;
|
|
iResID = (ULONG) US_GET(pjResType,OFF_rt_id);
|
|
}
|
|
|
|
if (iResID == RT_FDIR) // we found the font resource type
|
|
{
|
|
COUNT cFdirEntries;
|
|
|
|
// this is ptr to the first NAMEINFO struct that follows
|
|
// an RT_FDIR TYPEINFO structure
|
|
|
|
pjResName = pjResType + CJ_TYPEINFO;
|
|
|
|
// Get the offset to res data computed from the top of the new header
|
|
|
|
pwrd->dpFdirRes = (PTRDIFF)((ULONG)US_GET(pjResName,OFF_rn_offset) <<
|
|
pwrd->ulShift);
|
|
|
|
if ((ULONG)pwrd->dpFdirRes > pwrd->cjView)
|
|
return FALSE;
|
|
|
|
// Now pwrd->dpFdirRes is an offset to the FONTDIR resource, the first
|
|
// byte will be the number of entries in the font dir. Lets make sure it
|
|
// matches the number of FNT resources in the file.
|
|
|
|
cFdirEntries = (ULONG)US_GET(pvView,pwrd->dpFdirRes);
|
|
|
|
if( cFdirEntries != pwrd->cFntRes )
|
|
{
|
|
WARNING( "bInitWinResData: # of FONTDIR entries != # of FNT entries.\n");
|
|
pwrd->cFntRes = (ULONG)0;
|
|
pwrd->dpFntTab = (PTRDIFF)0;
|
|
return(FALSE);
|
|
}
|
|
|
|
// now increment dpFdirRes so it points passed the count of entries and
|
|
// to the first entry.
|
|
|
|
pwrd->dpFdirRes += 2;
|
|
|
|
return(TRUE);
|
|
}
|
|
else // iResID == 0L, no FONTDIR resources found in the font file
|
|
{
|
|
// no font resources
|
|
|
|
pwrd->cFntRes = (ULONG)0;
|
|
pwrd->dpFntTab = (PTRDIFF)0;
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vGetFntResource
|
|
*
|
|
* Writes the pointer to and the size of the iFntRes-th *.fnt resource
|
|
* of the *.fon file identified by pwrd. The info is written into RES_ELEM
|
|
* structure if successful. The function returns FALSE if it is not possible
|
|
* to locate iFntRes-th *.fnt resource in the file.
|
|
*
|
|
*
|
|
* History:
|
|
* 09-May-1991 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
vGetFntResource(
|
|
PWINRESDATA pwrd ,
|
|
ULONG iFntRes,
|
|
PRES_ELEM pre
|
|
)
|
|
{
|
|
PBYTE pjResName,pjFaceName;
|
|
PTRDIFF dpResData;
|
|
|
|
#ifdef DUMPCALL
|
|
DbgPrint("\nvGetFntResource(");
|
|
DbgPrint("\n PWINRESDATA pwrd = %-#8lx", pwrd);
|
|
DbgPrint("\n ULONG iFntRes = %-#8lx", iFntRes);
|
|
DbgPrint("\n PRES_ELEM pre = %-#8lx", pre);
|
|
DbgPrint("\n )\n");
|
|
#endif
|
|
|
|
ASSERTGDI((pwrd->cFntRes != 0L) && (iFntRes < pwrd->cFntRes),
|
|
"vGetFntResource\n");
|
|
|
|
// get to the Beginning of the NAMEINFO struct that correspoonds to
|
|
// the iFntRes-th *.fnt resource. (Note: iFntRes is zero based)
|
|
|
|
pjResName = (PBYTE)pwrd->pvView + pwrd->dpFntTab + iFntRes * CJ_NAMEINFO;
|
|
|
|
// Get the offset to res data computed from the top of the new header
|
|
|
|
dpResData = (PTRDIFF)((ULONG)US_GET(pjResName,OFF_rn_offset) <<
|
|
pwrd->ulShift);
|
|
|
|
pre->pvResData = (PVOID)((PBYTE)pwrd->pvView + dpResData);
|
|
pre->dpResData = dpResData;
|
|
|
|
pre->cjResData = (ULONG)US_GET(pjResName,OFF_rn_length) << pwrd->ulShift;
|
|
|
|
// Get the face name from the FONTDIR
|
|
|
|
pjFaceName = (PBYTE) (PBYTE)pwrd->pvView + pwrd->dpFdirRes;
|
|
|
|
do
|
|
{
|
|
// The first two bytes of the entry are the resource index so we will skip
|
|
// past that. After that add in the size of the font header. This will
|
|
// point us to the string for the device_name
|
|
|
|
|
|
pjFaceName += 2 + OFF_BitsOffset;
|
|
|
|
// skip past the device name
|
|
|
|
while( *pjFaceName++ );
|
|
|
|
// pjFaceName now really points to the facename
|
|
|
|
|
|
if( iFntRes )
|
|
{
|
|
// skip past the facename if this isn't one we are looking for
|
|
|
|
while( *pjFaceName++ );
|
|
|
|
}
|
|
|
|
}
|
|
while( iFntRes-- );
|
|
|
|
pre->pjFaceName = pjFaceName;
|
|
|
|
#ifdef FOOGOO
|
|
KdPrint(("%s: offset= 0x%lx, charset = %ld\n", pjFaceName, dpResData + OFF_CharSet, *((BYTE *)pwrd->pvView + dpResData + OFF_CharSet)));
|
|
#endif
|
|
return;
|
|
}
|