829 lines
20 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*
* Infparse.c - Setup.inf parsing code.
* Clark Cyr, Mike Colee, Todd Laney
* Copyright (C) Microsoft, 1989
* March 15, 1989
*
* Modification History:
*
* 3/15/89 CC Clark wrote this code for control Panel. This is windows
* code.
*
* 3/20/89 MC Decided this code would work for Dos and windows portion
* of setup. take out windows specifc stuff like local alloc's
* and dialog stuff. Replace it with standard C run time calls.
*
* 3/24/89 Toddla TOTAL rewrite! nothing is the same any more.
*
* 6/29/89 MC fixed getprofilestring func to not strip quotes if more
* than one field exists.
*/
#include <windows.h>
#include <dos.h>
#include <fcntl.h>
#include <io.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "inf.h"
#include "tapicpl.h"
#ifdef FAR_HEAP
/*** hack. to avoid realloc problems we make READ_BUFSIZE
as big as the inf file, thus avoiding any reallocs */
#define READ_BUFSIZE 27000 /* size of inf buffer */
#endif
#define TMP_BUFSIZE 1024 /* size of temp reads */
#define ISSEP(c) ((c) == '=' || (c) == ',')
#define ISWHITE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
#define ISNOISE(c) ((c) == '"')
#define EOF 26
#define QUOTE '"'
#define COMMA ','
#define SPACE ' '
#define EQUAL '='
PINF pinfDefault = NULL;
static PSTR pBuf;
static PINF pInf;
static WORD iBuf;
static WORD iInf;
/* Globaly used pointers to non-translatable text strings. */
char pszINFFILE[] = "mmsetup.inf";
//extern char *pszPATH;
/* Local prototypes */
BOOL multifields(PINF);
static char GETC(int fh)
{
register WORD n;
if (!pBuf)
return EOF;
n = iBuf % TMP_BUFSIZE;
if (n == 0)
{
FREAD(fh,pBuf,TMP_BUFSIZE);
}
iBuf++;
return pBuf[n];
}
#ifdef FAR_HEAP
static void PUTC(char c)
{
if (!pInf)
return;
#ifdef DOSONLY
c = XlateAnsi850(c);
#endif
pInf[iInf++] = c;
}
#else
static void PUTC(char c)
{
register WORD n;
register PINF pInfT;
if (!pInf)
return;
n = iInf % READ_BUFSIZE;
if (n == 0)
{
n = (iInf / READ_BUFSIZE) + 1;
pInfT = REALLOC(pInf,n * READ_BUFSIZE);
if (pInfT)
{
pInf = pInfT;
}
else
{
FREE(pInf);
pInf = NULL;
}
}
if (pInf)
pInf[iInf++] = c;
}
#endif
/* int infLoadFile() Load a entire INF file into memory
* comments are removed, each line is terminated
* by a \0 each section is terminated by a \0\0
* ONLY spaces inside of " " are preserved
* the end of file is marked with a ^Z
*
* RETURNS: A pointer to a block of memory containg file, NULL if failure
*
*/
PINF infLoadFile(int fh)
{
WORD len;
PINF pInfT;
register char c;
register BOOL fQuote = FALSE;
if (fh == -1)
return NULL;
len = (WORD)FSEEK(fh,0L,SEEK_END);
FSEEK(fh,0L,SEEK_SET);
iBuf = 0;
iInf = 0;
pBuf = ALLOC(TMP_BUFSIZE); // temp buffer
if (!pBuf)
return NULL;
#ifdef FAR_HEAP
pInf = FALLOC(len); // destination, at least as big as file
#else
pInf = ALLOC(READ_BUFSIZE);
#endif
if (!pInf) {
FREE((HANDLE)pBuf);
return NULL;
}
while (iBuf < len)
{
c = GETC(fh);
loop:
if (iBuf >= len)
break;
switch (c)
{
case '\r': /* ignore '\r' */
break;
case '\n':
for (; ISWHITE(c); c = GETC(fh))
;
if (c != ';')
PUTC(0); /* all lines end in a \0 */
if (c == '[')
PUTC(0); /* all sections end with \0\0 */
fQuote = FALSE;
goto loop;
break;
case '\t':
case ' ':
if (fQuote)
PUTC(c);
break;
case '"':
fQuote = !fQuote;
PUTC(c);
break;
case ';':
for (; !ISEOL(c); c = GETC(fh))
;
goto loop;
break;
default:
PUTC(c);
break;
}
}
PUTC(0);
PUTC(0);
PUTC(EOF);
FREE((HANDLE)pBuf);
// try to shrink this block
#ifdef FAR_HEAP
// just leave pInf it's original size. don't bother shrinking it
#else
pInfT = REALLOC(pInf,iInf);
if (pInfT) // if REALLOC fails just leave pInf as is
pInf = pInfT;
#endif
return pInf;
}
static int near pascal
strncmpi(LPSTR pch1, LPSTR pch2, int n)
{
while (*pch1 && --n > 0 && UPCASE(*pch1) == UPCASE(*pch2))
*pch1++,*pch2++;
return UPCASE(*pch1) != UPCASE(*pch2);
}
/* PINF FAR PASCAL infOpen()
* Takes the string held in szBasePath as the path
* to find SETUP.INF and attempts to open it. Returns
* a valid file handle is successful.
*
* RETURNS: A file pointer if successful, Null pointer in the case of
* a failure.
*
* ENTER:
* EXIT: To caller
*/
PINF FAR PASCAL infOpen(LPSTR szInf)
{
char szBuf[CPL_MAX_PATH];
short fh;
PINF pinf;
fh = -1;
if (szInf == NULL)
szInf = pszINFFILE;
/*
* Next try to open passed parameter as is. For Dos half.
*/
if (fh == -1)
{
fh = FOPEN(szInf);
}
/*
* Next try destination path\system. for win half.
*/
// if (fh == -1) {
// lstrcpy(szBuf, szSetupPath);
// catpath(szBuf, "system");
// catpath(szBuf, szInf);
// fh = FOPEN(szBuf);
// }
/*
* Next try destination path. for initial setup.
*/
// if (fh == -1) {
// lstrcpy(szBuf, szSetupPath);
// catpath(szBuf, szInf);
// fh = FOPEN(szBuf);
// }
if (fh != -1)
{
pinf = infLoadFile(fh);
FCLOSE(fh);
if (pinf && !pinfDefault)
pinfDefault = pinf;
return pinf;
}
return NULL;
}
/* void FAR PASCAL infClose(PINF pinf)
*
* ENTER:
* EXIT: To caller
*/
void FAR PASCAL infClose(PINF pinf)
{
if (pinf == NULL)
pinf = pinfDefault;
if (pinf != NULL)
{
FFREE(pinf);
if (pinf == pinfDefault)
pinfDefault = NULL;
}
}
/* FindSection locates a section in Setup.Inf. Sections are
* assumed to be delimited by a '[' as the first
* character on a line.
*
* Arguments: pInf Pointer to SETUP.INF buffer
* pszSect LPSTR to section name
*
* Return: WORD file position of the first line in the section
* 0 if section not found
*/
WORD FindSection(PINF pInf, LPSTR pszSect)
{
BOOL fFound = FALSE;
short nLen = lstrlen(pszSect);
PINF pch;
char ch;
if (!pInf)
return 0;
pch = pInf;
while (!fFound && *pch != EOF)
{
if (*pch++ == '[')
{
fFound = !strncmpi(pszSect, pch, nLen) && pch[nLen] == ']';
}
/*
* go to the next line, dont forget to skip over \0 and \0\0
*/
while (*pch != EOF && *pch != '\0')
pch++;
while (*pch == 0)
pch++;
}
return((fFound && *pch != '[' && *pch != EOF) ? pch - pInf : 0);
}
/* char* fnGetDataString(npszData,szDataStr)
*
* Called by functions that read sections of information from setup.inf
* to obtain strings that are set equal to keywords. Example:
*
* welcome=("Hello There")
*
* This function will return a pointer to the null terminated string
* "Hello There".
*
* ENTRY:
*
* npszData : pointer to entire section taken from setup.inf
* npszDataStr : pointer to key word to look for (welcome in example above.)
*
* EXIT: retutns pointer to string if successful, NULL if failure.
*
*/
BOOL fnGetDataString(PINF npszData, LPSTR szDataStr, LPSTR szBuf)
{
int len = lstrlen(szDataStr);
while (npszData)
{
if (!strncmpi(npszData,szDataStr,len)) // looking for correct prof.
{
npszData += len; // found !, look past prof str.
while (ISWHITE(*npszData)) // suck out the crap.
npszData++;
if (*npszData == EQUAL) // Now we have what were looking for !
{
npszData++;
if (!multifields(npszData) )
{
while (ISWHITE(*npszData) || ISNOISE(*npszData))
npszData++;
while (*npszData)
*szBuf++ = *npszData++;
/*
* remove trailing spaces, and those pesky ()'s
*/
while (ISWHITE(szBuf[-1]) || ISNOISE(szBuf[-1]))
szBuf--;
*szBuf = 0;
return TRUE;
}
else
{
while (*npszData)
*szBuf++ = *npszData++;
*szBuf = '\0';
return TRUE;
}
}
}
npszData = infNextLine(npszData);
}
*szBuf = 0;
return FALSE;
}
/* PINF FAR PASCAL infSetDefault(pinf)
*
* Sets the default INF file
*
* ENTRY:
* pinf : inf file to be new default
*
* EXIT: retutns old default
*
*/
PINF FAR PASCAL infSetDefault(PINF pinf)
{
PINF pinfT;
pinfT = pinfDefault;
pinfDefault = pinf;
return pinfT;
}
/* PINF FAR PASCAL infFindSection(pinf,szSection)
*
* Reads a entire section into memory and returns a pointer to it
*
* ENTRY:
* pinf : inf file to search for section
* szSection : section name to read
*
* EXIT: retutns pointer to section, NULL if error
*
*/
PINF FAR PASCAL infFindSection(PINF pinf, LPSTR szSection)
{
WORD pos;
if (pinf == NULL)
pinf = pinfDefault;
pos = FindSection(pinf, szSection);
return pos ? pinf + pos : NULL;
}
/* BOOL FAR PASCAL infGetProfileString(szSection,szItem,szBuf)
*
* Reads a single string from a section in SETUP.INF
*
* [section]
* item = string
*
* ENTRY:
* szSection : pointer to section name to read.
* szItem : pointer to item name to read
* szBuf : pointer to a buffer to hold result
*
* EXIT: retutns TRUE if successful, FALSE if failure.
*
*/
BOOL FAR PASCAL infGetProfileString(PINF pinf, LPSTR szSection,LPSTR szItem,LPSTR szBuf)
{
PINF pSection;
pSection = infFindSection(pinf,szSection);
if ( pSection )
return fnGetDataString(pSection,szItem,szBuf);
else
*szBuf = 0;
return FALSE;
}
/* BOOL FAR PASCAL infParseField(szData,n,szBuf)
*
* Given a line from SETUP.INF, will extract the nth field from the string
* fields are assumed separated by comma's. Leading and trailing spaces
* are removed.
*
* ENTRY:
*
* szData : pointer to line from SETUP.INF
* n : field to extract. ( 1 based )
* 0 is field before a '=' sign
* szDataStr : pointer to buffer to hold extracted field
*
* EXIT: retutns TRUE if successful, FALSE if failure.
*
*/
BOOL FAR PASCAL infParseField(PINF szData, int n, LPSTR szBuf)
{
BOOL fQuote = FALSE;
PINF pch;
LPSTR ptr;
if (!szData || !szBuf)
return FALSE;
/*
* find the first separator
*/
for (pch=szData; *pch && !ISSEP(*pch); pch++) {
if ( *pch == QUOTE )
fQuote = !fQuote;
}
if (n == 0 && *pch != '=')
return FALSE;
if (n > 0 && *pch == '=' && !fQuote)
szData = ++pch;
/*
* locate the nth comma, that is not inside of quotes
*/
fQuote = FALSE;
while (n > 1)
{
while (*szData)
{
if (!fQuote && ISSEP(*szData))
break;
if (*szData == QUOTE)
fQuote = !fQuote;
szData++;
}
if (!*szData) {
szBuf[0] = 0; // make szBuf empty
return FALSE;
}
szData++;
n--;
}
/*
* now copy the field to szBuf
*/
while (ISWHITE(*szData))
szData++;
fQuote = FALSE;
ptr = szBuf; // fill output buffer with this
while (*szData)
{
if (*szData == QUOTE)
fQuote = !fQuote;
else if (!fQuote && ISSEP(*szData))
break;
else
*ptr++ = *szData;
szData++;
}
/*
* remove trailing spaces, and those pesky ()'s
*/
while ((ptr > szBuf) && (ISWHITE(ptr[-1]) || ISNOISE(ptr[-1])))
ptr--;
*ptr = 0;
return TRUE;
}
/* BOOL multifields(LPSTR npszData);
*
* Given a line line from setup.inf that was phycisacaly after a profile
* string this function will determine if that line has more than one
* field. ie. Fields are seperated by commas that are NOT contained between
* quotes.
*
* ENYRY:
*
* npszData : a line from setup.inf Example "xyz adapter",1:foobar.drv
*
* EXIT: This function will return TRUE if the line containes more than
* one field, ie the function would return TRUE for the example line
* shown above.
*
*/
BOOL multifields(PINF npszData)
{
BOOL fQuote = FALSE;
while (*npszData)
{
if (!fQuote && ISSEP(*npszData))
return TRUE;
if (*npszData == QUOTE)
fQuote = !fQuote;
npszData++;
}
return FALSE;
}
/* LPSTR FAR PASCAL infNextLine(sz)
*
* Given a line from SETUP.INF, advance to the next line. will skip past the
* ending NULL character checking for end of buffer \0\0
*
* ENTRY:
*
* sz : pointer to line from a SETUP.INF section
*
* EXIT: retutns pointer to next line if successful, NULL if failure.
*
*/
PINF FAR PASCAL infNextLine(PINF pinf)
{
if (!pinf)
return NULL;
while (*pinf != 0 || *(pinf + 1) == ' ')
pinf++;
return *++pinf ? pinf : NULL;
}
/* int FAR PASCAL infLineCount(pinf)
*
* Given a section from SETUP.INF, returns the number of lines in the section
*
* ENTRY:
*
* pinf : pointer to a section from SETUP.INF
*
* EXIT: retutns line count
*
*/
int FAR PASCAL infLineCount(PINF pinf)
{
int n = 0;
for (n=0; pinf; pinf = infNextLine(pinf))
n++;
return n;
}
/* int FAR PASCAL infLookup(szInf,szBuf)
*
* lookup a section/key in SETUP.INF
*
* ENTRY:
*
* szInf : pointer to a string of the form section.key
* szBuf : pointer to buffer to recive string
*
* EXIT: retutns TRUE/FALSE
*
*/
BOOL FAR PASCAL infLookup(LPSTR szInf, LPSTR szBuf)
{
LPSTR pch;
BOOL f;
/*
* find the LAST .
*/
for (pch = szInf; *pch; pch++)
;
for (; pch > szInf && *pch != '.'; pch--)
;
if (*pch == '.')
{
*pch++ = 0;
f = infGetProfileString(NULL,szInf,pch,szBuf);
if (szInf != szBuf)
*pch = '.';
return f;
}
else
{
*szBuf = 0;
return FALSE;
}
}
#ifdef DOSONLY
unsigned char AnsiToOemTable[] = {
0x20, /* non breaking space (NBSP) */
0xAD, /* A1h inverted point */
0xbd, /* A2h cent --- */
0x9C, /* A3h british pound */
0xcf, /* A4h sun --- */
0xbe, /* A5h yen --- */
0xdd, /* A6h vertical bar (cut) --- */
0xf5, /* A7h section mark --- */
0xf9, /* A8h umlaut --- */
0xb8, /* A9h copyright sign --- */
0xa6, /* AAh a underlined (superscript) --- */
0xae, /* ABh << --- */
0xAA, /* ACh logical NOT */
0xf0, /* ADh syllabic hyphenation (SHY) --- */
0xa9, /* AEh registered mark */
0xee, /* AFh top bar --- */
0xF8, /* B0h degree */
0xF1, /* B1h + underlined (plus or minus) */
0xFD, /* B2h 2 (superscript) */
0xfc, /* B3h 3 (superscript) --- */
0xef, /* B4h acute --- */
0xE6, /* B5h greek mu */
0xf4, /* B6h paragraph sign --- */
0xFA, /* B7h middle dot */
0xf7, /* B8h cedilla for deadkey --- */
0xfb, /* B9h 1 (superscript) --- */
0xa7, /* BAh o underlined (superscript) --- */
0xaf, /* BBh >> --- */
0xac, /* BCh 1/4 --- */
0xab, /* BDh 1/2 --- */
0xf3, /* BEh 3/4 --- */
0xA8, /* BFh inverted question mark */
0xb7, /* C0h A grave uppercase -- */
0xb5, /* C1h A acute uc -- */
0xb6, /* C2h A circumflex uc -- */
0xc7, /* C3h A tilde uc --- */
0x8E, /* C4h A umlaut uc */
0x8F, /* C5h A ring uc */
0x92, /* C6h AE uc */
0x80, /* C7h C cedilla uc */
0xd4, /* C8h E grave uc --- */
0x90, /* C9h E acute uc */
0xd2, /* CAh E circumflex uc --- */
0xd3, /* CBh E umlaut uc --- */
0xde, /* CCh I grave uc --- */
0xd6, /* CDh I acute uc --- */
0xd7, /* CEh I circumflex uc --- */
0xd8, /* CFh I umlaut uc --- */
0xd1, /* D0h Icelandic eth (D striked) uc --- */
0xA5, /* D1h N tilde uc */
0xe3, /* D2h O grave uc --- */
0xe0, /* D3h O acute uc --- */
0xe2, /* D4h O circumflex uc --- */
0xe5, /* D5h O tilde uc --- */
0x99, /* D6h O umlaut uc */
0x9e, /* D7h Multiply sign --- */
0x9D, /* D8h O slashed uc --- */
0xeb, /* D9h U grave uc --- */
0xe9, /* DAh U acute uc --- */
0xea, /* DBh U circumflex uc --- */
0x9A, /* DCh U umlaut uc */
0xed, /* DDh Y acute uc --- */
0xe8, /* DEH Icelandic thorn uc --- */
0xE1, /* DFh german sharp S */
0x85, /* E0h a grave lowercase */
0xA0, /* E1h a acute lc */
0x83, /* E2h a circumflex lc */
0xc6, /* E3h a tilde lc --- */
0x84, /* E4h a umlaut lc */
0x86, /* E5h a ring lc */
0x91, /* E6h ae lc */
0x87, /* E7h c cedilla lc */
0x8A, /* E8h e grave lc */
0x82, /* E9h e acute lc */
0x88, /* EAh e circumflex lc */
0x89, /* EBh e umlaut lc */
0x8D, /* ECh i grave lc */
0xA1, /* EDh i acute lc */
0x8C, /* EEh i circumflex lc */
0x8B, /* EFh i umlaut lc */
0xd0, /* F0h Icelandic eth (d striked) lc --- */
0xA4, /* F1h n tilde lc */
0x95, /* F2h o grave lc */
0xA2, /* F3h o acute lc */
0x93, /* F4h o circumflex lc */
0xe4, /* F5h o tilde lc --- */
0x94, /* F6h o umlaut lc */
0xf6, /* F7h divide sign --- */
0x9B, /* F8h o slashed lc --- */
0x97, /* F9h u grave lc */
0xA3, /* FAh u acute lc */
0x96, /* FBh u circumflex lc */
0x81, /* FCh u umlaut lc */
0xec, /* FDh y acute lc */
0xe7, /* FEH icelandic thorn lc */
0x98 /* FFh y umlaut lc */
}; /* end of AnsiToOemTable */
unsigned char XlateAnsi850(unsigned char c)
{
if (c >= 160)
c = AnsiToOemTable[c - 160];
return c;
}
#endif