windows-nt/Source/XPSP1/NT/sdktools/restools/rltools/common/tokenapi.c

534 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include <ctype.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#ifdef RLDOS
#include "dosdefs.h"
#else
#include <windows.h>
#include "windefs.h"
#endif
#include "restok.h"
#include "commbase.h"
#include "resread.h"
extern UCHAR szDHW[];
//
// The syssetup.dll, that has been contained Windows NT 4.00, has the largest
// message strings than ever. So, we have to expand buffer size(to 20480).
//
#define MAX_OUT_BUFFER 20480
CHAR gt_szTextBuffer[ MAX_OUT_BUFFER];
TCHAR pt_szOutBuffer[MAX_OUT_BUFFER];
/**
*
*
* Function:
*
*
* Arguments:
*
* Returns:
*
* Errors Codes:
*
* History:
*
*
**/
/*---------------------------------------------------------
* Function: GetToken
* Input: fpInFile File pointer, points to the token to be read.
* tToken Pointer to a token.
*
*
* Output: fpInFile File pointer after read operation.
* points to the next token in the file.
* tToken The token read in from the file. Memory will have been
* allocated for the token text, unless no token was read in.
*
* Return code:
* 0 = Read token, every thing OK
* 1 = Empty line or line started with # (Comment)
* -1 = End of FILE
* -2 = Error reading from file.
*
* History:
* 01/93 Re-written to read in long token text strings. MHotchin
*
*----------------------------------------------------------*/
int GetToken(
FILE *fpInFile, //... File to get token from.
TOKEN *pToken) //... Buffer for token.
{
int chNextChar = 0;
int cTextLen = 0;
int rc = 0;
// Read token from file.
// we will want to use MyGetStr, when
// tokens are in UNICODE
// Strip off leading whitespace, and check
// for blank lines.
chNextChar = fgetc( fpInFile);
while ( (chNextChar == ' ') || (chNextChar == '\t') ) {
chNextChar = fgetc( fpInFile);
}
if ( chNextChar == EOF ) {
return ( -1);
} else if ( chNextChar == '\n' ) {
return ( 1);
}
// Now we have the first non-white space
// character.
// Check for a comment line, and strip out the
// remainder of the line if it is.
else if ( chNextChar == '#' ) {
fscanf( fpInFile, "%*[^\n]");
chNextChar = fgetc( fpInFile);
if ( chNextChar == EOF ) {
return ( -1);
} else {
return ( 1);
}
}
// Now we are positioned at the first
// non-whitespace character. Check it, and
// read in the numbers...
else if ( chNextChar != '[' ) {
// Bad format?
return ( -2);
}
if ( fscanf( fpInFile,
"[%hu|%hu|%hu|%hu|%hu",
&pToken->wType,
&pToken->wName,
&pToken->wID,
&pToken->wFlag,
&pToken->wReserved) != 5 ) {
QuitA( IDS_ENGERR_12, (LPSTR)IDS_BADTOKID, NULL);
}
// Now that we have all the numbers, we can
// look for the name of the token.
if ( (pToken->wName == IDFLAG) || (pToken->wType == ID_RT_ERRTABLE) ) {
static char szName[ TOKENSTRINGBUFFER];
int nRC = 0;
nRC = fscanf( fpInFile, "|\"%[^\"]", szName);
if ( nRC == EOF ) {
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_INVTOKNAME, NULL);
}
#ifndef UNITOK
#ifdef RLRES32
if (nRC)
_MBSTOWCS( (TCHAR *)pToken->szName,
szName,
TOKENSTRINGBUFFER,
lstrlenA( szName) + 1);
else
_MBSTOWCS( (TCHAR *)pToken->szName,
"",
TOKENSTRINGBUFFER,
lstrlenA( szName) + 1);
#else
if (nRC)
strcpy( pToken->szName, szName);
else
*pToken->szName = '\0';
#endif
#else
if (nRC)
strcpy( pToken->szName, szName);
else
*pToken->szName = '\0';
#endif
} else {
if ( fscanf( fpInFile, "|\"%*[^\"]") != 0 ) {
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_NOSKIPNAME, NULL);
}
pToken->szName[0] = '\0';
}
// Now the name has been read, and we are
// positioned at the last '"' in the text
// stream. Allocate memory for the token
// text, and read it in.
fgets( gt_szTextBuffer, sizeof(gt_szTextBuffer), fpInFile);
// Now that the token text is read in,
// convert it to whatever character type
// we are expecting. First strip the newline!
StripNewLineA( gt_szTextBuffer);
cTextLen = lstrlenA( gt_szTextBuffer);
if ( cTextLen < 4 ) { // Must be more than "\"]]=" in szTextBuffer
return ( -2);
}
pToken->szText = (TCHAR *)FALLOC( MEMSIZE( cTextLen - 3));
#ifndef UNITOK
#ifdef RLRES32
_MBSTOWCS( pToken->szText, gt_szTextBuffer+4, cTextLen - 3, cTextLen - 3);
#else
strcpy( pToken->szText, gt_szTextBuffer+4);
#endif // RLRES32
#else // UNITOK
strcpy( pToken->szText, gt_szTextBuffer+4);
#endif // UNITOK
return ( 0);
}
/**
*
*
* Function:
*
*
* Arguments:
*
* Returns:
*
* Errors Codes:
*
* History:
* 01/93 Added new character count field. MHotchin
*
**/
int PutToken(
FILE *fpOutFile, //... Token file to write to
TOKEN *tToken) //... Token to be writen to the token file
{
WORD rc = 0;
PCHAR pszBuf = NULL;
ParseTokToBuf( pt_szOutBuffer, tToken);
// RLFREE( tToken->szText);
#ifdef RLRES32
if ( ! _WCSTOMBS( szDHW, pt_szOutBuffer, DHWSIZE, lstrlen( pt_szOutBuffer) + 1) ) {
QuitT( IDS_ENGERR_26, pt_szOutBuffer, NULL);
}
pszBuf = szDHW;
#else
pszBuf = pt_szOutBuffer;
#endif
return fprintf( fpOutFile, "%s\n", pszBuf);
}
/**
* Function: FindToken
* Finds a token whose status bits match only where the mask is set.
*
* Arguments:
* fpSearchFile -- search file
* psTok -- pointer to the token
* uMask -- status bit mask
*
* Returns:
* string and status of found token
*
* Errors Codes:
* 0 - token not found
* 1 - token found
*
* History:
* 01/93 Added support for var length token text strings. Previous token text
* is de-allocated! MHotchin
*
**/
int FindToken( FILE *fpSearchFile, TOKEN *psTok, WORD wMask)
{
BOOL fFound = FALSE;
BOOL fStartOver = TRUE;
int error;
int nTokensRead = 0;
long lStartFilePos, lFilePos;
TOKEN cTok;
//... Remember where we are starting
lFilePos = lStartFilePos = ftell(fpSearchFile);
do {
long lType11Pos = 0;
do {
lType11Pos = ftell( fpSearchFile);
error = GetToken( fpSearchFile, &cTok);
if ( error == 0 ) {
//... Is this the token we are looking for?
fFound = ((cTok.wType == psTok->wType)
&& (cTok.wName == psTok->wName)
&& (cTok.wID == psTok->wID)
&& (cTok.wFlag == psTok->wFlag)
&& ((WORD)(cTok.wReserved & wMask) == psTok->wReserved)
&& (_tcscmp( (TCHAR *)cTok.szName,
(TCHAR *)psTok->szName) == 0));
}
if ( ! fFound ) {
//... If we were looking for another segment to
//... an NT Msg Table entry, move back to the
//... token we just read and quit (speedup).
if ( psTok->wType == ID_RT_ERRTABLE
&& psTok->wFlag > 0
&& error == 0 ) {
if ( cTok.wType != psTok->wType
|| cTok.wName != psTok->wName
|| cTok.wID != psTok->wID
|| cTok.wFlag > psTok->wFlag ) {
fseek( fpSearchFile, lType11Pos, SEEK_SET);
RLFREE( cTok.szText);
return ( FALSE);
}
} else if ( error >= 0 ) {
lFilePos = ftell(fpSearchFile);
if (error == 0) {
RLFREE(cTok.szText);
}
} else if (error == -2) {
return ( FALSE);
}
}
} while ( ! fFound
&& (error >= 0)
&& (fStartOver || (lFilePos < lStartFilePos)) );
if ( ! fFound && (error == -1) && fStartOver ) {
rewind(fpSearchFile);
lFilePos = 0L;
fStartOver = FALSE;
}
} while ( ! fFound && (lFilePos < lStartFilePos) );
//... Did we find the desired token?
if ( fFound ) { //... Yes, we found it
psTok->wReserved = cTok.wReserved;
RLFREE( psTok->szText);
psTok->szText = cTok.szText;
}
return ( fFound);
}
/**
*
*
* Function:
*
*
* Arguments:
*
* Returns:
*
* Errors Codes:
*
* History:
* 01/93 Added support for new token text count. MHotchin
*
**/
void ParseBufToTok( TCHAR *szToken, TOKEN *pTok )
{
TCHAR *pos;
WORD bChars;
if ( _stscanf( szToken,
TEXT("[[%hu|%hu|%hu|%hu|%hu"),
&pTok->wType,
&pTok->wName,
&pTok->wID,
&pTok->wFlag,
&pTok->wReserved) != 5 ) {
QuitT( IDS_BADTOK, szToken, NULL);
}
if ( pTok->wName == IDFLAG || pTok->wType == ID_RT_ERRTABLE ) {
//... Find Names's first char and get it's len
if ( pos = _tcschr( (TCHAR *)szToken, TEXT('"')) ) {
TCHAR *pStart;
pStart = ++pos;
bChars = 0;
while ( *pos && *pos != TEXT('"')
&& bChars < TOKENSTRINGBUFFER - 1 ) {
bChars++;
pos++;
} // while
CopyMemory( pTok->szName, pStart, min( TOKENSTRINGBUFFER, bChars) * sizeof( TCHAR));
pTok->szName[ bChars ] = TEXT('\0');
} else {
//... No token ID found
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_INVTOKNAME, NULL);
}
} else {
// Don't forget the zero termination
pTok->szName[0] = TEXT('\0');
}
// now do the token text
pos = _tcschr ((TCHAR *)szToken, TEXT(']'));
if ( pos ) {
// This can be written better now that we know the text length.
bChars = (WORD)lstrlen( pos);
if ( bChars > 3 ) {
pos += 3;
bChars -= 3;
pTok->szText = (TCHAR *)FALLOC( MEMSIZE( bChars + 1));
CopyMemory( pTok->szText, pos, MEMSIZE( bChars + 1));
// Don't forget the zero termination
pTok->szText[ bChars] = TEXT('\0');
} else if ( bChars == 3 ) {
//... Empty token text
pTok->szText = (TCHAR *) FALLOC( 0);
} else {
//... No token ID found
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_INVTOKID, NULL);
}
} else {
//... No token ID found
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_NOTOKID, NULL);
}
}
/**
*
*
* Function:
*
*
* Arguments:
*
* Returns:
*
* Errors Codes:
*
* History:
*
**/
void ParseTokToBuf( TCHAR *szToken, TOKEN *pTok )
{
*szToken = TEXT('\0');
if ( pTok != NULL) {
wsprintf( szToken,
TEXT("[[%hu|%hu|%hu|%hu|%hu|\"%s\"]]="),
pTok->wType,
pTok->wName,
pTok->wID,
pTok->wFlag,
pTok->wReserved,
pTok->szName);
if (pTok->szText)
lstrcat(szToken, pTok->szText);
}
}
/**
*
*
* Function: TokenToTextSize
* This calculates the number of characters needed to hold
* the text representation of a token.
*
* Arguments:
* pTok The token to measure.
*
* Returns:
* int The number of characters needed to hold the token, not
* including a null terminator. [[%hu|%hu|%hu|%hu|%hu|\"%s\"]]=%s
*
* Errors Codes:
* None.
*
* History:
* 01/18/93 MHotchin Created.
*
**/
int TokenToTextSize( TOKEN *pTok)
{
int cTextLen;
cTextLen = (14 + // Separators and terminator ( + 1 extra)
30); // Space for 5 numeric fields (65,535 = 6 chars)
if ( pTok->szText != NULL ) {
// Add space for the Token text
cTextLen += MEMSIZE( lstrlen( pTok->szText) );
}
cTextLen += lstrlen( pTok->szName);
return ( cTextLen);
}