GetDbgType info
This is a pseudo class demo, another taste of OOP while I
get the next generation of OOPz ready.
Wazzup...
Creates a single object named gdt through which all public
functions and variables can be accessed. No inheritance,
no "make", no "create" and no "new", but this shows the basic
idea of simple OOP in C.
Here are the tradeoffs compared to a message passing OOP
system such as the one used in the Win32 API.
this that
calls through func ptrs "interprets" messages
all calls equally fast msgs after first few are slow
even if threaded.
can be superclassed can only be superclassed if
the interpreter itself is
a function pointer variable
no global inits/checks can do inits and checks for
all methods before case-switches
harder to write easier to write
better type checking worse
any return type is ok return types must be cast or
have variable's addr on stack
Let us begin...
// GetDbgType.h
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
/*
///////////////////////////////////////////////////////////////
// Functions
gdt.InitOnce() fully automatic, usually never called
gdt.CountTypes() counts the number of debug type dirs
gdt.HasType(TypeId) returns t/f; TypeId should be
IMAGE_DEBUG_TYPE_<NAME>
gdt.FindType(TypeId) returns index # 1-based; see note above
///////////////////////////////////////////////////////////////
// Variables
int nDirs; same as CountTypes, but must be initialized!
misc stuff...
*/
typedef struct _gdt_t
{
// public initialized
int is_inited;
void(*InitOnce)(void);
int(*CountTypes)(void); // not a msg, no case switch
int(*HasType)(int arg); // not a msg, no case switch
int(*GetTypeId)(int arg); // not a msg, no case switch
int (*FindType)(int arg); // not a msg, no case switch
// public/protected uninitialized variables
int nDirs;
int sizeDirs; // 28 bytes per dir
PIMAGE_DOS_HEADER pehdr; // 'MZ'...
PIMAGE_NT_HEADERS pnhdr; // 'PE'...
PIMAGE_DATA_DIRECTORY pde; // list in lo mem
PIMAGE_DEBUG_DIRECTORY pdd; // addr in .data
PIMAGE_DEBUG_DIRECTORY pddEnd; // total size in .data
}gdt_t;
///////////////////////////////////////////////////////////////
// the public interface
extern gdt_t gdt; // "create" one that we can find
// GetDbgType.c
///////////////////////////////////////////////////////////////
// hidden nutz and boltz
__declspec(naked)
static void GDT_Noop(void) // func to turn InitOnce() off
{
__asm ret
}
static void GDT_InitOnce(void)
{
if(gdt.is_inited != (int)&gdt.is_inited)
{
gdt.InitOnce = (void*)GDT_Noop; // faster bypass
gdt.pehdr = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
gdt.pnhdr = (PIMAGE_NT_HEADERS)((PBYTE)gdt.pehdr + gdt.pehdr->e_lfanew);
gdt.pde = &gdt.pnhdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
if (gdt.pde->Size != 0)
{
gdt.pdd = (PIMAGE_DEBUG_DIRECTORY)((PBYTE)gdt.pehdr + gdt.pde->VirtualAddress);
gdt.pddEnd = (PIMAGE_DEBUG_DIRECTORY)((PBYTE)gdt.pdd + gdt.pde->Size);
gdt.sizeDirs = ((PCHAR)gdt.pddEnd-(PCHAR)gdt.pdd);
gdt.nDirs=gdt.sizeDirs/28;
}
gdt.is_inited = (int)&gdt.is_inited; // a 'self' pointer
}
}
static int GDT_CountTypes(void)
{
gdt.InitOnce();
if (gdt.pde->Size == 0) return 0;
return gdt.nDirs;
}
static int GDT_FindType(int arg)
{
gdt.InitOnce();
if (gdt.pde->Size == 0) return 0;
int cvfound = 0;
for (int i=0; i<gdt.nDirs; i++)
{
if (gdt.GetTypeId(i) == arg)
{
cvfound=i+1; // index is 1-based
break;
}
}
return cvfound;
}
static int GDT_HasType(int arg)
{
return GDT_FindType(arg)? 1: 0; // only returns t/f
}
static int GDT_GetTypeId(int arg)
{
gdt.InitOnce();
if (gdt.pde->Size == 0) return 0;
if (arg >= gdt.nDirs) return 0;
return gdt.pdd[arg].Type;
}
///////////////////////////////////////////////////////////////
// compile-time initialization for single obj of class
gdt_t gdt=
{
0, // inited -- will equal &gdt later
GDT_InitOnce, // function list
GDT_CountTypes, // must match order
GDT_HasType, // declared in typedef
GDT_GetTypeId, // ...
GDT_FindType
};
// main.c
///////////////////////////////////////////////////////////////
// tester..
#include <stdlib.h> // malloc
int WinPrintf(char* fmt, ...)
{
int rcode; char* tmp=malloc(4096);
va_list args; va_start(args, fmt);
vsprintf(tmp, fmt, args); va_end(args);
rcode = MessageBox(NULL, tmp, "WinPrintf -- Message", MB_OK);
free (tmp); return rcode;
}
int main(void)
{
int nTypes;
nTypes=gdt.CountTypes();
WinPrintf("There are %d types of debug info in the file.\n", nTypes);
// search for codeview
if(gdt.HasType(IMAGE_DEBUG_TYPE_CODEVIEW))
{
WinPrintf("The file does have CodeView debug info "
"in directory #%d\n", gdt.FindType(IMAGE_DEBUG_TYPE_CODEVIEW));
}
else
{
WinPrintf("No CodeView info..\n");
}
return 0;
}
.