563 lines
12 KiB
C
563 lines
12 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
genlvl.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module implements a program which generates the debug print filter
|
||
|
component id enumeration and the system filter table that are used by
|
||
|
various components in the system to dynamically filter debug print
|
||
|
output.
|
||
|
|
||
|
Two files are generated by this program. A header file that declares an
|
||
|
enumeration of debug print filter component id, and a source file that
|
||
|
declares and initializes the individual component filter variables.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
David N. Cutler (davec) 7-Jan-2000
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User mode.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <malloc.h>
|
||
|
|
||
|
//
|
||
|
// Increment this everytime a change to this file is made.
|
||
|
//
|
||
|
|
||
|
#define GENLVL_VERSION "1.0"
|
||
|
|
||
|
//
|
||
|
// Define component name table.
|
||
|
//
|
||
|
|
||
|
#define MAXIMUM_NAMES 4096
|
||
|
|
||
|
PCHAR ComponentNameTable[MAXIMUM_NAMES + 1] = {NULL};
|
||
|
|
||
|
//
|
||
|
// Define forward referenced prototypes.
|
||
|
//
|
||
|
|
||
|
ULONG
|
||
|
InsertName(
|
||
|
IN PCHAR NewName
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
GenerateCmHeaderFile(
|
||
|
FILE *OutputFile
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
GenerateCmSourceFile(
|
||
|
FILE *OutputFile
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
GenerateKdSourceFile(
|
||
|
FILE *OutputFile
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
GenerateNtHeaderFile(
|
||
|
FILE *OutputFile
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Main program.
|
||
|
//
|
||
|
|
||
|
int __cdecl
|
||
|
main(
|
||
|
int argc,
|
||
|
char *argv[]
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
CHAR Buffer[132];
|
||
|
CHAR CmHeaderFileName[128];
|
||
|
FILE *CmHeaderFile;
|
||
|
CHAR CmSourceFileName[128];
|
||
|
FILE *CmSourceFile;
|
||
|
ULONG Count;
|
||
|
PCHAR ComponentDirectory;
|
||
|
FILE *ComponentFile = NULL;
|
||
|
CHAR ComponentFileName[128];
|
||
|
int ExitCode = 0;
|
||
|
CHAR NtHeaderFileName[128];
|
||
|
FILE *NtHeaderFile = NULL;
|
||
|
FILE *KdSourceFile = NULL;
|
||
|
CHAR KdSourceFileName[128];
|
||
|
PCHAR TargetDirectory;
|
||
|
|
||
|
//
|
||
|
// Parse arguments.
|
||
|
//
|
||
|
|
||
|
if (argc == 2 && (!strcmp(argv[1],"-?") || !strcmp(argv[1],"/?"))) {
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine name of target directory for generated files. This requires
|
||
|
// the -t switch be specified and that the argument after the switch is
|
||
|
// the target directory name. If no -t switch is specfied, then default
|
||
|
// to ".".
|
||
|
//
|
||
|
|
||
|
if (argc >= 3 && !_stricmp(argv[1],"-t")) {
|
||
|
TargetDirectory = argv[2];
|
||
|
argc -= 2;
|
||
|
argv += 2;
|
||
|
|
||
|
} else {
|
||
|
TargetDirectory = ".";
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine name of the component id directory. This is the last input
|
||
|
// command line argument. If a component id directory is not specified,
|
||
|
// then default to ".".
|
||
|
//
|
||
|
|
||
|
if (argc >= 2) {
|
||
|
ComponentDirectory = argv[1];
|
||
|
argc -= 1;
|
||
|
argv += 1;
|
||
|
|
||
|
} else {
|
||
|
ComponentDirectory = ".";
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// There should be no more arguments.
|
||
|
//
|
||
|
|
||
|
if (argc != 1) {
|
||
|
printf("\n Manformed command line\n");
|
||
|
ExitCode = 1;
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the component id input file.
|
||
|
//
|
||
|
|
||
|
sprintf(&ComponentFileName[0], "%s\\componentid.tab", ComponentDirectory);
|
||
|
ComponentFile = fopen(&ComponentFileName[0], "r");
|
||
|
if (!ComponentFile) {
|
||
|
printf("\n Unable to open component id file %s\n", &ComponentFileName[0]);
|
||
|
ExitCode = 1;
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the kernel debugger source output file.
|
||
|
//
|
||
|
|
||
|
sprintf(&KdSourceFileName[0], "%s\\dpfilter.c", TargetDirectory);
|
||
|
KdSourceFile = fopen(&KdSourceFileName[0], "w");
|
||
|
if (!KdSourceFile) {
|
||
|
printf("\n Unable to open filter source file %s\n", &KdSourceFileName[0]);
|
||
|
ExitCode = 1;
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the configuration manager header output file.
|
||
|
//
|
||
|
|
||
|
sprintf(&CmHeaderFileName[0], "%s\\dpfiltercm.h", TargetDirectory);
|
||
|
CmHeaderFile = fopen(&CmHeaderFileName[0], "w");
|
||
|
if (!CmHeaderFile) {
|
||
|
printf("\n Unable to open filter source file %s\n", &CmHeaderFileName[0]);
|
||
|
ExitCode = 1;
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the configuration manager source output file.
|
||
|
//
|
||
|
|
||
|
sprintf(&CmSourceFileName[0], "%s\\dpfiltercm.c", TargetDirectory);
|
||
|
CmSourceFile = fopen(&CmSourceFileName[0], "w");
|
||
|
if (!CmSourceFile) {
|
||
|
printf("\n Unable to open filter source file %s\n", &CmSourceFileName[0]);
|
||
|
ExitCode = 1;
|
||
|
goto PrintUsage;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open the ntrtl.w append header output file.
|
||
|
//
|
||
|
|
||
|
sprintf(&NtHeaderFileName[0], "%s\\dpfilter.h", TargetDirectory);
|
||
|
NtHeaderFile = fopen(&NtHeaderFileName[0], "w");
|
||
|
if (!NtHeaderFile) {
|
||
|
printf("\n Unable to open filter header file %s\n", &NtHeaderFileName[0]);
|
||
|
ExitCode = 1;
|
||
|
PrintUsage:
|
||
|
printf("GENLVL: Debug Print Filter Generator. Version " GENLVL_VERSION "\n");
|
||
|
printf(" Usage: genlvl [-t target directory] [componentid.tab directory]\n");
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read component id table.
|
||
|
//
|
||
|
|
||
|
Count = 0;
|
||
|
while (fgets(&Buffer[0], 132, ComponentFile) != NULL) {
|
||
|
|
||
|
//
|
||
|
// If the the line is null, begins with a blank, or begins with
|
||
|
// a semicolon, then skip it.
|
||
|
//
|
||
|
|
||
|
if ((Buffer[0] == 0) ||
|
||
|
(Buffer[0] == '\n') ||
|
||
|
(Buffer[0] == ' ') ||
|
||
|
(Buffer[0] == ';')) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Insert the component name in the component name table.
|
||
|
//
|
||
|
|
||
|
Count += InsertName(&Buffer[0]);
|
||
|
if (Count >= MAXIMUM_NAMES) {
|
||
|
printf(" Component name table overflow at name %s\n", &Buffer[0]);
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check to determine if an error of eof was encountered.
|
||
|
//
|
||
|
|
||
|
if (feof(ComponentFile) == 0) {
|
||
|
printf(" Error encountered while reading component name file\n");
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate configuration manager header file.
|
||
|
//
|
||
|
|
||
|
if (GenerateCmHeaderFile(CmHeaderFile) == 0) {
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate configuration manager source file.
|
||
|
//
|
||
|
|
||
|
if (GenerateCmSourceFile(CmSourceFile) == 0) {
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate kernel debugger source file.
|
||
|
//
|
||
|
|
||
|
if (GenerateKdSourceFile(KdSourceFile) == 0) {
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Generate ntrtl.w append header file.
|
||
|
//
|
||
|
|
||
|
if (GenerateNtHeaderFile(NtHeaderFile) == 0) {
|
||
|
ExitCode = 1;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Common program exit.
|
||
|
//
|
||
|
// Close any files that are open and exit with appropriate exit code.
|
||
|
//
|
||
|
|
||
|
Exit:
|
||
|
if (CmHeaderFile != NULL) {
|
||
|
fclose(CmHeaderFile);
|
||
|
}
|
||
|
|
||
|
if (CmSourceFile != NULL) {
|
||
|
fclose(CmSourceFile);
|
||
|
}
|
||
|
|
||
|
if (ComponentFile != NULL) {
|
||
|
fclose(ComponentFile);
|
||
|
}
|
||
|
|
||
|
if (KdSourceFile != NULL) {
|
||
|
fclose(KdSourceFile);
|
||
|
}
|
||
|
|
||
|
if (NtHeaderFile != NULL) {
|
||
|
fclose(NtHeaderFile);
|
||
|
}
|
||
|
|
||
|
return ExitCode;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
GenerateCmHeaderFile(
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
ULONG Count;
|
||
|
PCHAR Name;
|
||
|
|
||
|
//
|
||
|
// Generate opening comments.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "// External component filter level definitions.\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
|
||
|
//
|
||
|
// Output all the component variable names.
|
||
|
//
|
||
|
|
||
|
Count = 0;
|
||
|
while ((Name = ComponentNameTable[Count]) != NULL) {
|
||
|
fprintf(OutputFile, "extern ULONG Kd_%s_Mask;\n", Name);
|
||
|
Count += 1;
|
||
|
}
|
||
|
|
||
|
fprintf(OutputFile, "\n");
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
GenerateCmSourceFile(
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
ULONG Count;
|
||
|
PCHAR Name;
|
||
|
|
||
|
//
|
||
|
// Generate opening comments.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "// Debug print filter level initialization.\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
|
||
|
//
|
||
|
// Output all the component variable names.
|
||
|
//
|
||
|
|
||
|
Count = 0;
|
||
|
while ((Name = ComponentNameTable[Count]) != NULL) {
|
||
|
fprintf(OutputFile, " { L\"Session Manager\\\\Debug Print Filter\",\n");
|
||
|
fprintf(OutputFile, " L\"%s\",\n", Name);
|
||
|
fprintf(OutputFile, " &Kd_%s_Mask,\n", Name);
|
||
|
fprintf(OutputFile, " NULL,\n");
|
||
|
fprintf(OutputFile, " NULL\n");
|
||
|
fprintf(OutputFile, " },\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
Count += 1;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
GenerateKdSourceFile(
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
ULONG Count;
|
||
|
PCHAR Name;
|
||
|
|
||
|
//
|
||
|
// Generate opening comments and typedef.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "// Component filter levels.\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
|
||
|
//
|
||
|
// Output all the component variable names with initialization.
|
||
|
//
|
||
|
|
||
|
Count = 0;
|
||
|
while ((Name = ComponentNameTable[Count]) != NULL) {
|
||
|
fprintf(OutputFile, "ULONG Kd_%s_Mask = 0;\n", Name);
|
||
|
Count += 1;
|
||
|
}
|
||
|
|
||
|
fprintf(OutputFile, "ULONG Kd_ENDOFTABLE_Mask = 0;\n");
|
||
|
|
||
|
//
|
||
|
// Output the initialization of the component variable table.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, "\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "// Component debug print filter table.\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
fprintf(OutputFile, "PULONG KdComponentTable[] = {\n");
|
||
|
Count = 0;
|
||
|
while ((Name = ComponentNameTable[Count]) != NULL) {
|
||
|
fprintf(OutputFile, " &Kd_%s_Mask,\n", Name);
|
||
|
Count += 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Output one final dummy entry and close the initialization.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, " &Kd_ENDOFTABLE_Mask\n");
|
||
|
fprintf(OutputFile, "};\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
ULONG
|
||
|
GenerateNtHeaderFile(
|
||
|
FILE *OutputFile
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
ULONG Count;
|
||
|
PCHAR Name;
|
||
|
|
||
|
//
|
||
|
// Generate opening comments and typedef.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "// Component name filter id enumeration and levels.\n");
|
||
|
fprintf(OutputFile, "//\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
fprintf(OutputFile, "#define DPFLTR_ERROR_LEVEL 0\n");
|
||
|
fprintf(OutputFile, "#define DPFLTR_WARNING_LEVEL 1\n");
|
||
|
fprintf(OutputFile, "#define DPFLTR_TRACE_LEVEL 2\n");
|
||
|
fprintf(OutputFile, "#define DPFLTR_INFO_LEVEL 3\n");
|
||
|
fprintf(OutputFile, "#define DPFLTR_MASK 0x80000000\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
fprintf(OutputFile, "typedef enum _DPFLTR_TYPE {\n");
|
||
|
|
||
|
//
|
||
|
// Output all the enumerations.
|
||
|
//
|
||
|
|
||
|
Count = 0;
|
||
|
while ((Name = ComponentNameTable[Count]) != NULL) {
|
||
|
fprintf(OutputFile, " DPFLTR_%s_ID = %d,\n", Name, Count);
|
||
|
Count += 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Output one final dummy entry and close the enumeration.
|
||
|
//
|
||
|
|
||
|
fprintf(OutputFile, " DPFLTR_ENDOFTABLE_ID\n");
|
||
|
fprintf(OutputFile, "} DPFLTR_TYPE;\n");
|
||
|
fprintf(OutputFile, "\n");
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Insert component name in component name table.
|
||
|
//
|
||
|
|
||
|
ULONG
|
||
|
InsertName(
|
||
|
IN PCHAR NewName
|
||
|
)
|
||
|
|
||
|
{
|
||
|
|
||
|
ULONG Index;
|
||
|
ULONG Length;
|
||
|
PCHAR OldName;
|
||
|
|
||
|
//
|
||
|
// Convert the input string to upper case.
|
||
|
//
|
||
|
|
||
|
Length = 0;
|
||
|
while (NewName[Length] != 0) {
|
||
|
if (NewName[Length] == '\n') {
|
||
|
NewName[Length] = 0;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NewName[Length] = (CHAR)toupper(NewName[Length]);
|
||
|
Length += 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Search for a duplicate name in the component name table.
|
||
|
//
|
||
|
|
||
|
Index = 0;
|
||
|
while ((OldName = ComponentNameTable[Index]) != NULL) {
|
||
|
if (strcmp(OldName, NewName) == 0) {
|
||
|
printf(" Duplicate component name %s ignored.\n", NewName);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
Index += 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate a new table entry, copy the new name to the entry, and
|
||
|
// insert the new entry in the table.
|
||
|
//
|
||
|
|
||
|
OldName = malloc(Length + 1);
|
||
|
if (!OldName) {
|
||
|
printf("Out of memory\n");
|
||
|
return 0;
|
||
|
}
|
||
|
strcpy(OldName, NewName);
|
||
|
ComponentNameTable[Index] = OldName;
|
||
|
ComponentNameTable[Index + 1] = NULL;
|
||
|
return 1;
|
||
|
}
|