Source code of Windows XP (NT5)
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.

466 lines
15 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. mcout.c
  5. Abstract:
  6. This file contains the output functions of the Win32 Message Compiler (MC)
  7. Author:
  8. Steve Wood (stevewo) 22-Aug-1991
  9. Revision History:
  10. --*/
  11. #include "mc.h"
  12. PMESSAGE_BLOCK MessageBlocks = NULL;
  13. int NumberOfBlocks = 0;
  14. BOOL
  15. McBlockMessages( void )
  16. {
  17. PMESSAGE_BLOCK p, *pp;
  18. PMESSAGE_INFO MessageInfo;
  19. pp = &MessageBlocks;
  20. p = NULL;
  21. MessageInfo = Messages;
  22. while (MessageInfo) {
  23. if (p) {
  24. if (p->HighId+1 == MessageInfo->Id) {
  25. p->HighId += 1;
  26. }
  27. else {
  28. pp = &p->Next;
  29. }
  30. }
  31. if (!*pp) {
  32. NumberOfBlocks += 1;
  33. p = malloc( sizeof( *p ) );
  34. if (!p) {
  35. McInputErrorA( "Out of memory reading messages", TRUE, NULL );
  36. return FALSE;
  37. }
  38. p->Next = NULL;
  39. p->LowId = MessageInfo->Id;
  40. p->HighId = MessageInfo->Id;
  41. p->LowInfo = MessageInfo;
  42. *pp = p;
  43. }
  44. MessageInfo = MessageInfo->Next;
  45. }
  46. return( TRUE );
  47. }
  48. BOOL
  49. McWriteBinaryFilesA( void )
  50. {
  51. PNAME_INFO LanguageName, *pp;
  52. PLANGUAGE_INFO LanguageInfo;
  53. PMESSAGE_INFO MessageInfo;
  54. PMESSAGE_BLOCK BlockInfo;
  55. char *FileName;
  56. ULONG cb, cbNeeded;
  57. ULONG MessageOffset;
  58. MESSAGE_RESOURCE_ENTRY MessageEntry;
  59. MESSAGE_RESOURCE_BLOCK MessageBlock;
  60. MESSAGE_RESOURCE_DATA MessageData;
  61. ULONG Zeroes = 0;
  62. ULONG NumberOfMessages;
  63. LPBYTE lpBuf;
  64. ULONG Size = 256;
  65. FileName = BinaryMessageFileName;
  66. FileName += strlen( FileName );
  67. lpBuf = malloc( Size );
  68. if (!lpBuf) {
  69. McInputErrorA( "Out of memory writing to output file - %s", TRUE, BinaryMessageFileName );
  70. return( FALSE );
  71. }
  72. pp = &LanguageNames;
  73. while (LanguageName = *pp) {
  74. pp = &LanguageName->Next;
  75. if (!LanguageName->Used) {
  76. continue;
  77. }
  78. WideCharToMultiByte( CP_OEMCP, 0, LanguageName->Value, -1, FileName,
  79. sizeof( BinaryMessageFileName ) - strlen( FileName ), NULL, NULL );
  80. strcat( FileName, ".bin" );
  81. if (!(BinaryMessageFile = fopen( BinaryMessageFileName, "wb" ))) {
  82. McInputErrorA( "unable to open output file - %s", TRUE, BinaryMessageFileName );
  83. return( FALSE );
  84. }
  85. if (VerboseOutput) {
  86. fprintf( stderr, "Writing %s\n", BinaryMessageFileName );
  87. }
  88. fprintf( RcInclFile, "LANGUAGE 0x%x,0x%x\r\n",
  89. PRIMARYLANGID( LanguageName->Id ),
  90. SUBLANGID( LanguageName->Id )
  91. );
  92. if (fUniqueBinName) {
  93. fprintf(RcInclFile, "1 11 %s_%s\r\n", FNameMsgFileName, FileName);
  94. } else {
  95. fprintf( RcInclFile, "1 11 %s\r\n", FileName );
  96. }
  97. NumberOfMessages = 0L;
  98. MessageData.NumberOfBlocks = NumberOfBlocks;
  99. MessageOffset = fwrite( &MessageData,
  100. 1,
  101. (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_DATA,
  102. Blocks[ 0 ]
  103. ),
  104. BinaryMessageFile
  105. );
  106. MessageOffset += NumberOfBlocks * sizeof( MessageBlock );
  107. BlockInfo = MessageBlocks;
  108. while (BlockInfo) {
  109. MessageBlock.LowId = BlockInfo->LowId;
  110. MessageBlock.HighId = BlockInfo->HighId;
  111. MessageBlock.OffsetToEntries = MessageOffset;
  112. fwrite( &MessageBlock, 1, sizeof( MessageBlock ), BinaryMessageFile );
  113. BlockInfo->InfoLength = 0;
  114. MessageInfo = BlockInfo->LowInfo;
  115. while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) {
  116. LanguageInfo = MessageInfo->MessageText;
  117. while (LanguageInfo) {
  118. if (LanguageInfo->Id == LanguageName->Id) {
  119. break;
  120. }
  121. else {
  122. LanguageInfo = LanguageInfo->Next;
  123. }
  124. }
  125. if (LanguageInfo != NULL) {
  126. cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) +
  127. WideCharToMultiByte( LanguageName->CodePage,
  128. 0,
  129. LanguageInfo->Text,
  130. LanguageInfo->Length,
  131. NULL, 0, NULL, NULL ) + 1;
  132. cb = (cb + 3) & ~3;
  133. BlockInfo->InfoLength += cb;
  134. }
  135. else {
  136. fprintf( stderr,
  137. "MC: No %ws language text for %ws\n",
  138. LanguageName->Name,
  139. MessageInfo->SymbolicName
  140. );
  141. fclose( BinaryMessageFile );
  142. return( FALSE );
  143. }
  144. MessageInfo = MessageInfo->Next;
  145. }
  146. if (VerboseOutput) {
  147. fprintf( stderr, " [%08lx .. %08lx] - %lu bytes\n",
  148. BlockInfo->LowId,
  149. BlockInfo->HighId,
  150. BlockInfo->InfoLength
  151. );
  152. }
  153. MessageOffset += BlockInfo->InfoLength;
  154. BlockInfo = BlockInfo->Next;
  155. }
  156. BlockInfo = MessageBlocks;
  157. while (BlockInfo) {
  158. MessageInfo = BlockInfo->LowInfo;
  159. while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) {
  160. LanguageInfo = MessageInfo->MessageText;
  161. while (LanguageInfo) {
  162. if (LanguageInfo->Id == LanguageName->Id) {
  163. break;
  164. }
  165. else {
  166. LanguageInfo = LanguageInfo->Next;
  167. }
  168. }
  169. if (LanguageInfo != NULL) {
  170. cbNeeded = WideCharToMultiByte( LanguageName->CodePage,
  171. 0,
  172. LanguageInfo->Text,
  173. LanguageInfo->Length,
  174. NULL, 0, NULL, NULL );
  175. cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) +
  176. cbNeeded + 1;
  177. cb = (cb + 3) & ~3;
  178. MessageEntry.Length = (USHORT)cb;
  179. MessageEntry.Flags = 0;
  180. cb = fwrite( &MessageEntry,
  181. 1,
  182. (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY,
  183. Text[ 0 ]
  184. ),
  185. BinaryMessageFile
  186. );
  187. if (Size < cbNeeded ) {
  188. lpBuf = realloc( lpBuf, cbNeeded );
  189. if (!lpBuf) {
  190. McInputErrorA( "Out of memory writing to output file - %s",
  191. TRUE, BinaryMessageFileName );
  192. return( FALSE );
  193. }
  194. Size = cbNeeded;
  195. }
  196. WideCharToMultiByte( LanguageName->CodePage,
  197. 0,
  198. LanguageInfo->Text,
  199. LanguageInfo->Length,
  200. lpBuf, cbNeeded, NULL, NULL );
  201. cb += fwrite( lpBuf,
  202. 1,
  203. (size_t)cbNeeded,
  204. BinaryMessageFile
  205. );
  206. NumberOfMessages++;
  207. cb = MessageEntry.Length - cb;
  208. if (cb) {
  209. fwrite( &Zeroes,
  210. 1,
  211. (size_t)cb,
  212. BinaryMessageFile
  213. );
  214. }
  215. }
  216. MessageInfo = MessageInfo->Next;
  217. }
  218. BlockInfo = BlockInfo->Next;
  219. }
  220. if (VerboseOutput) {
  221. fprintf( stderr, " Total of %lu messages, %lu bytes\n",
  222. NumberOfMessages,
  223. ftell( BinaryMessageFile )
  224. );
  225. }
  226. fclose( BinaryMessageFile );
  227. McClearArchiveBit( BinaryMessageFileName );
  228. }
  229. free( lpBuf );
  230. return( TRUE );
  231. }
  232. BOOL
  233. McWriteBinaryFilesW( void )
  234. {
  235. PNAME_INFO LanguageName, *pp;
  236. PLANGUAGE_INFO LanguageInfo;
  237. PMESSAGE_INFO MessageInfo;
  238. PMESSAGE_BLOCK BlockInfo;
  239. char *FileName;
  240. ULONG cb;
  241. ULONG MessageOffset;
  242. MESSAGE_RESOURCE_ENTRY MessageEntry;
  243. MESSAGE_RESOURCE_BLOCK MessageBlock;
  244. MESSAGE_RESOURCE_DATA MessageData;
  245. ULONG Zeroes = 0;
  246. ULONG NumberOfMessages;
  247. FileName = BinaryMessageFileName;
  248. FileName += strlen( FileName );
  249. pp = &LanguageNames;
  250. while (LanguageName = *pp) {
  251. pp = &LanguageName->Next;
  252. if (!LanguageName->Used) {
  253. continue;
  254. }
  255. WideCharToMultiByte( CP_OEMCP, 0, LanguageName->Value, -1,
  256. FileName, sizeof( BinaryMessageFileName ), NULL, NULL);
  257. strcat( FileName, ".bin" );
  258. if (!(BinaryMessageFile = fopen( BinaryMessageFileName, "wb" ))) {
  259. McInputErrorA( "unable to open output file - %s", TRUE, BinaryMessageFileName );
  260. return( FALSE );
  261. }
  262. if (VerboseOutput) {
  263. fprintf( stderr, "Writing %s\n", BinaryMessageFileName );
  264. }
  265. fprintf( RcInclFile, "LANGUAGE 0x%x,0x%x\r\n",
  266. PRIMARYLANGID( LanguageName->Id ),
  267. SUBLANGID( LanguageName->Id )
  268. );
  269. if (fUniqueBinName) {
  270. fprintf(RcInclFile, "1 11 %s_%s\r\n", FNameMsgFileName, FileName);
  271. } else {
  272. fprintf( RcInclFile, "1 11 %s\r\n", FileName );
  273. }
  274. NumberOfMessages = 0L;
  275. MessageData.NumberOfBlocks = NumberOfBlocks;
  276. MessageOffset = fwrite( &MessageData,
  277. 1,
  278. (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_DATA,
  279. Blocks[ 0 ]
  280. ),
  281. BinaryMessageFile
  282. );
  283. MessageOffset += NumberOfBlocks * sizeof( MessageBlock );
  284. BlockInfo = MessageBlocks;
  285. while (BlockInfo) {
  286. MessageBlock.LowId = BlockInfo->LowId;
  287. MessageBlock.HighId = BlockInfo->HighId;
  288. MessageBlock.OffsetToEntries = MessageOffset;
  289. fwrite( &MessageBlock, 1, sizeof( MessageBlock ), BinaryMessageFile );
  290. BlockInfo->InfoLength = 0;
  291. MessageInfo = BlockInfo->LowInfo;
  292. while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) {
  293. LanguageInfo = MessageInfo->MessageText;
  294. while (LanguageInfo) {
  295. if (LanguageInfo->Id == LanguageName->Id) {
  296. break;
  297. }
  298. else {
  299. LanguageInfo = LanguageInfo->Next;
  300. }
  301. }
  302. if (LanguageInfo != NULL) {
  303. cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) +
  304. ( LanguageInfo->Length + 1 );
  305. cb = (cb + 3) & ~3;
  306. BlockInfo->InfoLength += cb;
  307. }
  308. else {
  309. fprintf( stderr,
  310. "MC: No %ws language text for %ws\n",
  311. LanguageName->Name,
  312. MessageInfo->SymbolicName
  313. );
  314. fclose( BinaryMessageFile );
  315. _unlink( BinaryMessageFileName );
  316. return( FALSE );
  317. }
  318. MessageInfo = MessageInfo->Next;
  319. }
  320. if (VerboseOutput) {
  321. fprintf( stderr, " [%08lx .. %08lx] - %lu bytes\n",
  322. BlockInfo->LowId,
  323. BlockInfo->HighId,
  324. BlockInfo->InfoLength
  325. );
  326. }
  327. MessageOffset += BlockInfo->InfoLength;
  328. BlockInfo = BlockInfo->Next;
  329. }
  330. BlockInfo = MessageBlocks;
  331. while (BlockInfo) {
  332. MessageInfo = BlockInfo->LowInfo;
  333. while (MessageInfo != NULL && MessageInfo->Id <= BlockInfo->HighId) {
  334. LanguageInfo = MessageInfo->MessageText;
  335. while (LanguageInfo) {
  336. if (LanguageInfo->Id == LanguageName->Id) {
  337. break;
  338. }
  339. else {
  340. LanguageInfo = LanguageInfo->Next;
  341. }
  342. }
  343. if (LanguageInfo != NULL) {
  344. cb = FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY, Text[ 0 ] ) +
  345. ( LanguageInfo->Length + 1 ) ;
  346. cb = (cb + 3) & ~3;
  347. MessageEntry.Length = (USHORT)cb;
  348. MessageEntry.Flags = MESSAGE_RESOURCE_UNICODE;
  349. cb = fwrite( &MessageEntry,
  350. 1,
  351. (size_t)FIELD_OFFSET( MESSAGE_RESOURCE_ENTRY,
  352. Text[ 0 ]
  353. ),
  354. BinaryMessageFile
  355. );
  356. cb += fwrite( LanguageInfo->Text,
  357. 1,
  358. (size_t)( LanguageInfo->Length ),
  359. BinaryMessageFile
  360. );
  361. NumberOfMessages++;
  362. cb = MessageEntry.Length - cb;
  363. if (cb) {
  364. fwrite( &Zeroes,
  365. 1,
  366. (size_t)cb,
  367. BinaryMessageFile
  368. );
  369. }
  370. }
  371. MessageInfo = MessageInfo->Next;
  372. }
  373. BlockInfo = BlockInfo->Next;
  374. }
  375. if (VerboseOutput) {
  376. fprintf( stderr, " Total of %lu messages, %lu bytes\n",
  377. NumberOfMessages,
  378. ftell( BinaryMessageFile )
  379. );
  380. }
  381. fclose( BinaryMessageFile );
  382. McClearArchiveBit( BinaryMessageFileName );
  383. }
  384. return( TRUE );
  385. }