433 lines
9.2 KiB
C
433 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
generr.c
|
||
|
||
Abstract:
|
||
|
||
This module contains code to generate the NT status code to DOS
|
||
error code table that is used by the runtime to translate status
|
||
codes.
|
||
|
||
Author:
|
||
|
||
David N. Cutler (davec) 2-Dec-1992
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <windows.h>
|
||
#include "stdio.h"
|
||
#include "stdarg.h"
|
||
#include "stdlib.h"
|
||
|
||
//
|
||
// Ensure that the Registry ERROR_SUCCESS error code and the
|
||
// NO_ERROR error code remain equal and zero.
|
||
//
|
||
|
||
#if ERROR_SUCCESS != 0 || NO_ERROR != 0
|
||
#error Invalid value for ERROR_SUCCESS.
|
||
#endif
|
||
|
||
//
|
||
// The following error code table contains paired entries in a singly
|
||
// dimensioned array. The first member of a paired entry is an NT status
|
||
// code and the second member is the DOS error code that it translates to.
|
||
//
|
||
// To add a value to this table simply insert the NT status/DOS error code
|
||
// pair anywhere is the table. If multiple NT status codes map to a single
|
||
// DOS error code, then insert a paired entry for each of the code pairs.
|
||
//
|
||
#ifdef i386
|
||
#pragma warning (4:4018) // lower to -W4
|
||
#endif
|
||
LONG UNALIGNED *CodePairs;
|
||
ULONG TableSize;
|
||
|
||
//
|
||
// Define run table entry structure.
|
||
//
|
||
|
||
typedef struct _RUN_ENTRY {
|
||
ULONG BaseCode;
|
||
USHORT RunLength;
|
||
USHORT CodeSize;
|
||
} RUN_ENTRY, *PRUN_ENTRY;
|
||
|
||
//
|
||
// Define forward referenced procedure prptotypes.
|
||
//
|
||
|
||
ULONG
|
||
ComputeCodeSize (
|
||
IN ULONG Start,
|
||
IN ULONG Length
|
||
);
|
||
|
||
ULONG
|
||
ComputeRunLength (
|
||
IN ULONG Start
|
||
);
|
||
|
||
LONG UNALIGNED *
|
||
ReadErrorTable(
|
||
IN FILE *InFile,
|
||
OUT PULONG TableSize
|
||
);
|
||
|
||
|
||
//
|
||
// This program generates a header file that is included by the error
|
||
// translation module in ntos/rtl.
|
||
//
|
||
|
||
int
|
||
_cdecl
|
||
main (argc, argv)
|
||
int argc;
|
||
char *argv[];
|
||
|
||
{
|
||
|
||
ULONG Count;
|
||
ULONG Index1;
|
||
ULONG Index2;
|
||
ULONG Length;
|
||
FILE *OutFile;
|
||
PCHAR OutName;
|
||
FILE *InFile;
|
||
PCHAR InName;
|
||
RUN_ENTRY *RunTable;
|
||
ULONG Size;
|
||
ULONG Temp;
|
||
|
||
if (argc != 3) {
|
||
fprintf(stderr, "Usage: GENERR <input_obj> <output_h>\n");
|
||
perror("GENERR");
|
||
exit(1);
|
||
}
|
||
|
||
//
|
||
// Open file for input.
|
||
//
|
||
|
||
InName = argv[1];
|
||
InFile = fopen(InName, "rb");
|
||
if (InFile == NULL) {
|
||
fprintf(stderr, "GENERR: Cannot open %s for reading.\n", InName);
|
||
perror("GENERR");
|
||
exit(1);
|
||
}
|
||
|
||
CodePairs = ReadErrorTable( InFile, &TableSize );
|
||
if (CodePairs == NULL) {
|
||
fprintf(stderr, "CodePairs[] not found in %s.\n", InName);
|
||
perror("GENERR");
|
||
exit(1);
|
||
}
|
||
|
||
fclose(InFile);
|
||
|
||
RunTable = malloc(TableSize / 4);
|
||
if (RunTable == NULL) {
|
||
fprintf(stderr, "Out of memory.\n");
|
||
perror("GENERR");
|
||
exit(1);
|
||
}
|
||
|
||
//
|
||
// Create file for output.
|
||
//
|
||
|
||
OutName = argv[2];
|
||
fprintf(stderr, "GENERR: Writing %s header file.\n", OutName );
|
||
OutFile = fopen(OutName, "w");
|
||
if (OutFile == NULL) {
|
||
fprintf(stderr, "GENERR: Cannot open %s for writing.\n", OutName);
|
||
perror("GENERR");
|
||
exit(1);
|
||
}
|
||
|
||
//
|
||
// Sort the code translation table.
|
||
//
|
||
|
||
for (Index1 = 0; Index1 < (TableSize / 4); Index1 += 2) {
|
||
for (Index2 = Index1; Index2 < (TableSize / 4); Index2 += 2) {
|
||
if ((ULONG)CodePairs[Index2] < (ULONG)CodePairs[Index1]) {
|
||
Temp = CodePairs[Index1];
|
||
CodePairs[Index1] = CodePairs[Index2];
|
||
CodePairs[Index2] = Temp;
|
||
Temp = CodePairs[Index1 + 1];
|
||
CodePairs[Index1 + 1] = CodePairs[Index2 + 1];
|
||
CodePairs[Index2 + 1] = Temp;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Output the initial structure definitions and the translation
|
||
// table declaration.
|
||
//
|
||
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "// Define run length table entry structure type.\n");
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "\n");
|
||
fprintf(OutFile, "typedef struct _RUN_ENTRY {\n");
|
||
fprintf(OutFile, " ULONG BaseCode;\n");
|
||
fprintf(OutFile, " USHORT RunLength;\n");
|
||
fprintf(OutFile, " USHORT CodeSize;\n");
|
||
fprintf(OutFile, "} RUN_ENTRY, *PRUN_ENTRY;\n");
|
||
|
||
fprintf(OutFile, "\n");
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "// Declare translation table array.\n");
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "\n");
|
||
fprintf(OutFile, "CONST USHORT RtlpStatusTable[] = {");
|
||
fprintf(OutFile, "\n ");
|
||
|
||
//
|
||
// Calculate the run length entries and output the translation table
|
||
// entries.
|
||
//
|
||
|
||
Count = 0;
|
||
Index1 = 0;
|
||
Index2 = 0;
|
||
do {
|
||
Length = ComputeRunLength(Index1);
|
||
Size = ComputeCodeSize(Index1, Length);
|
||
RunTable[Index2].BaseCode = CodePairs[Index1];
|
||
RunTable[Index2].RunLength = (USHORT)Length;
|
||
RunTable[Index2].CodeSize = (USHORT)Size;
|
||
Index2 += 1;
|
||
do {
|
||
if (Size == 1) {
|
||
Count += 1;
|
||
fprintf(OutFile,
|
||
"0x%04lx, ",
|
||
CodePairs[Index1 + 1]);
|
||
|
||
} else {
|
||
Count += 2;
|
||
fprintf(OutFile,
|
||
"0x%04lx, 0x%04lx, ",
|
||
CodePairs[Index1 + 1] & 0xffff,
|
||
(ULONG)CodePairs[Index1 + 1] >> 16);
|
||
}
|
||
|
||
if (Count > 6) {
|
||
Count = 0;
|
||
fprintf(OutFile, "\n ");
|
||
}
|
||
|
||
Index1 += 2;
|
||
Length -= 1;
|
||
} while (Length > 0);
|
||
} while (Index1 < (TableSize / 4));
|
||
|
||
fprintf(OutFile, "0x0};\n");
|
||
|
||
//
|
||
// Output the run length table declaration.
|
||
//
|
||
|
||
fprintf(OutFile, "\n");
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "// Declare run length table array.\n");
|
||
fprintf(OutFile, "//\n");
|
||
fprintf(OutFile, "\n");
|
||
fprintf(OutFile, "CONST RUN_ENTRY RtlpRunTable[] = {");
|
||
fprintf(OutFile, "\n");
|
||
|
||
//
|
||
// Output the run length table entires.
|
||
//
|
||
|
||
for (Index1 = 0; Index1 < Index2; Index1 += 1) {
|
||
fprintf(OutFile,
|
||
" {0x%08lx, 0x%04lx, 0x%04lx},\n",
|
||
RunTable[Index1].BaseCode,
|
||
RunTable[Index1].RunLength,
|
||
RunTable[Index1].CodeSize);
|
||
}
|
||
|
||
fprintf(OutFile, " {0x0, 0x0, 0x0}};\n");
|
||
|
||
//
|
||
// Close output file.
|
||
//
|
||
|
||
fclose(OutFile);
|
||
return 0;
|
||
}
|
||
|
||
ULONG
|
||
ComputeCodeSize (
|
||
IN ULONG Start,
|
||
IN ULONG Length
|
||
)
|
||
|
||
//
|
||
// This function computes the size of the code entries required for the
|
||
// specified run and returns the length in words.
|
||
//
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
|
||
for (Index = Start; Index < (Start + (Length * 2)); Index += 2) {
|
||
if (((ULONG)CodePairs[Index + 1] >> 16) != 0) {
|
||
return 2;
|
||
}
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
ULONG
|
||
ComputeRunLength (
|
||
IN ULONG Start
|
||
)
|
||
|
||
//
|
||
// This function locates the next set of monotonically increasing status
|
||
// codes values and returns the length of the run.
|
||
//
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
ULONG Length;
|
||
|
||
Length = 1;
|
||
for (Index = Start + 2; Index < (TableSize / 4); Index += 2) {
|
||
if ((ULONG)CodePairs[Index] != ((ULONG)CodePairs[Index - 2] + 1)) {
|
||
break;
|
||
}
|
||
|
||
Length += 1;
|
||
}
|
||
|
||
return Length;
|
||
}
|
||
|
||
LONG UNALIGNED *
|
||
ReadErrorTable(
|
||
IN FILE *InFile,
|
||
OUT PULONG TableSize
|
||
)
|
||
{
|
||
ULONG fileSize;
|
||
PLONG fileBuf;
|
||
LONG UNALIGNED *searchEnd;
|
||
LONG pattern[4] = { 'Begi','n ge','nerr',' tbl' };
|
||
LONG UNALIGNED *p;
|
||
ULONG result;
|
||
ULONG i;
|
||
LONG UNALIGNED *tableStart;
|
||
|
||
//
|
||
// Get the file size and allocate a buffer large enough for it.
|
||
//
|
||
|
||
if (fseek( InFile, 0, SEEK_END ) == -1) {
|
||
return NULL;
|
||
}
|
||
fileSize = ftell( InFile );
|
||
if (fileSize == 0) {
|
||
return NULL;
|
||
}
|
||
|
||
fileBuf = malloc( fileSize );
|
||
if (fileBuf == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Read the file into the buffer
|
||
//
|
||
|
||
if (fseek( InFile, 0, SEEK_SET ) == -1) {
|
||
free (fileBuf);
|
||
return NULL;
|
||
}
|
||
result = fread( fileBuf, fileSize, 1, InFile );
|
||
if (result != 1) {
|
||
free (fileBuf);
|
||
return NULL;
|
||
}
|
||
searchEnd = fileBuf + (fileSize - sizeof(pattern)) / sizeof(ULONG);
|
||
|
||
//
|
||
// Step through the buffer looking for our pattern.
|
||
//
|
||
|
||
p = fileBuf;
|
||
while (p < searchEnd) {
|
||
|
||
//
|
||
// Match in this position?
|
||
//
|
||
|
||
for (i = 0; i < 4; i++) {
|
||
|
||
if (*(p + i) != pattern[i]) {
|
||
|
||
//
|
||
// No match here
|
||
//
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == 4) {
|
||
|
||
//
|
||
// Found the pattern. Now find out how big the table is. We
|
||
// do this by searching for the last pair, which has
|
||
// 0xffffffff as its first element.
|
||
//
|
||
|
||
p += 4;
|
||
|
||
tableStart = p;
|
||
while (p < searchEnd) {
|
||
|
||
if (*p == 0xffffffff) {
|
||
|
||
//
|
||
// Found the terminating pair.
|
||
//
|
||
|
||
*TableSize = (ULONG)((p - tableStart + 2) * sizeof(ULONG));
|
||
return tableStart;
|
||
}
|
||
|
||
p += 2;
|
||
}
|
||
|
||
free (fileBuf);
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Next position
|
||
//
|
||
|
||
p = (PLONG)((ULONG_PTR)p + 1);
|
||
}
|
||
|
||
free (fileBuf);
|
||
return NULL;
|
||
}
|