class PERsrcTbl
{
PERsrcTbl // Constructor
~PERsrcTbl // Destructor
GetNextResourceType // Enumeration
GetResourceTypeByName
GetResourceTypeById
}
class PERsrcType
{
~PERsrcType // Destructor
GetNextResourceInst // Enumeration
GetResourceInstByName
GetResourceInstById
Id // Get Id of resource
IsNamed // Is this a named resource?
Name // Get name of resource
};
class PERsrcInst
{
~PERsrcInst // Destructor
GetData // Get pointer to resource instance data
Id // Get Id of resource
IsNamed // Is this a named resource?
Name // Get name of resource
Size // Get size of resource instance, in btyes
CodePage // Get code page for this resource instance
};
Figure 3 DlgDump
DlgDump.CPP
//==========================================
// Matt Pietrek
// Microsoft Systems Journal, January 1998
// Program: DlgDump.EXE
// FILE: DlgDump.CPP
//==========================================
#include <windows.h>
#include <stdio.h>
#include "MSJPERsrc.h"
BOOL DumpDialog( PVOID pDlg ); // In DlgDumpHelper.H
//=============================== Global Variables ============================
char g_szHelpText[] =
"Dialog Dumper - Matt Pietrek, 1998 for MSJ\n"
"Syntax: DlgDump <Executable Name>\n";
PSTR g_pszFile = 0;
//==================================== Code ===================================
BOOL DumpAllDialogs( PSTR pszFilename )
{
// initial hook up to the resources
PERsrcTbl rsrcTbl( pszFilename );
// Locate the Dialog resources
PPERsrcType pDlgs = rsrcTbl.GetResourceTypeById( (WORD)RT_DIALOG );
if ( !pDlgs ) // No dialogs? We're done!
return FALSE;
PPERsrcInst pDlgInst = 0; // Begin enumeration by passing 0
// Enumerate through each dialog instance...
while ( pDlgInst = pDlgs->GetNextResourceInst( pDlgInst ) )
{
// Get a pointer to the raw dialog template
PVOID pDlgData = pDlgInst->GetData();
if ( pDlgInst )
{
printf( "====================\n" );
if ( pDlgInst->IsNamed() ) // Does the dialog have a name? Get it!
{
char szDlgName[256];
pDlgInst->Name( szDlgName, sizeof(szDlgName) );
printf( "Dialog name: %s\n", szDlgName );
}
else // Dialog is identified by an integer ID
printf( "Dialog id: %u\n", pDlgInst->Id() );
DumpDialog( pDlgData ); // The real work. In DlgDumpHelper.CPP
// We don't have to explicitly delete pDlgInst because the
// enumeration method does this for us
printf( "\n" );
}
}
delete pDlgs; // Delete pointer to the dialog collection
return TRUE;
}
BOOL ProcessCommandLine( int argc, char *argv[] )
{
if ( argc != 2 ) // One parameter (the filename) should be passed
return FALSE;
g_pszFile = argv[1]; // First real argument is first filename
return TRUE;
}
int main( int argc, char * argv[] )
{
if ( !ProcessCommandLine( argc, argv ) )
{
printf( g_szHelpText );
return 0;
}
DumpAllDialogs( g_pszFile );
return 0;
}
Figure 4 DlgDumpHelper.CPP
//==========================================
// Matt Pietrek
// Microsoft Systems Journal, January 1998
// Program: DlgDump.EXE
// FILE: DlgDumpHelper.CPP
//==========================================
#include <windows.h>
#include <stdio.h>
// Data and macro definitions to make bitfield/flag decoding easier
typedef struct
{
DWORD flag;
PSTR name;
} DWORD_FLAG_DESCRIPTIONS;
#define FLAG_AS_STRING( f ) { f, #f },
#define WS_STYLE_FLAGS \
FLAG_AS_STRING( WS_POPUP ) \
FLAG_AS_STRING( WS_CHILD ) \
FLAG_AS_STRING( WS_MINIMIZE ) \
FLAG_AS_STRING( WS_VISIBLE ) \
FLAG_AS_STRING( WS_DISABLED ) \
FLAG_AS_STRING( WS_CLIPSIBLINGS ) \
FLAG_AS_STRING( WS_CLIPCHILDREN ) \
FLAG_AS_STRING( WS_MAXIMIZE ) \
FLAG_AS_STRING( WS_BORDER ) \
FLAG_AS_STRING( WS_DLGFRAME ) \
FLAG_AS_STRING( WS_VSCROLL ) \
FLAG_AS_STRING( WS_HSCROLL ) \
FLAG_AS_STRING( WS_SYSMENU ) \
FLAG_AS_STRING( WS_THICKFRAME ) \
FLAG_AS_STRING( WS_GROUP ) \
FLAG_AS_STRING( WS_TABSTOP ) \
DWORD_FLAG_DESCRIPTIONS WndStyleFlags[] = // Style flags common to all wnds
{
WS_STYLE_FLAGS
};
#define NUMBER_WND_STYLE_FLAGS \
(sizeof(WndStyleFlags) / sizeof(WndStyleFlags[0]))
DWORD_FLAG_DESCRIPTIONS DlgStyleFlags[] = // All style flags used by dialogs
{
WS_STYLE_FLAGS
FLAG_AS_STRING( DS_ABSALIGN )
FLAG_AS_STRING( DS_SYSMODAL )
FLAG_AS_STRING( DS_LOCALEDIT )
FLAG_AS_STRING( DS_SETFONT )
FLAG_AS_STRING( DS_MODALFRAME )
FLAG_AS_STRING( DS_NOIDLEMSG )
FLAG_AS_STRING( DS_SETFOREGROUND )
FLAG_AS_STRING( DS_3DLOOK )
FLAG_AS_STRING( DS_FIXEDSYS )
FLAG_AS_STRING( DS_NOFAILCREATE )
FLAG_AS_STRING( DS_CONTROL )
FLAG_AS_STRING( DS_CENTER )
FLAG_AS_STRING( DS_CENTERMOUSE )
FLAG_AS_STRING( DS_CONTEXTHELP )
};
#define NUMBER_DLG_STYLE_FLAGS \
(sizeof(DlgStyleFlags) / sizeof(DlgStyleFlags[0]))
// Helper function that takes a set of flags, and constructs a string that
// contains the names of all the flags that are set
void GetBitfieldsAsString( DWORD dwStyle, DWORD_FLAG_DESCRIPTIONS *,
unsigned maxFlags, PSTR pszBuffer, unsigned cbLen )
{
if ( !cbLen || !pszBuffer )
return;
pszBuffer[0] = 0; // Start it out null terminated
BOOL fAtLeastOneFlag = FALSE;
for ( unsigned i = 0; i < maxFlags; i++ )
{
if ( dwStyle & DlgStyleFlags[i].flag )
{
if ( fAtLeastOneFlag )
pszBuffer += sprintf(pszBuffer, " | %s",DlgStyleFlags[i].name);
else
{
fAtLeastOneFlag = TRUE;
pszBuffer += sprintf( pszBuffer, "%s", DlgStyleFlags[i].name );
}
}
}
}
// Helper function that reads a Unicode string out of a dialog template,
// and stores the results in an ANSI (8-bit) buffer. Returns a pointer to
// the byte immediately following the string.
PWORD GetDlgEmbeddedString( PWORD pwsz, PSTR pszBuffer, unsigned cbLen )
{
if ( !cbLen || !pszBuffer )
return FALSE;
*pszBuffer = 0;
while ( *pwsz ) // Loop through all chars in the unicode string
{
if ( cbLen ) // While there's room, copy to the output buffer
*pszBuffer++ = (BYTE)*pwsz;
pwsz++;
}
// Null terminate the output string
if ( cbLen )
*pszBuffer = 0; // Space was left over
else
*(pszBuffer-1) = 0; // Wrote to the entire buffer. Back up and
// null out the last character
return pwsz+1; // return next WORD past the null terminator
}
PSTR GetDlgItemClassIdAsString( WORD classId )
{
switch ( classId )
{
case 0x0080: return "Button";
case 0x0081: return "Edit";
case 0x0082: return "Static";
case 0x0083: return "List box";
case 0x0084: return "Scroll bar";
case 0x0085: return "Combo box";
default: return "unknown";
}
}
// Input: a ptr. Output: the ptr aligned to a DWORD.
#define ALIGN_DWORD( type, p ) ( (type)(((DWORD)p+3) & ~3 ))
// Displays all the fields of a dialog control. Returns the next address
// following the control's data.
LPDLGITEMTEMPLATE DumpDialogItem( LPDLGITEMTEMPLATE pDlgItemTemplate )
{
char szDlgItemStyles[512];
// Emits "warning" if the WS_VISIBLE flag isn't set
if ( 0 == (pDlgItemTemplate->style & WS_VISIBLE) )
printf( " *** Dialog item not visible ***\n" );
// Start out by printing all the fixed fields in the DLGITEMTEMPLATE
GetBitfieldsAsString( pDlgItemTemplate->style,
WndStyleFlags, NUMBER_WND_STYLE_FLAGS,
szDlgItemStyles, sizeof(szDlgItemStyles) );
printf( " style: %X (%s)\n", pDlgItemTemplate->style, szDlgItemStyles );
printf( " dwExtendedStyle: %X\n", pDlgItemTemplate->dwExtendedStyle);
printf( " Coords: (%d,%d) - (%d,%d)\n",
pDlgItemTemplate->x, pDlgItemTemplate->y,
pDlgItemTemplate->x + pDlgItemTemplate->cx,
pDlgItemTemplate->y + pDlgItemTemplate->cy );
printf( " id: %d\n", (signed short)pDlgItemTemplate->id);
PWORD pClass, pTitle, pCreationData;
char szAnsiString[256];
// Following the fixed DLGITEMTEMPLATE, first up is the window class
pClass = (PWORD)(pDlgItemTemplate+1); // ptr math!
if ( *pClass )
{
if ( 0xFFFF == *pClass )
{
pClass++;
printf( " Class: %s\n", GetDlgItemClassIdAsString(*pClass++) );
}
else
{
pClass = GetDlgEmbeddedString( pClass, szAnsiString,
sizeof(szAnsiString) );
printf( " Class: %s\n", szAnsiString );
}
}
else
pClass++;
// Following the window class array is the title array
pTitle = pClass;
if ( *pTitle )
{
if ( 0xFFFF == *pTitle )
{
pTitle++;
printf( " Title resource ID: %u\n", *pTitle++ );
}
else
{
pTitle = GetDlgEmbeddedString( pTitle, szAnsiString,
sizeof(szAnsiString) );
printf( " Title: %s\n", szAnsiString );
}
}
else
pTitle++;
pCreationData = pTitle;
// Following the title array is the (optional) creation data. We won't
// show it here, because it's usually not meaningful as ASCII text
if ( *pCreationData )
{
// Adjust for the creation data. *pCreationData is in bytes, rather
// than WORDs, so we divide by sizeof(DWORD) to make the ptr addition
// come out correctly
pCreationData = (PWORD)( (PBYTE)pCreationData + *pCreationData );
}
else
pCreationData++;
// Return value is next byte after the DLGITEMTEMPLATE and its
// variable len fields
return (LPDLGITEMTEMPLATE)pCreationData;
}
// Displays all the fields of a dialog template, and then calls DumpDialogItem
// to display all the controls.
BOOL DumpDialog( PVOID pDlg )
{
LPDLGTEMPLATE pDlgTemplate = (LPDLGTEMPLATE)pDlg;
char szDlgStyles[512];
PWORD pMenu, pClass, pTitle, pPointSize, pTypeface;
char szAnsiString[256];
RECT rectDlg;
unsigned i;
if ( HIWORD(pDlgTemplate->style) != 0xFFFF )// Is it a regular DLGTEMPLATE?
{
// Start out by printing all the fixed fields in the DLGTEMPLATE
GetBitfieldsAsString( pDlgTemplate->style,
DlgStyleFlags, NUMBER_DLG_STYLE_FLAGS,
szDlgStyles, sizeof(szDlgStyles) );
printf( "style: %08X (%s)\n", pDlgTemplate->style, szDlgStyles );
printf( "extended style: %08X\n", pDlgTemplate->dwExtendedStyle );
printf( "controls: %u\n", pDlgTemplate->cdit );
printf( "Coords: (%d,%d) - (%d,%d)\n",
pDlgTemplate->x, pDlgTemplate->y,
pDlgTemplate->x + pDlgTemplate->cx,
pDlgTemplate->y + pDlgTemplate->cy );
rectDlg.left = rectDlg.top = 0;
rectDlg.right = pDlgTemplate->cx;
rectDlg.bottom = pDlgTemplate->cy;
// Following the fixed DLGTEMPLATE, first up is the menu
pMenu = (PWORD)(pDlgTemplate + 1); // ptr math!
if ( *pMenu )
{
if ( 0xFFFF == *pMenu )
{
pMenu++;
printf( "Menu ID: %u\n", *pMenu++ );
}
else
{
pMenu = GetDlgEmbeddedString( pMenu, szAnsiString,
sizeof(szAnsiString) );
printf( "Menu Name: %s\n", szAnsiString );
}
}
else
pMenu++;
// Following the menu array is the "window class" array
pClass = pMenu;
if ( *pClass )
{
if ( 0xFFFF == *pClass )
printf( "Class ID: %d\n", (signed short)*pClass++ );
else
{
pClass = GetDlgEmbeddedString( pClass, szAnsiString,
sizeof(szAnsiString) );
printf( "Class Name: %s\n", szAnsiString );
}
}
else
pClass++;
// Following the window class array is the title array
pTitle = pClass;
if ( *pTitle )
{
pTitle = GetDlgEmbeddedString( pTitle, szAnsiString,
sizeof(szAnsiString) );
printf( "Title: %s\n", szAnsiString );
}
else
pTitle++;
// Following the title array is the point size and font (if DS_SETFONT
// is set in pDlgTemplate->Style
if ( pDlgTemplate->style & DS_SETFONT )
{
pPointSize = pTitle;
pTypeface = pPointSize+1;
pTypeface = GetDlgEmbeddedString( pTypeface, szAnsiString,
sizeof(szAnsiString) );
printf( "Font: %u point %s\n", *pPointSize, szAnsiString );
}
else
pTypeface = pTitle;
LPDLGITEMTEMPLATE pDlgItemTemplate = (LPDLGITEMTEMPLATE)pTypeface;
// Now iterate through each of the controls, calling DumpDialogItem
for ( i=0; i < pDlgTemplate->cdit; i++ )
{
pDlgItemTemplate = ALIGN_DWORD(LPDLGITEMTEMPLATE, pDlgItemTemplate);
printf( " ----\n" ); // Print separator for next item
// Check that the dialog item is within the bounds of the dialog.
// If not, emit a warning message
POINT ctlPt = { pDlgItemTemplate->x, pDlgItemTemplate->y };
if ( !PtInRect( &rectDlg, ctlPt ) )
printf( " *** Item not within dialog ***\n" );
pDlgItemTemplate = DumpDialogItem( pDlgItemTemplate );
}
}
else // Left as an exercise for the reader... :-)
printf( "DLGTEMPLATEEX type not yet handled\n" );
return TRUE;
}