NO

Author Topic: Dialog code from res-file  (Read 222 times)

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1745
Dialog code from res-file
« on: September 10, 2018, 10:53:01 am »
This example dump Dialog code from res-file:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

int ProcessFile(PBYTE pMem, int nMax);

int main(int argc, char **argv)
{
HANDLE hFile, hMapping;
VOID *pMem;

if (argc < 2) {
printf("Usage: ResDlgDump.exe <file>\n");
return 1;
}
hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping)
{
pMem = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (pMem)
{
DWORD dwSize = GetFileSize(hFile, NULL);
ProcessFile(pMem, dwSize);
UnmapViewOfFile(pMem);
} else
printf("File open error");
CloseHandle(hMapping);
} else
printf("FileMapping error");
CloseHandle(hFile);
}
else
printf("File open error");
return 0;
}

typedef struct tagRESOURCEHEADER {
DWORD DataSize;
DWORD HeaderSize;
DWORD Type; // variable size
DWORD Name; // variable size
DWORD DataVersion;
WORD MemoryFlags;
WORD LanguageId;
DWORD Version;
DWORD Characteristics;
}RESOURCEHEADER, *PRESOURCEHEADER;

void DumpDialog(PBYTE pByte, PBYTE pMem);

int ProcessFile(PBYTE pMem, int nMax)
{
PBYTE pByte = pMem;
do {
if (((PRESOURCEHEADER)pByte)->Type == 0x5FFFF) { // Dialog
DumpDialog(pByte, pMem);
}
DWORD nSize = ((PRESOURCEHEADER)pByte)->DataSize + ((PRESOURCEHEADER)pByte)->HeaderSize;
pByte += (nSize + 3) & ~3;
} while (pByte < pMem + nMax);
return 0;
}
//#pragma pack(push, 2)
typedef struct {
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
/* sz_Or_Ord menu;
sz_Or_Ord windowClass;
WCHAR title[titleLen];
short pointsize;
short weight;
short bItalic;
WCHAR font[fontLen]; */
} DLGTEMPLATEEX, *LPDLGTEMPLATEEX;
// https://docs.microsoft.com/en-us/windows/desktop/dlgbox/dlgitemtemplateex
//https://blogs.msdn.microsoft.com/oldnewthing/20040623-00/?p=38753
typedef struct {
DWORD helpID;
DWORD dwExtendedStyle;
DWORD style;
WORD x;
WORD y;
WORD cx;
WORD cy;
DWORD id;
/* sz_Or_Ord windowClass;
sz_Or_Ord title;
WORD extraCount; */
} DLGITEMTEMPLATEEX, *LPDLGITEMTEMPLATEEX;
//#pragma pack(pop)
WCHAR *GetCtlClassW(WORD wClass)
{
switch (wClass) {
case 0x0080: return L"BUTTON"; break;
case 0x0081: return L"EDIT"; break;
case 0x0082: return L"STATIC"; break;
case 0x0083: return L"LISTBOX"; break;
case 0x0084: return L"SCROLLBAR"; break;
case 0x0085: return L"COMBOBOX"; break;
}
return NULL;
}

void AddDlgRCCodeEx(PRESOURCEHEADER pResHdr, LPDLGTEMPLATEEX pDlgEx,PWORD pMenu, PWORD pCaption, PBYTE pPar);
void AddCtlRCCodeEx(LPDLGITEMTEMPLATEEX pDlgItem, PWORD pClass, PWORD pTitle);
void AddDlgCodeEx(LPDLGTEMPLATEEX pDlgEx, PWORD pMenu, PWORD pCaption);
void AddCtlCodeEx(LPDLGITEMTEMPLATEEX pDlgItem, PWORD pClass, PWORD pTitle);


