Leaked source code of windows server 2003
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.

720 lines
27 KiB

  1. //.....................................................................
  2. //...
  3. //... NTMSGTBL.C
  4. //...
  5. //... Contains functions for handling strings found in NT's Message
  6. //... Resource Tables. This recource type is not present in Win 3.1.
  7. //...
  8. //... Author - David Wilcox (davewi@microsoft)
  9. //...
  10. //... NOTES: Created with tabstop set to 8
  11. //...
  12. //.....................................................................
  13. //...
  14. //... History:
  15. //... Original - 10/92
  16. //... 11/92 - Fixed to handle ULONG msg ID#'s - davewi
  17. //...
  18. //.....................................................................
  19. #include <windows.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <windef.h>
  24. #include <tchar.h>
  25. #include <winver.h>
  26. #include "windefs.h"
  27. #include "restok.h"
  28. #include "custres.h"
  29. #include "ntmsgtbl.h"
  30. #include "resread.h"
  31. typedef PMESSAGE_RESOURCE_ENTRY PMRE;
  32. extern BOOL gbMaster;
  33. extern UCHAR szDHW[];
  34. static PBYTE *pBlockEntries = NULL;
  35. VOID *pResMsgData = NULL; // NT-specific Message Table resource
  36. //.........................................................................
  37. //...
  38. //... Get Message Table from .res file
  39. //...
  40. //... This form of a message table, not found in Win 16, allows very long
  41. //... strings and the text is stored as an ASCIIZ string in the .res file.
  42. VOID *GetResMessage(
  43. FILE *pInResFile, //... The file containing the resources
  44. DWORD *plSize) //... The size of this resource from GetResHeader
  45. {
  46. ULONG ulNumBlocks = 0L; //... # of Message Table resource blocks
  47. ULONG ulStartMsgDataPos = 0L; //... Start of message data in file
  48. ULONG ulBlock; //... Current message block number
  49. USHORT usCurrBlockSize = 0; //... Current size of temp block buffer
  50. USHORT usDeltaBlockSize = 4096; //... Amount to increase usCurrBlockSize
  51. DWORD dwNumMsgs = 0; //... Count of msgs in the resource
  52. PBYTE pMsgBlock = NULL; //... Temp message block buffer
  53. PMESSAGE_RESOURCE_DATA pMsgResData;//... Returned as ptr to the resource
  54. PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a block of messages
  55. //... The resource header was read prior to
  56. //... entring this function, so the current
  57. //... file position should now be the start
  58. //... of the resource data.
  59. ulStartMsgDataPos = ftell( pInResFile);
  60. //... Get the number of message blocks and
  61. //... allocate enough memory for the array.
  62. ulNumBlocks = GetdWord( pInResFile, plSize);
  63. //... Allocate space for the array of
  64. //... pointers to entries. This array is used
  65. //... to store pointers to the first entry
  66. //... in each block of message entries.
  67. pBlockEntries = (PBYTE *)FALLOC( ulNumBlocks * sizeof( PBYTE));
  68. if ( ! pBlockEntries )
  69. {
  70. QuitT( IDS_ENGERR_11, NULL, NULL);
  71. }
  72. pMsgResData = (PMESSAGE_RESOURCE_DATA)FALLOC( sizeof( ULONG) + ulNumBlocks
  73. * sizeof( MESSAGE_RESOURCE_BLOCK));
  74. if ( ! pMsgResData )
  75. {
  76. QuitT( IDS_ENGERR_11, NULL, NULL);
  77. }
  78. pResMsgData = pMsgResData;
  79. pMsgResData->NumberOfBlocks = ulNumBlocks;
  80. //... Read the array of message block structs,
  81. //... and initialize block entry pointer array.
  82. for ( ulBlock = 0L, pMRB = pMsgResData->Blocks;
  83. ulBlock < ulNumBlocks;
  84. ++ulBlock, ++pMRB )
  85. {
  86. pMRB->LowId = GetdWord( pInResFile, plSize);
  87. pMRB->HighId = GetdWord( pInResFile, plSize);
  88. pMRB->OffsetToEntries = GetdWord( pInResFile, plSize);
  89. if ( pMRB->HighId < pMRB->LowId )
  90. {
  91. ClearResMsg( &pResMsgData);
  92. QuitT( IDS_ENGERR_16, (LPTSTR)IDS_INVMSGRNG, NULL);
  93. }
  94. dwNumMsgs += (pMRB->HighId - pMRB->LowId + 1);
  95. pBlockEntries[ ulBlock] = NULL;
  96. }
  97. //... Read in the MESSAGE_RESOURCE_ENTRY
  98. usCurrBlockSize = usDeltaBlockSize;
  99. for ( ulBlock = 0L, pMRB = pMsgResData->Blocks;
  100. ulBlock < ulNumBlocks;
  101. ++ulBlock, ++pMRB )
  102. {
  103. ULONG ulCurrID; //... Current message ID # in this block
  104. ULONG ulEndID; //... Last message ID # in this block + 1
  105. USHORT usLen; //... For length of a message - MUST BE USHORT
  106. USHORT usMsgBlkLen; //... Length of a block of messages
  107. usMsgBlkLen = 0;
  108. //... Move to start of block of message entries
  109. //... then read all the messages in this block.
  110. fseek( pInResFile,
  111. ulStartMsgDataPos + pMRB->OffsetToEntries,
  112. SEEK_SET);
  113. for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
  114. ulCurrID < ulEndID;
  115. ++ulCurrID, --dwNumMsgs )
  116. {
  117. //... Get Msg Resource entry length
  118. //... (Length is in bytes and includes
  119. //... .Length and .Flags fields and any
  120. //... padding that may exist after the text.)
  121. usLen = GetWord( pInResFile, plSize);
  122. if ( usLen >= 2 * sizeof( USHORT) )
  123. {
  124. PMRE pMRE;
  125. PUCHAR puchText;
  126. //... Create, or expand size of, pMsgBlkData
  127. //... so we can append this entry.
  128. //... Always resave ptr to the message block
  129. //... (it may have moved).
  130. if ( pMsgBlock )
  131. {
  132. if ( (USHORT)(usMsgBlkLen + usLen) > usCurrBlockSize )
  133. {
  134. usCurrBlockSize += __max(usDeltaBlockSize, (USHORT)(usMsgBlkLen + usLen));
  135. pMsgBlock = (PBYTE)FREALLOC( pMsgBlock,
  136. usCurrBlockSize);
  137. }
  138. }
  139. else
  140. {
  141. pMsgBlock = FALLOC( usCurrBlockSize);
  142. }
  143. //... If the malloc worked, read this msg entry.
  144. //... The section assumes there is one WORD
  145. //... per USHORT and one WORD per WCHAR.
  146. pMRE = (PMRE)(pMsgBlock + usMsgBlkLen);
  147. //... Store the .Length field value (USHORT)
  148. pMRE->Length = usLen;
  149. usMsgBlkLen += usLen;
  150. //... Get the .Flags field value (USHORT)
  151. pMRE->Flags = GetWord( pInResFile, plSize);
  152. //... Check to make sure this message is stored
  153. //... either in ASCII in the current code page
  154. //... or in Unicode, else fail.
  155. if ( pMRE->Flags != 0 //... ASCII
  156. && pMRE->Flags != MESSAGE_RESOURCE_UNICODE ) //... Unicode
  157. {
  158. if ( pMsgBlock != NULL )
  159. {
  160. RLFREE( pMsgBlock);
  161. }
  162. ClearResMsg( &pResMsgData);
  163. QuitA( IDS_NON0FLAG, NULL, NULL);
  164. }
  165. //... Get the .Text field string
  166. usLen -= (2 * sizeof( WORD));
  167. for ( puchText = (PUCHAR)pMRE->Text; usLen; ++puchText, --usLen )
  168. {
  169. *puchText = (UCHAR)GetByte( pInResFile, plSize);
  170. }
  171. DWordUpFilePointer( pInResFile,
  172. MYREAD,
  173. ftell( pInResFile),
  174. plSize);
  175. }
  176. else
  177. {
  178. if ( pMsgBlock != NULL )
  179. {
  180. RLFREE( pMsgBlock);
  181. }
  182. ClearResMsg( &pResMsgData);
  183. QuitT( IDS_ENGERR_05, (LPTSTR)IDS_INVMSGTBL, NULL);
  184. }
  185. } //... END FOR(each message entry in this block)
  186. if ( pMsgBlock != NULL && usMsgBlkLen > 0 )
  187. {
  188. pBlockEntries[ ulBlock] = FALLOC( usMsgBlkLen);
  189. memcpy( pBlockEntries[ ulBlock], pMsgBlock, usMsgBlkLen);
  190. }
  191. } //... END FOR(each message block)
  192. if ( pMsgBlock != NULL )
  193. {
  194. RLFREE( pMsgBlock);
  195. }
  196. DWordUpFilePointer( pInResFile, MYREAD, ftell( pInResFile), plSize);
  197. return( (VOID *)pMsgResData);
  198. }
  199. //.........................................................................
  200. //...
  201. //... Put localized Message Table into .res
  202. //...
  203. //... 01/93 - changes for var length Token text. MHotchin
  204. //... 02/93 - stripped out code that split msgs into multiple tokens. davewi
  205. void PutResMessage(
  206. FILE *fpOutResFile, //... File to which localized resources are written
  207. FILE *fpInTokFile, //... Output token file
  208. RESHEADER ResHeader, //... Resource header data
  209. VOID *pMsgResData) //... message table data built in GetResMessage
  210. {
  211. WORD wcCount = 0;
  212. fpos_t ulResSizePos = 0L; //... File position for fixed up resource size
  213. fpos_t ulBlocksStartPos=0L; //... File position of start of message blocks
  214. ULONG ulNumBlocks = 0L; //... Number of Message Blocks
  215. ULONG ulCurrOffset = 0L; //... Offset to current msg block
  216. ULONG ulResSize = 0L; //... Size of this resource
  217. ULONG ulBlock; //... Temporary counter
  218. USHORT usEntryLen = 0; //... Length of current message entry
  219. PMESSAGE_RESOURCE_DATA pData; //. Message table data from InResFile
  220. static TOKEN Tok; //... Token from localized token file
  221. if ( pMsgResData == NULL)
  222. {
  223. QuitT( IDS_ENGERR_05, (LPTSTR)IDS_NULMSGDATA, NULL);
  224. }
  225. memset( (void *)&Tok, 0, sizeof( Tok));
  226. pData = (PMESSAGE_RESOURCE_DATA)pMsgResData;
  227. if ( PutResHeader( fpOutResFile, ResHeader, &ulResSizePos, &ulResSize))
  228. {
  229. ClearResMsg( &pResMsgData);
  230. QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MSGTBLHDR, NULL);
  231. }
  232. ulResSize = 0L; //... Reset to zero (hdr len not to be included)
  233. ulNumBlocks = pData->NumberOfBlocks;
  234. //... Write number of msg blocks
  235. PutdWord( fpOutResFile, ulNumBlocks, &ulResSize);
  236. //... Remember this file position so we can
  237. //... come back here and update the
  238. //... OffsetToEntries field in each struct.
  239. ulBlocksStartPos = ftell( fpOutResFile);
  240. //... Write the array of message block structs
  241. for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
  242. {
  243. PutdWord( fpOutResFile, pData->Blocks[ ulBlock].LowId, &ulResSize);
  244. PutdWord( fpOutResFile, pData->Blocks[ ulBlock].HighId, &ulResSize);
  245. PutdWord( fpOutResFile, 0L, &ulResSize); //... Will get fixed up later
  246. }
  247. // Prep for find token call
  248. Tok.wType = ResHeader.wTypeID;
  249. Tok.wName = ResHeader.wNameID;
  250. Tok.wID = 0;
  251. Tok.wFlag = 0;
  252. if ( ResHeader.bNameFlag == IDFLAG )
  253. {
  254. lstrcpy( Tok.szName, ResHeader.pszName);
  255. }
  256. //... Write the MESSAGE_RESOURCE_ENTRY's. First
  257. //... note offset from start of this resource's
  258. //... data to first msg res entry struct which
  259. //... starts right after the array of
  260. //... RESOURCE_MESSAGE_BLOCK structs.
  261. ulCurrOffset = sizeof( ULONG) + ulNumBlocks*sizeof( MESSAGE_RESOURCE_BLOCK);
  262. for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
  263. {
  264. ULONG ulCurrID; //... Current message ID # in this block
  265. ULONG ulEndID; //... Last message ID # in this block + 1
  266. fpos_t ulEntryPos; //... Start of the current msg entry struct
  267. PBYTE pMRE; //... Ptr to a MESSAGE_RESOURCE_ENTRY
  268. PMESSAGE_RESOURCE_BLOCK pMRB;
  269. //... Retrieve ptr to block of messages. The
  270. //... ptr was stored in the pBlockEntries array
  271. //... in GetResMessage function above.
  272. pMRB = (PMESSAGE_RESOURCE_BLOCK)( &pData->Blocks[ ulBlock]);
  273. pMRE = pBlockEntries[ ulBlock];
  274. //... Note offset to start of block's entries
  275. pData->Blocks[ ulBlock].OffsetToEntries = ulCurrOffset;
  276. for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
  277. ulCurrID < ulEndID;
  278. ++ulCurrID )
  279. {
  280. static UCHAR szString[ 64] = "";
  281. static TCHAR szwTmp[ 4096] = TEXT("");
  282. USHORT usCnt = 0;
  283. BOOL fFound = FALSE;
  284. ULONG ulEntrySize = 0;
  285. ulEntryPos = ftell( fpOutResFile);
  286. ulEntrySize = 0L;
  287. //... Write dummy entry length.
  288. //... Value gets corrected later.
  289. //... Write the .Flags field's value (USHORT).
  290. PutWord( fpOutResFile, ((PMRE)pMRE)->Length, &ulEntrySize);
  291. PutWord( fpOutResFile, ((PMRE)pMRE)->Flags, &ulEntrySize);
  292. //... Get localized token then the length of
  293. //... that token's new text. Add to that length
  294. //... the length of the two USHORTs and use this
  295. //... combined length as the value to store in
  296. //... the msg res entry's .Length field.
  297. //... Put low word of ID# in .wID and
  298. //... the high word in .szName
  299. Tok.wID = LOWORD( ulCurrID);
  300. _itoa( HIWORD( ulCurrID), szString, 10);
  301. _MBSTOWCS( Tok.szName,
  302. szString,
  303. TOKENSTRINGBUFFER,
  304. lstrlenA( szString) + 1);
  305. //... Always reset .wReserved because the code
  306. //... in FindTokenText will change its value.
  307. Tok.wReserved = ST_TRANSLATED;
  308. Tok.szText = NULL;
  309. *szwTmp = TEXT('\0');
  310. for ( fFound = FALSE, Tok.wFlag = 0;
  311. fFound = FindToken( fpInTokFile, &Tok, ST_TRANSLATED);
  312. Tok.wFlag++ )
  313. {
  314. TextToBin( szwTmp, Tok.szText, lstrlen( Tok.szText) + 1);
  315. //... Write out localized message text. It may
  316. //... be stored as ASCII or Unicode string.
  317. if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
  318. {
  319. _WCSTOMBS( szDHW,
  320. szwTmp,
  321. DHWSIZE,
  322. lstrlen( szwTmp) + 1);
  323. for ( usCnt = 0; szDHW[ usCnt]; ++usCnt )
  324. {
  325. PutByte( fpOutResFile, szDHW[ usCnt], &ulEntrySize);
  326. }
  327. }
  328. else //... Unicode message
  329. {
  330. for ( usCnt = 0; szwTmp[ usCnt]; ++usCnt )
  331. {
  332. PutWord( fpOutResFile, szwTmp[ usCnt], &ulEntrySize);
  333. }
  334. }
  335. *szwTmp = TEXT('\0');
  336. RLFREE( Tok.szText);
  337. //... Always reset .wReserved because the code
  338. //... in FindTokenText will change its value.
  339. Tok.wReserved = ST_TRANSLATED;
  340. }
  341. //... Did we find the token?
  342. if ( Tok.wFlag == 0 && ! fFound )
  343. {
  344. static TCHAR szToken[ 4160];
  345. ParseTokToBuf( szToken, &Tok);
  346. ClearResMsg( &pResMsgData);
  347. QuitT( IDS_ENGERR_05, szToken, NULL);
  348. }
  349. //... nul-terminate the text
  350. if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
  351. {
  352. PutByte( fpOutResFile , '\0', (DWORD *)&ulEntrySize);
  353. }
  354. else //... Unicode message
  355. {
  356. PutWord( fpOutResFile , TEXT('\0'), (DWORD *)&ulEntrySize);
  357. }
  358. DWordUpFilePointer( fpOutResFile,
  359. MYWRITE,
  360. ftell( fpOutResFile),
  361. &ulEntrySize);
  362. //... Also, use this length in later updating
  363. //... next msg block's OffsetToEntries value.
  364. ulResSize += ulEntrySize;
  365. ulCurrOffset += ulEntrySize;
  366. //... Write Msg Resource entry length
  367. //... (Length is in bytes and includes
  368. //... .Length and .Flags fields and any
  369. //... padding needed after the text.)
  370. //...
  371. //... NOTE: Msg text is currently stored as
  372. //... an ASCIIZ string.
  373. fseek( fpOutResFile, (long)ulEntryPos, SEEK_SET);
  374. PutWord( fpOutResFile, (WORD)ulEntrySize, NULL);
  375. fseek( fpOutResFile, 0L, SEEK_END);
  376. //... Move pMRE to point to start of next
  377. //... Message Resource Entry in memory.
  378. pMRE += ((PMRE)pMRE)->Length;
  379. } //... END FOR(each message entry in this block)
  380. ulCurrOffset = DWORDUP( ulCurrOffset);
  381. DWordUpFilePointer( fpOutResFile,
  382. MYWRITE,
  383. ftell( fpOutResFile),
  384. &ulResSize);
  385. } //... END FOR(each message block)
  386. //... Update resource size field in res header
  387. if ( UpdateResSize( fpOutResFile, &ulResSizePos, ulResSize) == 0L )
  388. {
  389. ClearResMsg( &pResMsgData);
  390. QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MSGRESTBL, NULL);
  391. }
  392. //... Now, update the OffsetToEntries fields.
  393. fseek( fpOutResFile, (long)ulBlocksStartPos, SEEK_SET);
  394. for ( ulBlock = 0L; ulBlock < ulNumBlocks; ++ulBlock )
  395. {
  396. PutdWord( fpOutResFile, pData->Blocks[ulBlock].LowId, NULL);
  397. PutdWord( fpOutResFile, pData->Blocks[ulBlock].HighId, NULL);
  398. PutdWord( fpOutResFile, pData->Blocks[ulBlock].OffsetToEntries, NULL);
  399. }
  400. fseek( fpOutResFile, 0L, SEEK_END);
  401. } //... END PutResMessage()
  402. //.........................................................................
  403. //...
  404. //... Write Message Table to the token file
  405. //...
  406. //... This function assumes that, in each message block, the message ID's are
  407. //... contiguouse within the range given in the fields LowId and HighId in a
  408. //... MESSAGE_RESOURCE_BLOCK.
  409. //
  410. // 01/93 - Changes for var length token text strings. Mhotchin
  411. //
  412. void TokResMessage(
  413. FILE *pfTokFile, //... Output token file
  414. RESHEADER ResHeader, //... Resource header data
  415. VOID *pMsgResData) //... Data to tokenize (from GetResMessage call)
  416. {
  417. static TOKEN Tok;
  418. ULONG ulBlock; //... Message resource block number
  419. PMESSAGE_RESOURCE_DATA pData; //... Data to tokenize
  420. PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a message block struct
  421. pData = (PMESSAGE_RESOURCE_DATA)pMsgResData;
  422. memset( (void *)&Tok, 0, sizeof( Tok));
  423. Tok.wType = ResHeader.wTypeID;
  424. Tok.wName = ResHeader.wNameID;
  425. Tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
  426. if ( ResHeader.bNameFlag == IDFLAG )
  427. {
  428. lstrcpy( Tok.szName, ResHeader.pszName);
  429. }
  430. for ( ulBlock = 0L; ulBlock < pData->NumberOfBlocks; ++ulBlock )
  431. {
  432. ULONG ulCurrID = 0L; //... ID # of current msg being processed
  433. ULONG ulEndID; //... Last message ID # in this block + 1
  434. USHORT usLineNum = 0; //... Count of lines in a message text
  435. PCHAR pMRE; //... ptr to a message entry struct
  436. //... Get ptr to this message block struct
  437. pMRB = &pData->Blocks[ ulBlock];
  438. //... Get ptr to first entry in
  439. //... this block of messages
  440. pMRE = (PCHAR)pBlockEntries[ ulBlock];
  441. //... Tokenize entries in this block of messages
  442. for ( ulCurrID = pMRB->LowId, ulEndID = pMRB->HighId + 1;
  443. ulCurrID < ulEndID;
  444. ++ulCurrID )
  445. {
  446. usLineNum = 0;
  447. //... inclusive of .Length and .Flags fields so
  448. //... we need get the real length of the text.
  449. if ( ((PMRE)pMRE)->Length >= 2 * sizeof( WORD) )
  450. {
  451. USHORT usLen = 0;
  452. USHORT usTokTextLen = 0;
  453. PWCHAR pszwStart = NULL;
  454. // This is really ugly. This code was
  455. // originally to get around the problem
  456. // that tokens could hold only 260 chars.
  457. // Now, it's whatever you want.
  458. // Temp hack - assume each line will be
  459. // less than 4k in size. (mhotchin)
  460. static TCHAR szwString[ 32768 ];
  461. //... Put low word of ID# in .wID and
  462. //... the high word in .szName
  463. Tok.wID = LOWORD( ulCurrID);
  464. _itoa( HIWORD( ulCurrID), szDHW, 10);
  465. _MBSTOWCS( Tok.szName,
  466. szDHW,
  467. TOKENSTRINGBUFFER,
  468. lstrlenA( szDHW) +1);
  469. //... The err msg table strings may be stored
  470. //... in the resources as ANSI or Unicode.
  471. //... If the pMRE->Flags field in the
  472. //... table entry struct is 0, the text is a
  473. //... ANSI striing so we need to convert it to
  474. //... UNICODE (WCHAR).
  475. if ( ((PMRE)pMRE)->Flags == 0 ) //... ASCII message
  476. {
  477. PUCHAR puchStart = (PUCHAR)((PMRE)pMRE)->Text;
  478. usLen = (USHORT)_MBSTOWCS( szwString,
  479. puchStart,
  480. WCHARSIN( sizeof( szwString)),
  481. ACHARSIN( lstrlenA( puchStart) + 1));
  482. if (usLen == 0)
  483. QuitT( IDS_ENGERR_10, szwString, NULL);
  484. pszwStart = szwString;
  485. }
  486. else //... Unicode message
  487. {
  488. pszwStart = (WCHAR *)(((PMRE)pMRE)->Text);
  489. usLen = (USHORT)lstrlen( pszwStart) /*+ 1*/;
  490. }
  491. //... We need to split the token text at \r\n
  492. for ( Tok.wFlag = 0;
  493. usLen > 0;
  494. usLen -= usTokTextLen, Tok.wFlag++ )
  495. {
  496. WCHAR wcTmp;
  497. for ( usTokTextLen = 0, wcTmp = TEXT('\0');
  498. usTokTextLen < usLen;
  499. ++usTokTextLen )
  500. {
  501. if ( pszwStart[ usTokTextLen] == TEXT('\r')
  502. && pszwStart[ usTokTextLen+1] == TEXT('\n') )
  503. {
  504. usTokTextLen += 2;
  505. wcTmp = pszwStart[ usTokTextLen];
  506. pszwStart[ usTokTextLen] = TEXT('\0');
  507. break;
  508. }
  509. }
  510. Tok.szText = BinToTextW( pszwStart, usTokTextLen);
  511. PutToken( pfTokFile, &Tok);
  512. RLFREE( Tok.szText);
  513. pszwStart += usTokTextLen;
  514. *pszwStart = wcTmp;
  515. }
  516. //... Set up to move to start of next msg entry
  517. pMRE += ((PMRE)pMRE)->Length;
  518. }
  519. else
  520. {
  521. ClearResMsg( &pResMsgData);
  522. QuitT( IDS_ENGERR_05, (LPTSTR)IDS_MSGTOOSHORT, NULL);
  523. }
  524. } //... END FOR processing a msg block
  525. } //... END FOR processing all msg blocks
  526. }
  527. //.........................................................................
  528. //...
  529. //... Clear memory created in GetResMessage()
  530. void ClearResMsg(
  531. VOID **pData) //... ptr to ptr to start of memory to free
  532. {
  533. if ( pData != NULL && *pData != NULL )
  534. {
  535. ULONG ulBlock;
  536. PMESSAGE_RESOURCE_DATA pMRD; //... ptr to a message data struct
  537. PMESSAGE_RESOURCE_BLOCK pMRB; //... ptr to a message block struct
  538. pMRD = (PMESSAGE_RESOURCE_DATA)*pData;
  539. pMRB = pMRD->Blocks;
  540. if ( pBlockEntries != NULL )
  541. {
  542. for ( ulBlock = 0L; ulBlock < pMRD->NumberOfBlocks; ++ulBlock )
  543. {
  544. if ( pBlockEntries[ ulBlock] )
  545. {
  546. RLFREE( pBlockEntries[ ulBlock]);
  547. }
  548. }
  549. RLFREE( (PBYTE)pBlockEntries);
  550. }
  551. RLFREE( *pData);
  552. }
  553. }