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.

432 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. generr.c
  5. Abstract:
  6. This module contains code to generate the NT status code to DOS
  7. error code table that is used by the runtime to translate status
  8. codes.
  9. Author:
  10. David N. Cutler (davec) 2-Dec-1992
  11. Revision History:
  12. --*/
  13. #include <windows.h>
  14. #include "stdio.h"
  15. #include "stdarg.h"
  16. #include "stdlib.h"
  17. //
  18. // Ensure that the Registry ERROR_SUCCESS error code and the
  19. // NO_ERROR error code remain equal and zero.
  20. //
  21. #if ERROR_SUCCESS != 0 || NO_ERROR != 0
  22. #error Invalid value for ERROR_SUCCESS.
  23. #endif
  24. //
  25. // The following error code table contains paired entries in a singly
  26. // dimensioned array. The first member of a paired entry is an NT status
  27. // code and the second member is the DOS error code that it translates to.
  28. //
  29. // To add a value to this table simply insert the NT status/DOS error code
  30. // pair anywhere is the table. If multiple NT status codes map to a single
  31. // DOS error code, then insert a paired entry for each of the code pairs.
  32. //
  33. #ifdef i386
  34. #pragma warning (4:4018) // lower to -W4
  35. #endif
  36. LONG UNALIGNED *CodePairs;
  37. ULONG TableSize;
  38. //
  39. // Define run table entry structure.
  40. //
  41. typedef struct _RUN_ENTRY {
  42. ULONG BaseCode;
  43. USHORT RunLength;
  44. USHORT CodeSize;
  45. } RUN_ENTRY, *PRUN_ENTRY;
  46. //
  47. // Define forward referenced procedure prptotypes.
  48. //
  49. ULONG
  50. ComputeCodeSize (
  51. IN ULONG Start,
  52. IN ULONG Length
  53. );
  54. ULONG
  55. ComputeRunLength (
  56. IN ULONG Start
  57. );
  58. LONG UNALIGNED *
  59. ReadErrorTable(
  60. IN FILE *InFile,
  61. OUT PULONG TableSize
  62. );
  63. //
  64. // This program generates a header file that is included by the error
  65. // translation module in ntos/rtl.
  66. //
  67. int
  68. _cdecl
  69. main (argc, argv)
  70. int argc;
  71. char *argv[];
  72. {
  73. ULONG Count;
  74. ULONG Index1;
  75. ULONG Index2;
  76. ULONG Length;
  77. FILE *OutFile;
  78. PCHAR OutName;
  79. FILE *InFile;
  80. PCHAR InName;
  81. RUN_ENTRY *RunTable;
  82. ULONG Size;
  83. ULONG Temp;
  84. if (argc != 3) {
  85. fprintf(stderr, "Usage: GENERR <input_obj> <output_h>\n");
  86. perror("GENERR");
  87. exit(1);
  88. }
  89. //
  90. // Open file for input.
  91. //
  92. InName = argv[1];
  93. InFile = fopen(InName, "rb");
  94. if (InFile == NULL) {
  95. fprintf(stderr, "GENERR: Cannot open %s for reading.\n", InName);
  96. perror("GENERR");
  97. exit(1);
  98. }
  99. CodePairs = ReadErrorTable( InFile, &TableSize );
  100. if (CodePairs == NULL) {
  101. fprintf(stderr, "CodePairs[] not found in %s.\n", InName);
  102. perror("GENERR");
  103. exit(1);
  104. }
  105. fclose(InFile);
  106. RunTable = malloc(TableSize / 4);
  107. if (RunTable == NULL) {
  108. fprintf(stderr, "Out of memory.\n");
  109. perror("GENERR");
  110. exit(1);
  111. }
  112. //
  113. // Create file for output.
  114. //
  115. OutName = argv[2];
  116. fprintf(stderr, "GENERR: Writing %s header file.\n", OutName );
  117. OutFile = fopen(OutName, "w");
  118. if (OutFile == NULL) {
  119. fprintf(stderr, "GENERR: Cannot open %s for writing.\n", OutName);
  120. perror("GENERR");
  121. exit(1);
  122. }
  123. //
  124. // Sort the code translation table.
  125. //
  126. for (Index1 = 0; Index1 < (TableSize / 4); Index1 += 2) {
  127. for (Index2 = Index1; Index2 < (TableSize / 4); Index2 += 2) {
  128. if ((ULONG)CodePairs[Index2] < (ULONG)CodePairs[Index1]) {
  129. Temp = CodePairs[Index1];
  130. CodePairs[Index1] = CodePairs[Index2];
  131. CodePairs[Index2] = Temp;
  132. Temp = CodePairs[Index1 + 1];
  133. CodePairs[Index1 + 1] = CodePairs[Index2 + 1];
  134. CodePairs[Index2 + 1] = Temp;
  135. }
  136. }
  137. }
  138. //
  139. // Output the initial structure definitions and the translation
  140. // table declaration.
  141. //
  142. fprintf(OutFile, "//\n");
  143. fprintf(OutFile, "// Define run length table entry structure type.\n");
  144. fprintf(OutFile, "//\n");
  145. fprintf(OutFile, "\n");
  146. fprintf(OutFile, "typedef struct _RUN_ENTRY {\n");
  147. fprintf(OutFile, " ULONG BaseCode;\n");
  148. fprintf(OutFile, " USHORT RunLength;\n");
  149. fprintf(OutFile, " USHORT CodeSize;\n");
  150. fprintf(OutFile, "} RUN_ENTRY, *PRUN_ENTRY;\n");
  151. fprintf(OutFile, "\n");
  152. fprintf(OutFile, "//\n");
  153. fprintf(OutFile, "// Declare translation table array.\n");
  154. fprintf(OutFile, "//\n");
  155. fprintf(OutFile, "\n");
  156. fprintf(OutFile, "CONST USHORT RtlpStatusTable[] = {");
  157. fprintf(OutFile, "\n ");
  158. //
  159. // Calculate the run length entries and output the translation table
  160. // entries.
  161. //
  162. Count = 0;
  163. Index1 = 0;
  164. Index2 = 0;
  165. do {
  166. Length = ComputeRunLength(Index1);
  167. Size = ComputeCodeSize(Index1, Length);
  168. RunTable[Index2].BaseCode = CodePairs[Index1];
  169. RunTable[Index2].RunLength = (USHORT)Length;
  170. RunTable[Index2].CodeSize = (USHORT)Size;
  171. Index2 += 1;
  172. do {
  173. if (Size == 1) {
  174. Count += 1;
  175. fprintf(OutFile,
  176. "0x%04lx, ",
  177. CodePairs[Index1 + 1]);
  178. } else {
  179. Count += 2;
  180. fprintf(OutFile,
  181. "0x%04lx, 0x%04lx, ",
  182. CodePairs[Index1 + 1] & 0xffff,
  183. (ULONG)CodePairs[Index1 + 1] >> 16);
  184. }
  185. if (Count > 6) {
  186. Count = 0;
  187. fprintf(OutFile, "\n ");
  188. }
  189. Index1 += 2;
  190. Length -= 1;
  191. } while (Length > 0);
  192. } while (Index1 < (TableSize / 4));
  193. fprintf(OutFile, "0x0};\n");
  194. //
  195. // Output the run length table declaration.
  196. //
  197. fprintf(OutFile, "\n");
  198. fprintf(OutFile, "//\n");
  199. fprintf(OutFile, "// Declare run length table array.\n");
  200. fprintf(OutFile, "//\n");
  201. fprintf(OutFile, "\n");
  202. fprintf(OutFile, "CONST RUN_ENTRY RtlpRunTable[] = {");
  203. fprintf(OutFile, "\n");
  204. //
  205. // Output the run length table entires.
  206. //
  207. for (Index1 = 0; Index1 < Index2; Index1 += 1) {
  208. fprintf(OutFile,
  209. " {0x%08lx, 0x%04lx, 0x%04lx},\n",
  210. RunTable[Index1].BaseCode,
  211. RunTable[Index1].RunLength,
  212. RunTable[Index1].CodeSize);
  213. }
  214. fprintf(OutFile, " {0x0, 0x0, 0x0}};\n");
  215. //
  216. // Close output file.
  217. //
  218. fclose(OutFile);
  219. return 0;
  220. }
  221. ULONG
  222. ComputeCodeSize (
  223. IN ULONG Start,
  224. IN ULONG Length
  225. )
  226. //
  227. // This function computes the size of the code entries required for the
  228. // specified run and returns the length in words.
  229. //
  230. {
  231. ULONG Index;
  232. for (Index = Start; Index < (Start + (Length * 2)); Index += 2) {
  233. if (((ULONG)CodePairs[Index + 1] >> 16) != 0) {
  234. return 2;
  235. }
  236. }
  237. return 1;
  238. }
  239. ULONG
  240. ComputeRunLength (
  241. IN ULONG Start
  242. )
  243. //
  244. // This function locates the next set of monotonically increasing status
  245. // codes values and returns the length of the run.
  246. //
  247. {
  248. ULONG Index;
  249. ULONG Length;
  250. Length = 1;
  251. for (Index = Start + 2; Index < (TableSize / 4); Index += 2) {
  252. if ((ULONG)CodePairs[Index] != ((ULONG)CodePairs[Index - 2] + 1)) {
  253. break;
  254. }
  255. Length += 1;
  256. }
  257. return Length;
  258. }
  259. LONG UNALIGNED *
  260. ReadErrorTable(
  261. IN FILE *InFile,
  262. OUT PULONG TableSize
  263. )
  264. {
  265. ULONG fileSize;
  266. PLONG fileBuf;
  267. LONG UNALIGNED *searchEnd;
  268. LONG pattern[4] = { 'Begi','n ge','nerr',' tbl' };
  269. LONG UNALIGNED *p;
  270. ULONG result;
  271. ULONG i;
  272. LONG UNALIGNED *tableStart;
  273. //
  274. // Get the file size and allocate a buffer large enough for it.
  275. //
  276. if (fseek( InFile, 0, SEEK_END ) == -1) {
  277. return NULL;
  278. }
  279. fileSize = ftell( InFile );
  280. if (fileSize == 0) {
  281. return NULL;
  282. }
  283. fileBuf = malloc( fileSize );
  284. if (fileBuf == NULL) {
  285. return NULL;
  286. }
  287. //
  288. // Read the file into the buffer
  289. //
  290. if (fseek( InFile, 0, SEEK_SET ) == -1) {
  291. free (fileBuf);
  292. return NULL;
  293. }
  294. result = fread( fileBuf, fileSize, 1, InFile );
  295. if (result != 1) {
  296. free (fileBuf);
  297. return NULL;
  298. }
  299. searchEnd = fileBuf + (fileSize - sizeof(pattern)) / sizeof(ULONG);
  300. //
  301. // Step through the buffer looking for our pattern.
  302. //
  303. p = fileBuf;
  304. while (p < searchEnd) {
  305. //
  306. // Match in this position?
  307. //
  308. for (i = 0; i < 4; i++) {
  309. if (*(p + i) != pattern[i]) {
  310. //
  311. // No match here
  312. //
  313. break;
  314. }
  315. }
  316. if (i == 4) {
  317. //
  318. // Found the pattern. Now find out how big the table is. We
  319. // do this by searching for the last pair, which has
  320. // 0xffffffff as its first element.
  321. //
  322. p += 4;
  323. tableStart = p;
  324. while (p < searchEnd) {
  325. if (*p == 0xffffffff) {
  326. //
  327. // Found the terminating pair.
  328. //
  329. *TableSize = (ULONG)((p - tableStart + 2) * sizeof(ULONG));
  330. return tableStart;
  331. }
  332. p += 2;
  333. }
  334. free (fileBuf);
  335. return NULL;
  336. }
  337. //
  338. // Next position
  339. //
  340. p = (PLONG)((ULONG_PTR)p + 1);
  341. }
  342. free (fileBuf);
  343. return NULL;
  344. }