void DumpDialog(PBYTE pByte, PBYTE pMem)
{
PRESOURCEHEADER pResHdr = (PRESOURCEHEADER)pByte;
PWORD pPtr = (PWORD)(pByte + ((PRESOURCEHEADER)pByte)->HeaderSize);
DWORD nSize = *(DWORD*)pByte;
DWORD nItems;
if (*(DWORD*)pPtr != 0xFFFF0001) { // Standard Dialog
DLGTEMPLATE *pDlg = (DLGTEMPLATE*)(pByte + ((PRESOURCEHEADER)pByte)->HeaderSize);
nItems = pDlg->cdit;
//printf("style: %Xh\n", pDlg->style);
if (pDlg->style & DS_SETFONT)
pPtr += sizeof(DWORD);
for (unsigned i=0; i<nItems; i++) {
pPtr = (PWORD)((DWORD_PTR)(pPtr + 3) & ~3);
LPDLGITEMTEMPLATE pDlgItem = (LPDLGITEMTEMPLATE)pPtr;
//printf("\nOfs: %Xh\n", pPtr - pMem);
}
} else { // Extended Dialog
//DLGTEMPLATEEX1 *pDlgEx = (DLGTEMPLATEEX1*)(pByte + ((PRESOURCEHEADER)pByte)->HeaderSize);
DLGTEMPLATEEX *pDlgEx = (DLGTEMPLATEEX*)pPtr;
nItems = pDlgEx->cDlgItems;
pPtr = (PWORD)((PBYTE)pPtr + sizeof(DLGTEMPLATEEX));
pPtr = (PWORD)((DWORD_PTR)((PBYTE)pPtr + 3) & ~3); // if struct packed 1
PWORD pMenu = pPtr;
if (*(WORD*)pPtr) { // Menu ?
while (pPtr) pPtr++;
pPtr ++; // past zero
} else {
pPtr ++;
}
//printf("\nCaption: %Xh\n", (PBYTE)pPtr - pMem);
PWORD pCaption = pPtr;
if (*(WORD*)pPtr) { // Caption ?
while (*pPtr) pPtr++;
pPtr ++; // past zero
} else {
pPtr ++;
}
//printf("\nOfs: %Xh\n", pPtr - pMem);
PBYTE pPar =(PBYTE) pPtr;
// Font name
pPtr += 3;
while (*pPtr) pPtr++;
pPtr ++; // past zero
//if (pDlgEx->style & DS_SETFONT)
// pPtr ++;
AddDlgRCCodeEx(pResHdr, pDlgEx, pMenu, pCaption, pPar);
AddDlgCodeEx(pDlgEx, pMenu, pCaption);
printf("{\n");
for (unsigned i=0; i<nItems; i++) {
pPtr = (PWORD)((DWORD_PTR)((PBYTE)pPtr + 3) & ~3);
//printf("%Xh", (PBYTE)pPtr - pMem);
LPDLGITEMTEMPLATEEX pDlgItem = (LPDLGITEMTEMPLATEEX)pPtr;
PWORD pClass, pTitle;
//printf("\nOfs: %Xh\n", pPtr - pMem);
//pPtr += sizeof(DLGITEMTEMPLATEEX);
pPtr = (PWORD)((PBYTE)pPtr + sizeof(DLGITEMTEMPLATEEX));
//printf("\npClass: %Xh\n", pPtr - pMem);
pClass = (PWORD)pPtr;
if (*(WORD*)pPtr) { // Class name or id ?
if (*pClass == 0xFFFF) {
pPtr += 2; // FFFFh and id
} else {
while (*(WORD*)pPtr) pPtr++;
pPtr ++; // past zero
}
} else {
pPtr ++;
}
pTitle = (PWORD)pPtr;
if (*(WORD*)pPtr) { // Title name or id ?
if (*pTitle == 0xFFFF)
pPtr += 2;
else {
while (*(WORD*)pPtr) pPtr+=2;
pPtr ++; // past zero
}
} else {
pPtr ++;
}
if (*(WORD*)pPtr) { // CreationData
pPtr += *pPtr;
} else pPtr ++;
AddCtlRCCodeEx(pDlgItem, pClass, pTitle);
AddCtlCodeEx(pDlgItem, pClass, pTitle);
//printf("\n");
}
printf("}\n");
}
}

