721 lines
26 KiB
C
721 lines
26 KiB
C
|
//.....................................................................
|
||
|
//...
|
||
|
//... NTMSGTBL.C
|
||
|
//...
|
||
|
//... Contains functions for handling strings found in NT's Message
|
||
|
//... Resource Tables. This recource type is not present in Win 3.1.
|
||
|
//...
|
||
|
//... Author - David Wilcox (davewi@microsoft)
|
||
|
//...
|
||
|
//... NOTES: Created with tabstop set to 8
|
||
|
//...
|
||
|
//.....................................................................
|
||
|
//...
|
||
|
//... History:
|
||
|
//... Original - 10/92
|
||
|
//... 11/92 - Fixed to handle ULONG msg ID#'s - davewi
|
||
|
//...
|
||
|
//.....................................................................
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <windef.h>
|
||
|
#include <tchar.h>
|
||
|
#include <winver.h>
|
||
|
|
||
|
#include "windefs.h"
|
||
|
#include "restok.h"
|
||
|
#include "custres.h"
|
||
|
#include "ntmsgtbl.h"
|
||
|
#include "resread.h"
|
||
|
|
||
|
|
||
|
typedef PMESSAGE_RESOURCE_ENTRY PMRE;
|
||
|
|
||
|
extern BOOL gbMaster;
|
||
|
extern UCHAR szDHW[];
|
||
|
|
||
|
static PBYTE *pBlockEntries = NULL;
|
||
|
|
||
|
VOID *pResMsgData = NULL; // NT-specific Message Table resource
|
||
|
|
||
|
|
||
|
//.........................................................................
|
||
|
//...
|
||
|
//... Get Message Table from .res file
|
||
|
//...
|
||
|
//... This form of a message table, not found in Win 16, allows very long
|
||
|
//... strings and the text is stored as an ASCIIZ string in the .res file.
|
||
|
|
||
|
|
||
|
VOID *GetResMessage(
|
||
|
|
||
|
FILE *pInResFile, //... The file containing the resources
|
||
|
DWORD *plSize) //... The size of this resource from GetResHeader
|
||
|
{
|
||
|
ULONG ulNumBlocks = 0L; //... # of Message Table resource blocks
|
||
|
ULONG ulStartMsgDataPos = 0L; //... Start of message data in file
|
||
|
ULONG ulBlock; //... Current message block number
|
||
|
USHORT usCurrBlockSize = 0; //... Current size of temp block buffer
|
||
|
USHORT usDeltaBlockSize = 4096; //... Amount to increase usCurrBlockSize
|
||
|
DWORD dwNumMsgs = 0; //... Count of msgs in the resource
|
||
|
PBYTE pMsgBlock = NULL; //... Temp message block buffer
|
||
|
|
||
|
PMESSAGE_RESOURCE_DATA pMsgResData;//... Returned as ptr to the resource
|
||
|
PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a block of messages
|
||
|
|
||
|
|
||
|
|
||
|
//... The resource header was read prior to
|
||
|
//... entring this function, so the current
|
||
|
//... file position should now be the start
|
||
|
//... of the resource data.
|
||
|
|
||
|
ulStartMsgDataPos = ftell( pInResFile);
|
||
|
|
||
|
//... Get the number of message blocks and
|
||
|
//... allocate enough memory for the array.
|
||
|
|
||
|
ulNumBlocks = GetdWord( pInResFile, plSize);
|
||
|
|
||
|
//... Allocate space for the array of
|
||
|
//... pointers to entries. This array is used
|
||
|
//... to store pointers to the first entry
|
||
|
//... in each block of message entries.
|
||
|
|
||
|
pBlockEntries = (PBYTE *)FALLOC( ulNumBlocks * sizeof( PBYTE));
|
||
|
|
||
|
if ( ! pBlockEntries )
|
||
|
{
|
||
|
QuitT( IDS_ENGERR_11, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
pMsgResData = (PMESSAGE_RESOURCE_DATA)FALLOC( sizeof( ULONG) + ulNumBlocks
|
||
|
* sizeof( MESSAGE_RESOURCE_BLOCK));
|
||
|
|
||
|
if ( ! pMsgResData )
|
||
|
{
|
||
|
QuitT( IDS_ENGERR_11, NULL, NULL);
|
||
|
}
|
||
|
pResMsgData = pMsgResData;
|
||
|
pMsgResData->NumberOfBlocks = ulNumBlocks;
|
||
|
|
||
|
//... Read the array of message block structs,
|
||
|
//... and initialize block entry pointer array.
|
||
|
|
||
|
for ( ulBlock = 0L, pMRB = pMsgResData->Blocks;
|
||
|
ulBlock < ulNumBlocks;
|
||
|
++ulBlock, ++pMRB )
|
||
|
{
|
||
|
pMRB->LowId = GetdWord( pInResFile, plSize);
|
||
|
pMRB->HighId = GetdWord( pInResFile, plSize);
|
||
|
pMRB->OffsetToEntries = GetdWord( pInResFile, plSize);
|
||
|
|
||
|
if ( pMRB->HighId < pMRB->LowId )
|
||
|
{
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_16, (LPTSTR)IDS_INVMSGRNG, NULL);
|
||
|
}
|
||
|
dwNumMsgs += (pMRB->HighId - pMRB->LowId + 1);
|
||
|
|
||
|
pBlockEntries[ ulBlock] = NULL;
|
||
|
}
|
||
|
|
||
|
//... Read in the MESSAGE_RESOURCE_ENTRY
|
||
|
|
||
|
usCurrBlockSize = usDeltaBlockSize;
|
||
|
|
||
|
for ( ulBlock = 0L, pMRB = pMsgResData->Blocks;
|
||
|
ulBlock < ulNumBlocks;
|
||
|
++ulBlock, ++pMRB )
|
||
|
{
|
||
|
ULONG ulCurrID; //... Current message ID # in this block
|
||
|
ULONG ulEndID; //... Last message ID # in this block + 1
|
||
|
USHORT usLen; //... For length of a message - MUST BE USHORT
|
||
|
USHORT usMsgBlkLen; //... Length of a block of messages
|
||
|
|
||
|
|
||
|
usMsgBlkLen = 0;
|
||
|
|
||
|
//... Move to start of block of message entries
|
||
|
//... then read all the messages in this block.
|
||
|
|
||
|
fseek( pInResFile,
|
||
|
ulStartMsgDataPos + pMRB->OffsetToEntries,
|
||
|
SEEK_SET);
|
||
|
|
||
|
for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
|
||
|
ulCurrID < ulEndID;
|
||
|
++ulCurrID, --dwNumMsgs )
|
||
|
{
|
||
|
//... Get Msg Resource entry length
|
||
|
//... (Length is in bytes and includes
|
||
|
//... .Length and .Flags fields and any
|
||
|
//... padding that may exist after the text.)
|
||
|
|
||
|
usLen = GetWord( pInResFile, plSize);
|
||
|
|
||
|
if ( usLen >= 2 * sizeof( USHORT) )
|
||
|
{
|
||
|
PMRE pMRE;
|
||
|
PUCHAR puchText;
|
||
|
|
||
|
//... Create, or expand size of, pMsgBlkData
|
||
|
//... so we can append this entry.
|
||
|
//... Always resave ptr to the message block
|
||
|
//... (it may have moved).
|
||
|
|
||
|
if ( pMsgBlock )
|
||
|
{
|
||
|
if ( (USHORT)(usMsgBlkLen + usLen) > usCurrBlockSize )
|
||
|
{
|
||
|
usCurrBlockSize += __max(usDeltaBlockSize, (USHORT)(usMsgBlkLen + usLen));
|
||
|
pMsgBlock = (PBYTE)FREALLOC( pMsgBlock,
|
||
|
usCurrBlockSize);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pMsgBlock = FALLOC( usCurrBlockSize);
|
||
|
}
|
||
|
|
||
|
//... If the malloc worked, read this msg entry.
|
||
|
//... The section assumes there is one WORD
|
||
|
//... per USHORT and one WORD per WCHAR.
|
||
|
|
||
|
pMRE = (PMRE)(pMsgBlock + usMsgBlkLen);
|
||
|
|
||
|
//... Store the .Length field value (USHORT)
|
||
|
|
||
|
pMRE->Length = usLen;
|
||
|
usMsgBlkLen += usLen;
|
||
|
|
||
|
//... Get the .Flags field value (USHORT)
|
||
|
|
||
|
pMRE->Flags = GetWord( pInResFile, plSize);
|
||
|
|
||
|
//... Check to make sure this message is stored
|
||
|
//... either in ASCII in the current code page
|
||
|
//... or in Unicode, else fail.
|
||
|
|
||
|
if ( pMRE->Flags != 0 //... ASCII
|
||
|
&& pMRE->Flags != MESSAGE_RESOURCE_UNICODE ) //... Unicode
|
||
|
{
|
||
|
if ( pMsgBlock != NULL )
|
||
|
{
|
||
|
RLFREE( pMsgBlock);
|
||
|
}
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitA( IDS_NON0FLAG, NULL, NULL);
|
||
|
}
|
||
|
|
||
|
//... Get the .Text field string
|
||
|
|
||
|
usLen -= (2 * sizeof( WORD));
|
||
|
|
||
|
for ( puchText = (PUCHAR)pMRE->Text; usLen; ++puchText, --usLen )
|
||
|
{
|
||
|
*puchText = (UCHAR)GetByte( pInResFile, plSize);
|
||
|
}
|
||
|
DWordUpFilePointer( pInResFile,
|
||
|
MYREAD,
|
||
|
ftell( pInResFile),
|
||
|
plSize);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( pMsgBlock != NULL )
|
||
|
{
|
||
|
RLFREE( pMsgBlock);
|
||
|
}
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_INVMSGTBL, NULL);
|
||
|
}
|
||
|
} //... END FOR(each message entry in this block)
|
||
|
|
||
|
if ( pMsgBlock != NULL && usMsgBlkLen > 0 )
|
||
|
{
|
||
|
pBlockEntries[ ulBlock] = FALLOC( usMsgBlkLen);
|
||
|
|
||
|
memcpy( pBlockEntries[ ulBlock], pMsgBlock, usMsgBlkLen);
|
||
|
}
|
||
|
} //... END FOR(each message block)
|
||
|
|
||
|
if ( pMsgBlock != NULL )
|
||
|
{
|
||
|
RLFREE( pMsgBlock);
|
||
|
}
|
||
|
|
||
|
DWordUpFilePointer( pInResFile, MYREAD, ftell( pInResFile), plSize);
|
||
|
|
||
|
return( (VOID *)pMsgResData);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//.........................................................................
|
||
|
//...
|
||
|
//... Put localized Message Table into .res
|
||
|
//...
|
||
|
//... 01/93 - changes for var length Token text. MHotchin
|
||
|
//... 02/93 - stripped out code that split msgs into multiple tokens. davewi
|
||
|
|
||
|
void PutResMessage(
|
||
|
|
||
|
FILE *fpOutResFile, //... File to which localized resources are written
|
||
|
FILE *fpInTokFile, //... Output token file
|
||
|
RESHEADER ResHeader, //... Resource header data
|
||
|
VOID *pMsgResData) //... message table data built in GetResMessage
|
||
|
{
|
||
|
WORD wcCount = 0;
|
||
|
fpos_t ulResSizePos = 0L; //... File position for fixed up resource size
|
||
|
fpos_t ulBlocksStartPos=0L; //... File position of start of message blocks
|
||
|
ULONG ulNumBlocks = 0L; //... Number of Message Blocks
|
||
|
ULONG ulCurrOffset = 0L; //... Offset to current msg block
|
||
|
ULONG ulResSize = 0L; //... Size of this resource
|
||
|
ULONG ulBlock; //... Temporary counter
|
||
|
USHORT usEntryLen = 0; //... Length of current message entry
|
||
|
PMESSAGE_RESOURCE_DATA pData; //. Message table data from InResFile
|
||
|
static TOKEN Tok; //... Token from localized token file
|
||
|
|
||
|
|
||
|
if ( pMsgResData == NULL)
|
||
|
{
|
||
|
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_NULMSGDATA, NULL);
|
||
|
}
|
||
|
memset( (void *)&Tok, 0, sizeof( Tok));
|
||
|
pData = (PMESSAGE_RESOURCE_DATA)pMsgResData;
|
||
|
|
||
|
if ( PutResHeader( fpOutResFile, ResHeader, &ulResSizePos, &ulResSize))
|
||
|
{
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MSGTBLHDR, NULL);
|
||
|
}
|
||
|
|
||
|
ulResSize = 0L; //... Reset to zero (hdr len not to be included)
|
||
|
|
||
|
ulNumBlocks = pData->NumberOfBlocks;
|
||
|
|
||
|
//... Write number of msg blocks
|
||
|
|
||
|
PutdWord( fpOutResFile, ulNumBlocks, &ulResSize);
|
||
|
|
||
|
//... Remember this file position so we can
|
||
|
//... come back here and update the
|
||
|
//... OffsetToEntries field in each struct.
|
||
|
|
||
|
ulBlocksStartPos = ftell( fpOutResFile);
|
||
|
|
||
|
//... Write the array of message block structs
|
||
|
|
||
|
for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
|
||
|
{
|
||
|
PutdWord( fpOutResFile, pData->Blocks[ ulBlock].LowId, &ulResSize);
|
||
|
PutdWord( fpOutResFile, pData->Blocks[ ulBlock].HighId, &ulResSize);
|
||
|
PutdWord( fpOutResFile, 0L, &ulResSize); //... Will get fixed up later
|
||
|
}
|
||
|
// Prep for find token call
|
||
|
|
||
|
Tok.wType = ResHeader.wTypeID;
|
||
|
Tok.wName = ResHeader.wNameID;
|
||
|
Tok.wID = 0;
|
||
|
Tok.wFlag = 0;
|
||
|
|
||
|
if ( ResHeader.bNameFlag == IDFLAG )
|
||
|
{
|
||
|
lstrcpy( Tok.szName, ResHeader.pszName);
|
||
|
}
|
||
|
//... Write the MESSAGE_RESOURCE_ENTRY's. First
|
||
|
//... note offset from start of this resource's
|
||
|
//... data to first msg res entry struct which
|
||
|
//... starts right after the array of
|
||
|
//... RESOURCE_MESSAGE_BLOCK structs.
|
||
|
|
||
|
ulCurrOffset = sizeof( ULONG) + ulNumBlocks*sizeof( MESSAGE_RESOURCE_BLOCK);
|
||
|
|
||
|
for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
|
||
|
{
|
||
|
ULONG ulCurrID; //... Current message ID # in this block
|
||
|
ULONG ulEndID; //... Last message ID # in this block + 1
|
||
|
fpos_t ulEntryPos; //... Start of the current msg entry struct
|
||
|
PBYTE pMRE; //... Ptr to a MESSAGE_RESOURCE_ENTRY
|
||
|
PMESSAGE_RESOURCE_BLOCK pMRB;
|
||
|
|
||
|
|
||
|
//... Retrieve ptr to block of messages. The
|
||
|
//... ptr was stored in the pBlockEntries array
|
||
|
//... in GetResMessage function above.
|
||
|
|
||
|
pMRB = (PMESSAGE_RESOURCE_BLOCK)( &pData->Blocks[ ulBlock]);
|
||
|
pMRE = pBlockEntries[ ulBlock];
|
||
|
|
||
|
//... Note offset to start of block's entries
|
||
|
|
||
|
pData->Blocks[ ulBlock].OffsetToEntries = ulCurrOffset;
|
||
|
|
||
|
for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
|
||
|
ulCurrID < ulEndID;
|
||
|
++ulCurrID )
|
||
|
{
|
||
|
static UCHAR szString[ 64] = "";
|
||
|
static TCHAR szwTmp[ 4096] = TEXT("");
|
||
|
USHORT usCnt = 0;
|
||
|
BOOL fFound = FALSE;
|
||
|
ULONG ulEntrySize = 0;
|
||
|
|
||
|
|
||
|
ulEntryPos = ftell( fpOutResFile);
|
||
|
ulEntrySize = 0L;
|
||
|
|
||
|
//... Write dummy entry length.
|
||
|
//... Value gets corrected later.
|
||
|
//... Write the .Flags field's value (USHORT).
|
||
|
|
||
|
PutWord( fpOutResFile, ((PMRE)pMRE)->Length, &ulEntrySize);
|
||
|
PutWord( fpOutResFile, ((PMRE)pMRE)->Flags, &ulEntrySize);
|
||
|
|
||
|
//... Get localized token then the length of
|
||
|
//... that token's new text. Add to that length
|
||
|
//... the length of the two USHORTs and use this
|
||
|
//... combined length as the value to store in
|
||
|
//... the msg res entry's .Length field.
|
||
|
|
||
|
//... Put low word of ID# in .wID and
|
||
|
//... the high word in .szName
|
||
|
|
||
|
Tok.wID = LOWORD( ulCurrID);
|
||
|
_itoa( HIWORD( ulCurrID), szString, 10);
|
||
|
_MBSTOWCS( Tok.szName,
|
||
|
szString,
|
||
|
TOKENSTRINGBUFFER,
|
||
|
lstrlenA( szString) + 1);
|
||
|
|
||
|
//... Always reset .wReserved because the code
|
||
|
//... in FindTokenText will change its value.
|
||
|
|
||
|
Tok.wReserved = ST_TRANSLATED;
|
||
|
|
||
|
Tok.szText = NULL;
|
||
|
*szwTmp = TEXT('\0');
|
||
|
|
||
|
for ( fFound = FALSE, Tok.wFlag = 0;
|
||
|
fFound = FindToken( fpInTokFile, &Tok, ST_TRANSLATED);
|
||
|
Tok.wFlag++ )
|
||
|
{
|
||
|
TextToBin( szwTmp, Tok.szText, lstrlen( Tok.szText) + 1);
|
||
|
|
||
|
//... Write out localized message text. It may
|
||
|
//... be stored as ASCII or Unicode string.
|
||
|
|
||
|
if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
|
||
|
{
|
||
|
_WCSTOMBS( szDHW,
|
||
|
szwTmp,
|
||
|
DHWSIZE,
|
||
|
lstrlen( szwTmp) + 1);
|
||
|
|
||
|
for ( usCnt = 0; szDHW[ usCnt]; ++usCnt )
|
||
|
{
|
||
|
PutByte( fpOutResFile, szDHW[ usCnt], &ulEntrySize);
|
||
|
}
|
||
|
}
|
||
|
else //... Unicode message
|
||
|
{
|
||
|
for ( usCnt = 0; szwTmp[ usCnt]; ++usCnt )
|
||
|
{
|
||
|
PutWord( fpOutResFile, szwTmp[ usCnt], &ulEntrySize);
|
||
|
}
|
||
|
}
|
||
|
*szwTmp = TEXT('\0');
|
||
|
RLFREE( Tok.szText);
|
||
|
|
||
|
//... Always reset .wReserved because the code
|
||
|
//... in FindTokenText will change its value.
|
||
|
|
||
|
Tok.wReserved = ST_TRANSLATED;
|
||
|
}
|
||
|
|
||
|
//... Did we find the token?
|
||
|
|
||
|
if ( Tok.wFlag == 0 && ! fFound )
|
||
|
{
|
||
|
static TCHAR szToken[ 4160];
|
||
|
|
||
|
|
||
|
ParseTokToBuf( szToken, &Tok);
|
||
|
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_05, szToken, NULL);
|
||
|
}
|
||
|
//... nul-terminate the text
|
||
|
|
||
|
if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
|
||
|
{
|
||
|
PutByte( fpOutResFile , '\0', (DWORD *)&ulEntrySize);
|
||
|
}
|
||
|
else //... Unicode message
|
||
|
{
|
||
|
PutWord( fpOutResFile , TEXT('\0'), (DWORD *)&ulEntrySize);
|
||
|
}
|
||
|
DWordUpFilePointer( fpOutResFile,
|
||
|
MYWRITE,
|
||
|
ftell( fpOutResFile),
|
||
|
&ulEntrySize);
|
||
|
|
||
|
//... Also, use this length in later updating
|
||
|
//... next msg block's OffsetToEntries value.
|
||
|
|
||
|
ulResSize += ulEntrySize;
|
||
|
ulCurrOffset += ulEntrySize;
|
||
|
|
||
|
//... Write Msg Resource entry length
|
||
|
//... (Length is in bytes and includes
|
||
|
//... .Length and .Flags fields and any
|
||
|
//... padding needed after the text.)
|
||
|
//...
|
||
|
//... NOTE: Msg text is currently stored as
|
||
|
//... an ASCIIZ string.
|
||
|
fseek( fpOutResFile, (long)ulEntryPos, SEEK_SET);
|
||
|
|
||
|
PutWord( fpOutResFile, (WORD)ulEntrySize, NULL);
|
||
|
|
||
|
fseek( fpOutResFile, 0L, SEEK_END);
|
||
|
|
||
|
//... Move pMRE to point to start of next
|
||
|
//... Message Resource Entry in memory.
|
||
|
|
||
|
pMRE += ((PMRE)pMRE)->Length;
|
||
|
|
||
|
} //... END FOR(each message entry in this block)
|
||
|
|
||
|
ulCurrOffset = DWORDUP( ulCurrOffset);
|
||
|
DWordUpFilePointer( fpOutResFile,
|
||
|
MYWRITE,
|
||
|
ftell( fpOutResFile),
|
||
|
&ulResSize);
|
||
|
|
||
|
} //... END FOR(each message block)
|
||
|
|
||
|
//... Update resource size field in res header
|
||
|
|
||
|
if ( UpdateResSize( fpOutResFile, &ulResSizePos, ulResSize) == 0L )
|
||
|
{
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MSGRESTBL, NULL);
|
||
|
}
|
||
|
//... Now, update the OffsetToEntries fields.
|
||
|
|
||
|
fseek( fpOutResFile, (long)ulBlocksStartPos, SEEK_SET);
|
||
|
|
||
|
for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
|
||
|
{
|
||
|
PutdWord( fpOutResFile, pData->Blocks[ulBlock].LowId, NULL);
|
||
|
PutdWord( fpOutResFile, pData->Blocks[ulBlock].HighId, NULL);
|
||
|
PutdWord( fpOutResFile, pData->Blocks[ulBlock].OffsetToEntries, NULL);
|
||
|
}
|
||
|
fseek( fpOutResFile, 0L, SEEK_END);
|
||
|
|
||
|
} //... END PutResMessage()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//.........................................................................
|
||
|
//...
|
||
|
//... Write Message Table to the token file
|
||
|
//...
|
||
|
//... This function assumes that, in each message block, the message ID's are
|
||
|
//... contiguouse within the range given in the fields LowId and HighId in a
|
||
|
//... MESSAGE_RESOURCE_BLOCK.
|
||
|
//
|
||
|
// 01/93 - Changes for var length token text strings. Mhotchin
|
||
|
//
|
||
|
|
||
|
void TokResMessage(
|
||
|
|
||
|
FILE *pfTokFile, //... Output token file
|
||
|
RESHEADER ResHeader, //... Resource header data
|
||
|
VOID *pMsgResData) //... Data to tokenize (from GetResMessage call)
|
||
|
{
|
||
|
static TOKEN Tok;
|
||
|
ULONG ulBlock; //... Message resource block number
|
||
|
PMESSAGE_RESOURCE_DATA pData; //... Data to tokenize
|
||
|
PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a message block struct
|
||
|
|
||
|
|
||
|
pData = (PMESSAGE_RESOURCE_DATA)pMsgResData;
|
||
|
memset( (void *)&Tok, 0, sizeof( Tok));
|
||
|
|
||
|
Tok.wType = ResHeader.wTypeID;
|
||
|
Tok.wName = ResHeader.wNameID;
|
||
|
|
||
|
Tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
|
||
|
|
||
|
if ( ResHeader.bNameFlag == IDFLAG )
|
||
|
{
|
||
|
lstrcpy( Tok.szName, ResHeader.pszName);
|
||
|
}
|
||
|
|
||
|
for ( ulBlock = 0L; ulBlock < pData->NumberOfBlocks; ++ulBlock )
|
||
|
{
|
||
|
ULONG ulCurrID = 0L; //... ID # of current msg being processed
|
||
|
ULONG ulEndID; //... Last message ID # in this block + 1
|
||
|
USHORT usLineNum = 0; //... Count of lines in a message text
|
||
|
PCHAR pMRE; //... ptr to a message entry struct
|
||
|
|
||
|
|
||
|
//... Get ptr to this message block struct
|
||
|
|
||
|
pMRB = &pData->Blocks[ ulBlock];
|
||
|
|
||
|
//... Get ptr to first entry in
|
||
|
//... this block of messages
|
||
|
|
||
|
pMRE = (PCHAR)pBlockEntries[ ulBlock];
|
||
|
|
||
|
//... Tokenize entries in this block of messages
|
||
|
|
||
|
for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
|
||
|
ulCurrID < ulEndID;
|
||
|
++ulCurrID )
|
||
|
{
|
||
|
usLineNum = 0;
|
||
|
|
||
|
//... inclusive of .Length and .Flags fields so
|
||
|
//... we need get the real length of the text.
|
||
|
|
||
|
if ( ((PMRE)pMRE)->Length >= 2 * sizeof( WORD) )
|
||
|
{
|
||
|
USHORT usLen = 0;
|
||
|
USHORT usTokTextLen = 0;
|
||
|
PWCHAR pszwStart = NULL;
|
||
|
// This is really ugly. This code was
|
||
|
// originally to get around the problem
|
||
|
// that tokens could hold only 260 chars.
|
||
|
// Now, it's whatever you want.
|
||
|
// Temp hack - assume each line will be
|
||
|
// less than 4k in size. (mhotchin)
|
||
|
static TCHAR szwString[ 32768 ];
|
||
|
|
||
|
//... Put low word of ID# in .wID and
|
||
|
//... the high word in .szName
|
||
|
|
||
|
Tok.wID = LOWORD( ulCurrID);
|
||
|
_itoa( HIWORD( ulCurrID), szDHW, 10);
|
||
|
_MBSTOWCS( Tok.szName,
|
||
|
szDHW,
|
||
|
TOKENSTRINGBUFFER,
|
||
|
lstrlenA( szDHW) +1);
|
||
|
|
||
|
//... The err msg table strings may be stored
|
||
|
//... in the resources as ANSI or Unicode.
|
||
|
//... If the pMRE->Flags field in the
|
||
|
//... table entry struct is 0, the text is a
|
||
|
//... ANSI striing so we need to convert it to
|
||
|
//... UNICODE (WCHAR).
|
||
|
|
||
|
if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
|
||
|
{
|
||
|
PUCHAR puchStart = (PUCHAR)((PMRE)pMRE)->Text;
|
||
|
|
||
|
usLen = (USHORT)_MBSTOWCS( szwString,
|
||
|
puchStart,
|
||
|
WCHARSIN( sizeof( szwString)),
|
||
|
ACHARSIN( lstrlenA( puchStart) + 1));
|
||
|
|
||
|
if (usLen == 0)
|
||
|
QuitT( IDS_ENGERR_10, szwString, NULL);
|
||
|
|
||
|
pszwStart = szwString;
|
||
|
}
|
||
|
else //... Unicode message
|
||
|
{
|
||
|
pszwStart = (WCHAR *)(((PMRE)pMRE)->Text);
|
||
|
usLen = (USHORT)lstrlen( pszwStart) /*+ 1*/;
|
||
|
}
|
||
|
//... We need to split the token text at \r\n
|
||
|
|
||
|
for ( Tok.wFlag = 0;
|
||
|
usLen > 0;
|
||
|
usLen -= usTokTextLen, Tok.wFlag++ )
|
||
|
{
|
||
|
WCHAR wcTmp;
|
||
|
|
||
|
|
||
|
for ( usTokTextLen = 0, wcTmp = TEXT('\0');
|
||
|
usTokTextLen < usLen;
|
||
|
++usTokTextLen )
|
||
|
{
|
||
|
if ( pszwStart[ usTokTextLen] == TEXT('\r')
|
||
|
&& pszwStart[ usTokTextLen+1] == TEXT('\n') )
|
||
|
{
|
||
|
usTokTextLen += 2;
|
||
|
wcTmp = pszwStart[ usTokTextLen];
|
||
|
pszwStart[ usTokTextLen] = TEXT('\0');
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Tok.szText = BinToTextW( pszwStart, usTokTextLen);
|
||
|
|
||
|
PutToken( pfTokFile, &Tok);
|
||
|
|
||
|
RLFREE( Tok.szText);
|
||
|
|
||
|
pszwStart += usTokTextLen;
|
||
|
*pszwStart = wcTmp;
|
||
|
}
|
||
|
//... Set up to move to start of next msg entry
|
||
|
|
||
|
pMRE += ((PMRE)pMRE)->Length;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ClearResMsg( &pResMsgData);
|
||
|
QuitT( IDS_ENGERR_05, (LPTSTR)IDS_MSGTOOSHORT, NULL);
|
||
|
}
|
||
|
} //... END FOR processing a msg block
|
||
|
} //... END FOR processing all msg blocks
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//.........................................................................
|
||
|
//...
|
||
|
//... Clear memory created in GetResMessage()
|
||
|
|
||
|
void ClearResMsg(
|
||
|
|
||
|
VOID **pData) //... ptr to ptr to start of memory to free
|
||
|
{
|
||
|
if ( pData != NULL && *pData != NULL )
|
||
|
{
|
||
|
ULONG ulBlock;
|
||
|
PMESSAGE_RESOURCE_DATA pMRD; //... ptr to a message data struct
|
||
|
PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a message block struct
|
||
|
|
||
|
|
||
|
pMRD = (PMESSAGE_RESOURCE_DATA)*pData;
|
||
|
pMRB = pMRD->Blocks;
|
||
|
|
||
|
if ( pBlockEntries != NULL )
|
||
|
{
|
||
|
for ( ulBlock = 0L; ulBlock < pMRD->NumberOfBlocks; ++ulBlock )
|
||
|
{
|
||
|
if ( pBlockEntries[ ulBlock] )
|
||
|
{
|
||
|
RLFREE( pBlockEntries[ ulBlock]);
|
||
|
}
|
||
|
}
|
||
|
RLFREE( (PBYTE)pBlockEntries);
|
||
|
}
|
||
|
RLFREE( *pData);
|
||
|
}
|
||
|
}
|