void AddDlgRCCodeEx(PRESOURCEHEADER pResHdr, LPDLGTEMPLATEEX pDlgEx, PWORD pMenu, PWORD pCaption, PBYTE pPar)
{
if ((WORD)pResHdr->Name == 0xFFFF) // numeric id
printf("%d ", HIWORD(pResHdr->Name));
else
printf("Name: %ls\n", (WCHAR*)pResHdr->Name);
printf("DIALOGEX %d,%d,%d,%d\n", pDlgEx->x, pDlgEx->y, pDlgEx->cx, pDlgEx->cy);
printf("STYLE 0x%X\n", pDlgEx->style);
printf("CAPTION \"%ls\"\n", pCaption);
if (*pMenu) printf("MENU \"%ls\"\n", pMenu);
printf("FONT %d \"%ls\"", *(WORD*)pPar, (WCHAR*)pPar+6);
printf(",%d,%d,%d\n", *(pPar+3), *(pPar+4), *(pPar+5));
}

void AddCtlRCCodeEx(LPDLGITEMTEMPLATEEX pDlgItem, PWORD pClass, PWORD pTitle)
{
printf("\tCONTROL ");
if (*pTitle) {
if (*pTitle == 0xFFFF) printf("%d", *(pTitle+1));
else printf("\"%ls\"", pTitle);
} else printf("NULL");
printf(",%d,", pDlgItem->id);
if (*pClass == 0xFFFF) printf("\"%ls\"", GetCtlClassW(*(pClass+1)));
else printf("\"%ls\"", pClass);
if (pDlgItem->style) printf(",0x%X", pDlgItem->style);
else printf(",0");
printf(",%d,%d,%d,%d,0x%X\n",
pDlgItem->x, pDlgItem->y, pDlgItem->cx, pDlgItem->cy,
pDlgItem->dwExtendedStyle);
}

void AddDlgCodeEx(LPDLGTEMPLATEEX pDlgEx, PWORD pMenu, PWORD pCaption)
{
printf("hWnd=CreateWindowEx(");
if (pDlgEx->exStyle) printf("0x%X", pDlgEx->exStyle);
else printf("0");
if (*pCaption) printf(",\"cDlg\",\"%ls\"", pCaption);
else printf("NULL");
printf(",0x%X,%d,%d,%d,%d,hWnd,(HMENU)%d,hInst,NULL);\n",
pDlgEx->style, pDlgEx->x*2, pDlgEx->y*2, pDlgEx->cx*2, pDlgEx->cy*2,0);
}

void AddCtlCodeEx(LPDLGITEMTEMPLATEEX pDlgItem, PWORD pClass, PWORD pTitle)
{
printf("\tCreateWindowEx(");
if (pDlgItem->dwExtendedStyle) printf("0x%X", pDlgItem->dwExtendedStyle);
else printf("0");
if (*pClass == 0xFFFF) printf(",\"%ls\"", GetCtlClassW(*(pClass+1)));
else printf(",\"%ls\"", pClass);
if (*pTitle) {
if (*pTitle == 0xFFFF) printf(",\"#%d\"", *(pTitle+1));
else printf(",\"%ls\"", pTitle);
} else printf("NULL");
printf(",0x%X,%d,%d,%d,%d,hWnd,(HMENU)%d,hInst,NULL);\n",
pDlgItem->style,
pDlgItem->x*2, pDlgItem->y*2, pDlgItem->cx*2, pDlgItem->cy*2,
pDlgItem->id);

}
Example:
Code: [Select]
1001 DIALOGEX 6,18,195,77
STYLE 0x90C828C0
CAPTION "About WTest3 Program"
FONT 8 "Sans Serif",0,0,1
hWnd=CreateWindowEx(0,"cDlg","About WTest3 Program",0x90C828C0,12,36,390,154,hWnd,(HMENU)0,hInst,NULL);
{
        CONTROL "OK",1,"BUTTON",0x50010000,75,55,45,15,0x0
        CreateWindowEx(0,"BUTTON","OK",0x50010000,150,110,90,30,hWnd,(HMENU)1,hInst,NULL);
        CONTROL 8001,4001,"STATIC",0x50000203,5,10,26,26,0x0
        CreateWindowEx(0,"STATIC","#8001",0x50000203,10,20,52,52,hWnd,(HMENU)4001,hInst,NULL);
        CONTROL "WTest3 Program",-1,"STATIC",0x50020000,40,10,150,10,0x0
        CreateWindowEx(0,"STATIC","WTest3 Program",0x50020000,80,20,300,20,hWnd,(HMENU)-1,hInst,NULL);
        CONTROL "Version 1.0",-1,"STATIC",0x50020000,40,22,150,10,0x0
        CreateWindowEx(0,"STATIC","Version 1.0",0x50020000,80,44,300,20,hWnd,(HMENU)-1,hInst,NULL);
}
EDIT: ResDlg2Code Add-In
It add to menu File -> Resource Dialog to C code and works with Resource Editor even without saving (untitled), but not in design window.

A helper tools:
Code: [Select]
#include <stdio.h>
#include <string.h>

typedef unsigned long DWORD;

// #define WS_OVERLAPPED  0x00000000L
int main(int argc,char **argv)
{
FILE *fi;
int i =0;
char ch, buf[4096];

if ((fi=fopen("WinUser.h", "r")) == NULL) {
//if ((fi=fopen("WinStyles.h", "r")) == NULL) {
//if ((fi=fopen("CommCtrl.h", "r")) == NULL) {
return 1;
}
int instyles = 0;
int iflag = 0;
while (fgets(buf, sizeof(buf), fi)) {
i++;
if (*(unsigned long*)buf == *(unsigned long*)"#def"
&& *(unsigned long*)(buf+4) == *(unsigned long*)"ine "
&& (*(unsigned short*)(buf+9) == *(unsigned short*)"S_"
||*(unsigned short*)(buf+10) == *(unsigned short*)"S_")) {
//
buf[7] = 0;
char *p = &buf[8];
char *p1 = p;
while (*p && *p != ' ') p++;
*p++ = 0;
char *p2 = p;
while (*p && *p != '\n') p++;
*p = 0;
if (*p2 == ' ') p2++;
if (*(p-1) == 'L' && *(p1+5) != '_'  && *p1 != 'M') {
if (*p1 == 'C' && *(p1+1) == 'S') iflag = 1; // WINDOW
else if (*p1 == 'D') iflag = 2; // DIALOG
else if (*p1 == 'B') iflag = 0x80; // BUTTON 0x80
else if (*p1 == 'E') iflag = 0x81; // EDIT 0x81
else if (*p1 == 'S') iflag = 0x82; // STATIC 0x82
else if (*p1 == 'L') iflag = 0x83; // LISTBOX 0x83
else if (*p1 == 'S' && *(p1+1) == 'B') iflag = 0x84; // SCROLLBAR 0x84
else if (*p1 == 'C' && *(p1+1) == 'B') iflag = 0x85; // COMBOBOX 0x85
else iflag = 0; // unknown
printf("{\"%s\",%s,0x%X},\n", p1, p2, iflag);
}
}
}
fclose(fi);
return 0;
}
and a test:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#define NELEMS(a)  (sizeof(a) / sizeof(a[0]))

//#define WS_POPUP  0x80000000L
//#define WS_VISIBLE  0x10000000L

struct _WINSTYLES {
char *name;
long mask;
long flag;
}aws[] = {
{"WS_OVERLAPPED",0x00000000L,0},
...
{"SBS_SIZEGRIP",0x0010L,7},
};

int __cdecl main(void)
{
//long ws = 0x90C828C4;
long ws = DS_MODALFRAME | DS_CENTER | DS_CONTEXTHELP | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU;
int iflag = 2; // a dialog
for (int i=0; i<NELEMS(aws); i++) {
if (ws & aws[i].mask && (!aws[i].flag || aws[i].flag == iflag))
printf("%08X %s\n", aws[i].mask, aws[i].name);
}
return 0;
}
« Last Edit: September 13, 2018, 08:01:25 pm by TimoVJL »
May the source be with you