diff options
Diffstat (limited to 'src/ildasm/gui.cpp')
-rw-r--r-- | src/ildasm/gui.cpp | 4013 |
1 files changed, 4013 insertions, 0 deletions
diff --git a/src/ildasm/gui.cpp b/src/ildasm/gui.cpp new file mode 100644 index 0000000000..f5f141d279 --- /dev/null +++ b/src/ildasm/gui.cpp @@ -0,0 +1,4013 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "ildasmpch.h" + +#ifndef FEATURE_CORECLR +#include "debugmacros.h" +#include "corpriv.h" +#include "ceeload.h" +#include "dasmgui.h" +#include "dasmenum.hpp" +#include "dis.h" +#include "resource.h" +#include "gui.h" +#include "formattype.h" +#include "..\tools\metainfo\mdinfo.h" +#include <NdpVersion.h> + +struct MemberInfo { + const char *pszMemberName; + DWORD dwAttrs; + ULONG cComSig; + PCCOR_SIGNATURE pComSig; + mdToken token; +}; + +int __cdecl memberCmp(const void *elem1, const void *elem2 ) { + MemberInfo* mem1 = (MemberInfo*) elem1; + MemberInfo* mem2 = (MemberInfo*) elem2; + return(strcmp(mem1->pszMemberName, mem2->pszMemberName)); +} + +// +// Global buffer, filled by AddOPCode +// +char *GlobalBuffer = new (nothrow) char[65535]; +ULONG GlobalBufferLen = 65535; +ULONG InGlobalBuffer; +// +// Global HINSTANCE +// +extern HINSTANCE g_hInstance; +extern HINSTANCE g_hResources; + +// +// Main window +// +HWND g_hwndMain; + +// +// Treeview for main window +// +HWND g_hwndTreeView; + +// +// Treeview class full name / partial name switch +// +BOOL g_fTreeViewFCN = TRUE; + +// +// Assembly info window (child of main) +// +HWND g_hwndAsmInfo; +extern IMetaDataAssemblyImport* g_pAssemblyImport; +void DumpAssembly(void* GUICookie, BOOL fFullDump); +IMetaDataAssemblyImport* GetAssemblyImport(void* GUICookie); + +// +// Global image list +// +HIMAGELIST g_hImageList; + +// +// Menu for main window +// +HMENU g_hMenu, g_hMetaInfoMenu, g_hFileMenu, g_hViewMenu, g_hFontMenu; + +// +// Flags +// +BOOL g_fFullMemberInfo = FALSE; // Show member type? (method, field, event, prop) +BOOL g_fSortByName = TRUE; // Sort members in tree? +// +// Module name of loaded DLL/EXE +// +const char *g_pszModule; + +// +// Interlocked variable for setting char dimensions once +// +long g_SetCharDimensions = 0; + +unsigned g_uFindReplaceMsg = 0; +HWND g_hFindText = NULL; +// +// Bitmap handles +// +HBITMAP g_hBitmaps[LAST_IMAGE_INDEX]; + +// +// Root item for listview +// +HTREEITEM g_hRoot; + +// Global graphics +HBRUSH g_hWhiteBrush; +HFONT g_hFixedFont; +HFONT g_hSmallFont; +HBITMAP g_hMethodBmp, g_hFieldBmp, g_hClassBmp, g_hStaticMethodBmp, g_hStaticFieldBmp, g_hQuestionBmp; +LOGFONTW g_strLogFontTree, g_strLogFontDasm; +CHOOSEFONTW g_strChFontTree, g_strChFontDasm; + +struct GUI_Info +{ + LOGFONTW* plfTree; + LOGFONTW* plfDasm; + int x; + int y; + int w; + int h; +}; + +GUI_Info guiInfo = {&g_strLogFontTree, &g_strLogFontDasm, CW_USEDEFAULT, CW_USEDEFAULT, 400,600}; + +// Text info +long g_Height; +long g_MaxCharWidth; + +// Currently selected treeview item +HTREEITEM g_CurSelItem; + +extern IMAGE_COR20_HEADER * g_CORHeader; +extern BOOL g_fDumpTokens; +extern BOOL g_fShowBytes; +extern BOOL g_fShowSource; +extern BOOL g_fTryInCode; +extern BOOL g_fQuoteAllNames; +extern BOOL g_fCAVerbal; +extern BOOL g_fShowProgressBar; +extern BOOL g_fDumpHeader; +extern BOOL g_fDumpAsmCode; +extern BOOL g_fDumpTokens; +extern BOOL g_fDumpStats; +extern BOOL g_fDumpMetaInfo; +extern BOOL g_fDumpClassList; +extern BOOL g_fInsertSourceLines; + +extern BOOL g_fLimitedVisibility; +extern BOOL g_fHidePub; +extern BOOL g_fHidePriv; +extern BOOL g_fHideFam; +extern BOOL g_fHideAsm; +extern BOOL g_fHideFAA; +extern BOOL g_fHideFOA; +extern BOOL g_fHidePrivScope; +extern BOOL g_fTDC; + +extern char g_szInputFile[]; // in UTF-8 +extern WCHAR g_wszFullInputFile[]; // in UTF-16 +extern ULONG g_ulMetaInfoFilter; +extern char g_szOutputFile[]; // in UTF-8 +extern DWORD g_Mode; +extern FILE* g_pFile; +extern HINSTANCE g_hInstance; + +extern unsigned g_uCodePage; +extern unsigned g_uConsoleCP; +DWORD DumpResourceToFile(__in __nullterminated WCHAR* wzFileName); // see DRES.CPP +// +// Functions +// +BOOL RegisterWindowClasses(); +HWND CreateTreeView(HWND hwndParent); +HTREEITEM AddOneItem(HTREEITEM hParent, const char *pszText, HTREEITEM hInsAfter, int iImage, HWND hwndTree, BOOL fExpanded); +HWND GUIDisassemble(mdTypeDef cl, mdToken mbMember, __in __nullterminated char *pszWindowTitle); +HTREEITEM AddClassToTreeView(HTREEITEM hParent, mdTypeDef cl); +void AddGlobalFunctions(); +void CreateMenus(); +Namespace_t* FindNamespace(const char *pszNamespace); +void GUICleanupClassItems(); +void SelectClassByName(__in __nullterminated char *pszFQName); +void SelectClassByToken(mdToken tk); +void DumpTreeItem(HTREEITEM hItem, FILE* pFile, __inout __nullterminated WCHAR* szIndent); +HTREEITEM FindCreateNamespaceRoot(const char *pszNamespace); +FILE* OpenOutput(__in __nullterminated const char* szFileName); +FILE* OpenOutput(__in __nullterminated const WCHAR* wzFileName); + +#undef SendMessageW +#undef PostMessageW +#undef CreateWindowExW +#undef DefWindowProcW +#undef RegisterClassExW +#undef RegisterClassW +#undef SetWindowTextW +#undef GetWindowTextW +#undef MessageBoxW + +char* UtfToAnsi(__in __nullterminated const char* sz) { return UnicodeToAnsi(UtfToUnicode(sz));} + +LRESULT CALLBACK DisassemblyWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam +); + +LRESULT CALLBACK MainWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam +); + +ClassItem_t *AddClassToGUI(mdTypeDef cl, UINT uImageIndex, + const char *pszNamespace, const char *pszClassName, DWORD cSubItems, HTREEITEM *phRoot); + +void AddMethodToGUI( + mdTypeDef cl, + ClassItem_t * pClassItem, + const char *pszNamespace, + const char *pszClassName, + const char *pszMethodName, + PCCOR_SIGNATURE pComSig, + unsigned cComSig, + mdMethodDef mbMethod, + DWORD dwAttrs +); + +void AddFieldToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + const char *pszFieldName, + const char *pszSignature, + mdFieldDef mbField, + DWORD dwAttrs +); + +void AddEventToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + DWORD dwClassAttrs, + mdEvent mbEvent +); + +void AddPropToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + DWORD dwClassAttrs, + mdProperty mbProp +); + +DynamicArray<DisasmBox_t> *g_DisasmBox; +DWORD g_NumDisasmBoxes=0; + +DynamicArray<ClassItem_t> *g_ClassItemList; +DWORD g_NumClassItems=0; + +DynamicArray<Namespace_t> *g_NamespaceList; +DWORD g_NumNamespaces=0; + + +ClassItem_t *FindClassItem(HTREEITEM hItem); +ClassItem_t *FindClassItem(mdTypeDef cl); +ClassItem_t *FindClassItem(__in_opt __nullterminated char *pszNamespace, __in __nullterminated char *pszName); + +// Find disasm box among opened by class and member tokens +DisasmBox_t* FindDisasmBox(mdToken tkClass, mdToken tkMember) +{ + for (DWORD i = 0; i < g_NumDisasmBoxes; i++) + { + if (((*g_DisasmBox)[i].tkClass == tkClass) + &&((*g_DisasmBox)[i].tkMember == tkMember)) + return &(*g_DisasmBox)[i]; + } + return NULL; +} +// Find disasm box among opened by the container hwnd +DisasmBox_t* FindDisasmBoxByHwnd(HWND hwndContainer) +{ + for (DWORD i = 0; i < g_NumDisasmBoxes; i++) + { + if ((*g_DisasmBox)[i].hwndContainer == hwndContainer) + return &(*g_DisasmBox)[i]; + } + return NULL; +} +// +// Add a new disassembly box to the global list of them +// +// hwndContainer - parent window +// hwndChild - listview +// +void AddDisasmBox(HWND hwndContainer, HWND hwndChild, HMENU hMenu, mdToken tkClass, mdToken tkMember) +{ + (*g_DisasmBox)[g_NumDisasmBoxes].hwndContainer = hwndContainer; + (*g_DisasmBox)[g_NumDisasmBoxes].hwndChild = hwndChild; + (*g_DisasmBox)[g_NumDisasmBoxes].hMenu = hMenu; + (*g_DisasmBox)[g_NumDisasmBoxes].tkClass = tkClass; + (*g_DisasmBox)[g_NumDisasmBoxes].tkMember = tkMember; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lStructSize = sizeof(FINDREPLACEW); + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.hwndOwner = hwndContainer; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.Flags = FR_DOWN|FR_DIALOGTERM; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpstrFindWhat = (LPWSTR)((*g_DisasmBox)[g_NumDisasmBoxes].wzFind); + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpstrReplaceWith = NULL; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.wFindWhatLen = 120; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.wReplaceWithLen = 0; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lCustData = 0; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpfnHook = NULL; + (*g_DisasmBox)[g_NumDisasmBoxes].strFR.lpTemplateName = NULL; + g_NumDisasmBoxes++; +} + +void UpdateDisasmBox(DisasmBox_t* pBox, HWND hwndContainer, HWND hwndChild, HMENU hMenu) +{ + pBox->hwndContainer = hwndContainer; + pBox->hwndChild = hwndChild; + pBox->hMenu = hMenu; + pBox->strFR.hwndOwner = hwndContainer; +} +// +// Given a container window, find the associated disassembly window +// +HWND FindAssociatedDisassemblyListBox(HWND hwndContainer) +{ + DWORD i; + + for (i = 0; i < g_NumDisasmBoxes; i++) + { + if ((*g_DisasmBox)[i].hwndContainer == hwndContainer) + return (*g_DisasmBox)[i].hwndChild; + } + + return NULL; +} + +// +// Given a disassembly window, find the associated container window +// +HWND FindAssociatedDisassemblyContainer(HWND hwndChild) +{ + DWORD i; + + for (i = 0; i < g_NumDisasmBoxes; i++) + { + if ((*g_DisasmBox)[i].hwndChild == hwndChild) + return (*g_DisasmBox)[i].hwndContainer; + } + + return NULL; +} + + +void RemoveDisasmBox(HWND hwndContainer) +{ + DWORD i; + + for (i = 0; i < g_NumDisasmBoxes; i++) + { + if ((*g_DisasmBox)[i].hwndContainer == hwndContainer) + { + memcpy(&(*g_DisasmBox)[i], &(*g_DisasmBox)[i+1], (g_NumDisasmBoxes-i-1)*sizeof(DisasmBox_t)); + g_NumDisasmBoxes--; + break; + } + } +} + + +void RemoveItemsFromList() +{ + TreeView_DeleteAllItems(g_hwndTreeView); +} + + +BOOL RefreshList() +{ + GUICleanupClassItems(); + return GUIAddItemsToList(); +} + + +void GUISetModule(__in __nullterminated const char *pszModule) +{ + g_pszModule = pszModule; +} + + +TreeItem_t *FindClassMemberByName(ClassItem_t *pClassItem, + __in __nullterminated char *pszFindName, + __in __nullterminated char *pszFindSig) +{ + HRESULT hr; + DWORD i; + + // do in two passes, fields first + for (i = 0; i < pClassItem->SubItems; i++) + { + TreeItem_t *pItem; + const char *pszMemberName; + const char *pszMemberSig; + DWORD dwAttrs; + + CQuickBytes qbMemberSig; + + PCCOR_SIGNATURE pComSig; + ULONG cComSig; + + + pItem = &pClassItem->pMembers[i]; + if (pItem->Discriminator != TREEITEM_TYPE_MEMBER) + continue; + + if (TypeFromToken(pItem->mbMember) == mdtMethodDef) + { + if (FAILED(g_pImport->GetMethodDefProps(pItem->mbMember, &dwAttrs))) + { + continue; + } + if (FAILED(g_pImport->GetNameOfMethodDef(pItem->mbMember, &pszMemberName))) + { + continue; + } + if (FAILED(g_pImport->GetSigOfMethodDef(pItem->mbMember, &cComSig, &pComSig))) + { + continue; + } + } + else + { + if (FAILED(g_pImport->GetFieldDefProps(pItem->mbMember, &dwAttrs))) + { + continue; + } + if (FAILED(g_pImport->GetNameOfFieldDef(pItem->mbMember, &pszMemberName))) + { + continue; + } + if (FAILED(g_pImport->GetSigOfFieldDef(pItem->mbMember, &cComSig, &pComSig))) + { + continue; + } + } + MAKE_NAME_IF_NONE(pszMemberName,pItem->mbMember); + qbMemberSig.Shrink(0); + pszMemberSig = PrettyPrintSig(pComSig, cComSig, "", &qbMemberSig, g_pImport,NULL); + + // @todo: GUI IL is so that NDView can call into DASM with/GUI; NDView uses Reflection API + // which doesn't let us get a valid signature. + // If GUI IL only, then ignore signature if it's NULL + if (IsGuiILOnly()) { + if (!strcmp(pszMemberName, pszFindName)) { + if ((pszFindSig != NULL) && strcmp(pszMemberSig, pszFindSig)) continue; + return pItem; + } + } else { + if (!strcmp(pszMemberName, pszFindName) && !strcmp(pszMemberSig, pszFindSig)) + return pItem; + } + } + + return NULL; +} + +// Kick of a disassembly window +// Return TRUE if window opened ok, and FALSE if there's an error +BOOL DisassembleMemberByName(__in __nullterminated char *pszClassName, + __in __nullterminated char *pszMemberName, + __in_opt __nullterminated char *pszSig) +{ + char szClassName[MAX_CLASSNAME_LENGTH]; + char szClassNamespace[MAX_CLASSNAME_LENGTH]; + char *pszClassNamespace; + char *p; + + p = ns::FindSep(pszClassName); + if (p == NULL) + { + strcpy_s(szClassName, MAX_CLASSNAME_LENGTH,pszClassName); + pszClassNamespace = NULL; + } + else + { + strncpy_s(szClassNamespace, MAX_CLASSNAME_LENGTH, pszClassName, p - pszClassName); + szClassNamespace[ p - pszClassName ] = '\0'; + pszClassNamespace = szClassNamespace; + + strcpy_s(szClassName, MAX_CLASSNAME_LENGTH, p+1); + } + + ClassItem_t *pClassItem = FindClassItem(pszClassNamespace, szClassName); + + if (pClassItem != NULL) + { + TreeItem_t *pTreeItem; + + pTreeItem = FindClassMemberByName(pClassItem, pszMemberName, pszSig); + + if (pTreeItem != NULL) + { + DWORD dwAttrs; + DWORD dwImplAttrs; + + // What is this member? + + if (TypeFromToken(pTreeItem->mbMember) == mdtMethodDef) + { + char* szText; + HWND fOK=NULL; + if (FAILED(g_pImport->GetMethodDefProps(pTreeItem->mbMember, &dwAttrs))) + { + goto ErrorHere; + } + if (FAILED(g_pImport->GetMethodImplProps(pTreeItem->mbMember, NULL, &dwImplAttrs))) + { + goto ErrorHere; + } + + // Can't be abstract or native + if (IsMdAbstract(dwAttrs) || IsMiInternalCall(dwImplAttrs)) + return FALSE; + + szText = new (nothrow) char[4096]; + if(szText) + { + TVITEMA SelItem; + + // Get the name of this item so that we can title the disassembly window + memset(&SelItem, 0, sizeof(SelItem)); + SelItem.mask = TVIF_TEXT; + SelItem.pszText = szText; + SelItem.hItem = pTreeItem->hItem; + SelItem.cchTextMax = 4095; + + WCHAR* wzText = (WCHAR*)szText; + SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem); + unsigned L = ((unsigned)wcslen(wzText)+1)*3; + char* szUTFText = new (nothrow) char[L]; + if(szUTFText) + { + memset(szUTFText,0,L); + WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL); + delete[] wzText; + szText = szUTFText; + } + + fOK = GUIDisassemble(pClassItem->cl, pTreeItem->mbMember, szText); + delete[] szText; + } + if (fOK == NULL) { + goto ErrorHere; + } + } + } // endif (pTreeItem != NULL) + else { + goto ErrorHere; + } + + } else { + goto ErrorHere; + } + + return TRUE; + +ErrorHere: + char pzText[300]; + sprintf_s(pzText, 300,RstrUTF(IDS_CANTVIEW_TX) /*"Can't view %s::%s(%s)"*/, pszClassName, pszMemberName, pszSig); + + WszMessageBox(g_hwndMain, UtfToUnicode(pzText), RstrW(IDS_CANTVIEW_HD) /*"Can't View IL"*/, MB_OK | MB_ICONERROR | GetDasmMBRTLStyle() ); + + + return FALSE; +} + +//HTREEITEM AddInfoItemToClass(HTREEITEM hParent, ClassItem_t *pClassItem, const char *pszText, const char *pszStoredInfoText) +HTREEITEM AddInfoItemToClass(HTREEITEM hParent, ClassItem_t *pClassItem, const char *pszText, mdToken tk) +{ + _ASSERTE(pClassItem->CurMember < pClassItem->SubItems); + pClassItem->pMembers[pClassItem->CurMember].hItem = AddOneItem( + pClassItem->hItem, pszText, hParent, RED_ARROW_IMAGE_INDEX, g_hwndTreeView, FALSE + ); + pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_INFO; + //pClassItem->pMembers[pClassItem->CurMember].pszText = (char *) pszStoredInfoText; + pClassItem->pMembers[pClassItem->CurMember].mbMember = tk; + pClassItem->CurMember++; + + return pClassItem->pMembers[pClassItem->CurMember-1].hItem; +} + +struct ClassDescr +{ + mdToken tk; + const char* szName; +}; +static int __cdecl classDescrCmp(const void *op1, const void *op2) +{ + return strcmp(((ClassDescr*)op1)->szName,((ClassDescr*)op2)->szName); +} + +unsigned AddClassesWithEncloser(mdToken tkEncloser, HTREEITEM hParent) +{ + unsigned i, N=0; + for (i = 0; i < g_NumClasses; i++) + { + if(g_cl_enclosing[i] == tkEncloser) N++; + } + + if(N) + { + ClassDescr* rClassDescr = new (nothrow) ClassDescr[N]; + const char *pszClassName,*pszNamespace; + for (i = 0, N = 0; i < g_NumClasses; i++) + { + if(g_cl_enclosing[i] == tkEncloser) + { + rClassDescr[N].tk = g_cl_list[i]; + if (FAILED(g_pImport->GetNameOfTypeDef(g_cl_list[i], &pszClassName, &pszNamespace))) + { + pszClassName = pszNamespace = "Invalid TypeDef record"; + } + // doesn't throw here, so rClassDescr doesn't leak + MAKE_NAME_IF_NONE(pszClassName,g_cl_list[i]); + rClassDescr[N].szName = pszClassName; + N++; + } + } + if(g_fSortByName) qsort(&rClassDescr[0],N,sizeof(ClassDescr),classDescrCmp); + for(i = 0; i < N; i++) AddClassToTreeView(hParent,rClassDescr[i].tk); + delete[] rClassDescr; + } + return N; +} + +static int __cdecl stringCmp(const void *op1, const void *op2) +{ + return strcmp(*((char**)op1), *((char**)op2)); + //return(strlen(*((char**)op1)) - strlen(*((char**)op2))); +} + +UINT GetDasmMBRTLStyle() { + UINT RTLMessageBoxStyle = 0; + WCHAR* pwStr = RstrW(IDS_RTL); + if( wcscmp(pwStr, L"RTL_True") == 0) { + RTLMessageBoxStyle = 0x00080000 |0x00100000; // MB_RIGHT || MB_RTLREADING + } + return RTLMessageBoxStyle; +} + +void GUIDumpAssemblyInfo() +{ + memset(GlobalBuffer,0,GlobalBufferLen); + InGlobalBuffer = 0; + if(g_pAssemblyImport==NULL) g_pAssemblyImport = GetAssemblyImport((void*)g_hwndAsmInfo); + if(g_pAssemblyImport) + { + if(g_fDumpRTF) DumpRTFPrefix((void *)g_hwndAsmInfo,FALSE); + DumpAssembly((void *)g_hwndAsmInfo,FALSE); + if(g_fDumpRTF) DumpRTFPostfix((void *)g_hwndAsmInfo); + } + + if(g_uCodePage == 0xFFFFFFFF) + SendMessageW((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)GlobalBuffer); + else + { + UINT32 L = (UINT32)strlen(GlobalBuffer); + WCHAR* wz = new (nothrow) WCHAR[L+4]; + if(wz) + { + memset(wz,0,sizeof(WCHAR)*(L+2)); + int x = WszMultiByteToWideChar(CP_UTF8,0,GlobalBuffer,-1,wz,L+2); + if(g_fDumpRTF) + { + x = (int)SendMessageA((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)UnicodeToAnsi(wz)); + } + else + { + x = (int)WszSendMessage((HWND)g_hwndAsmInfo,WM_SETTEXT,0, (LPARAM)wz); + } + delete[] wz; + } + } +} + +BOOL GUIAddItemsToList() +{ + DWORD i,NumGlobals=0; + HENUMInternal hEnumMethod; + + RemoveItemsFromList(); + g_NumClassItems = 0; + g_NumNamespaces = 0; + + g_hRoot = AddOneItem( + (HTREEITEM)NULL, + g_pszModule, + (HTREEITEM)TVI_ROOT, + FIELD_IMAGE_INDEX, + g_hwndTreeView, + TRUE + ); + + if (SUCCEEDED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod))) + { + NumGlobals = g_pImport->EnumGetCount(&hEnumMethod); + g_pImport->EnumClose(&hEnumMethod); + } + if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnumMethod))) + { + NumGlobals += g_pImport->EnumGetCount(&hEnumMethod); + g_pImport->EnumClose(&hEnumMethod); + } + (*g_ClassItemList)[0].hItem = g_hRoot; + (*g_ClassItemList)[0].cl = 0; + (*g_ClassItemList)[0].SubItems = NumGlobals+1; + (*g_ClassItemList)[0].CurMember = 0; + (*g_ClassItemList)[0].pMembers = new (nothrow) TreeItem_t[NumGlobals+1]; + g_NumClassItems++; + + //AddInfoItemToClass((HTREEITEM)TVI_ROOT, &(*g_ClassItemList)[0], " M A N I F E S T", "__MANIFEST__"); + AddInfoItemToClass((HTREEITEM)TVI_ROOT, &(*g_ClassItemList)[0], " M A N I F E S T", 0xFFFFFFFF); + + if (g_NumClasses != 0) + { + //create root namespaces + { + char** rszNamespace = new (nothrow) char*[g_NumClasses]; + ULONG ulNamespaces=0; + for (i = 0; i < g_NumClasses; i++) + { + if (g_cl_enclosing[i] == mdTypeDefNil) // nested classes don't have separate namespaces + { + const char *pszClassName, *pszNameSpace; + if (FAILED(g_pImport->GetNameOfTypeDef( + g_cl_list[i], + &pszClassName, + &pszNameSpace))) + { + pszClassName = pszNameSpace = "Invalid TypeDef record"; + } + if ((pszNameSpace != NULL) && (*pszNameSpace != 0)) + { + rszNamespace[ulNamespaces++] = (char*)pszNameSpace; + } + } + } + if (ulNamespaces != 0) + { + qsort(&rszNamespace[0],ulNamespaces,sizeof(char*),stringCmp); + for(i = 0; i < ulNamespaces; i++) FindCreateNamespaceRoot(rszNamespace[i]); + } + delete[] rszNamespace; + } + AddClassesWithEncloser(mdTypeDefNil,NULL); + }// end if (g_NumClasses) + AddGlobalFunctions(); + + WszSendMessage(g_hwndTreeView, TVM_EXPAND, TVE_EXPAND, (LPARAM)g_hRoot); + EnableMenuItem(g_hMenu,(UINT)(UINT_PTR)g_hViewMenu, MF_ENABLED); + EnableMenuItem(g_hFileMenu,IDM_DUMP,MF_ENABLED); + EnableMenuItem(g_hFileMenu,IDM_DUMP_TREE,MF_ENABLED); + DrawMenuBar(g_hwndMain); + + { + WszMultiByteToWideChar(CP_UTF8,0,g_szInputFile,-1,wzUniBuf,2048); + wcscat_s(wzUniBuf,2048,L" - IL DASM"); + for(int cnt=0; cnt<100; cnt++) + { + SendMessageW(g_hwndMain,WM_SETTEXT, 0, (LPARAM)wzUniBuf); + SendMessageW(g_hwndMain,WM_GETTEXT, 2048, (LPARAM)&wzUniBuf[2048]); + wzUniBuf[2047]=0; + if(0 == wcscmp(wzUniBuf,&wzUniBuf[2048])) break; + } + } + + if (IsGuiILOnly()) { + ShowWindow(g_hwndMain, SW_HIDE); + } else { + ShowWindow(g_hwndMain, SW_SHOW); + } + UpdateWindow(g_hwndMain); + //GUIDisassemble(0,0,"MANIFEST"); + g_Mode &= ~MODE_GUI; + DumpManifest(NULL); + g_Mode |= MODE_GUI; + + GUIDumpAssemblyInfo(); + + TreeView_SelectItem(g_hwndTreeView,g_hRoot); + SetFocus(g_hwndTreeView); + return TRUE; +} + + +// +// Find class item by class token +// +ClassItem_t* ClassItemByToken(mdTypeDef cl) +{ + for(ULONG i=0; i < g_NumClassItems; i++) + { + if((*g_ClassItemList)[i].cl == cl) return &(*g_ClassItemList)[i]; + } + return NULL; +} + +// Factored out of AddClassToTreeView for its big stack consumption (AddClassToTreeView is +// called recursively via AddClassesWithEncloser). +static void AddClassToTreeView_PrettyPrintClass(mdTypeRef crType, LPCUTF8 pszFormat, __out_ecount(cBufferSize) char *pszBuffer, size_t cBufferSize) +{ + CQuickBytes out; + sprintf_s(pszBuffer, cBufferSize, pszFormat, PrettyPrintClass(&out, crType, g_pImport)); +} + +// +// Add a class and its members +// +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif +HTREEITEM AddClassToTreeView(HTREEITEM hParent, mdTypeDef cl) +{ + HRESULT hr; + ClassItem_t *pClassItem; + HTREEITEM hClassRoot; + HTREEITEM hNamespaceRoot = hParent; + HTREEITEM hPrimaryInfo; + HTREEITEM hLast; + mdToken *pMemberList = NULL; + HENUMInternal hEnumMethod; // enumerator for method defs + HENUMInternal hEnumField; // enumerator for fields + HENUMInternal hEnumEvent; // enumerator for events + HENUMInternal hEnumProp; // enumerator for properties + DWORD NumMembers; + const char *pszClassName; // name associated with this CL + const char *pszNamespace; + DWORD dwClassAttrs; + mdTypeRef crExtends; + mdInterfaceImpl ii; + DWORD NumInterfaces; + DWORD i; + char *szPrimaryInfo; // public class foo extends bar +// char *szFullClassName; + DWORD SubItems; + const char *pszSuperName = NULL; + HENUMInternal hEnumII; // enumerator for interface impl + mdCustomAttribute *rCA; + ULONG ulCAs; + UINT uImageIndex = CLASS_IMAGE_INDEX; + BOOL bIsEnum = FALSE; + BOOL bIsValueType = FALSE; + BOOL bExtendsSysObject=FALSE; + + if (FAILED(g_pImport->GetNameOfTypeDef( + cl, + &pszClassName, + &pszNamespace))) + { + return FALSE; + } + MAKE_NAME_IF_NONE(pszClassName,cl); + g_pImport->GetTypeDefProps( + cl, + &dwClassAttrs, + &crExtends + ); + if(g_fLimitedVisibility) + { + if(g_fHidePub && (IsTdPublic(dwClassAttrs)||IsTdNestedPublic(dwClassAttrs))) return NULL; + if(g_fHidePriv && (IsTdNotPublic(dwClassAttrs)||IsTdNestedPrivate(dwClassAttrs))) return NULL; + if(g_fHideFam && IsTdNestedFamily(dwClassAttrs)) return NULL; + if(g_fHideAsm && IsTdNestedAssembly(dwClassAttrs)) return NULL; + if(g_fHideFOA && IsTdNestedFamORAssem(dwClassAttrs)) return NULL; + if(g_fHideFAA && IsTdNestedFamANDAssem(dwClassAttrs)) return NULL; + } + hr = g_pImport->EnumInit( + mdtInterfaceImpl, + cl, + &hEnumII); + if (FAILED(hr)) + return FALSE; + + NumInterfaces = g_pImport->EnumGetCount(&hEnumII); + hr = g_pImport->EnumInit(mdtMethodDef, cl, &hEnumMethod); + if (FAILED(hr)) + { + printf("Unable to enum methods\n"); + return FALSE; + } + NumMembers = g_pImport->EnumGetCount(&hEnumMethod); + + hr = g_pImport->EnumInit(mdtFieldDef, cl, &hEnumField); + if (FAILED(hr)) + { + g_pImport->EnumClose(&hEnumMethod); + printf("Unable to enum fields\n"); + return FALSE; + } + NumMembers += g_pImport->EnumGetCount(&hEnumField); + + hr = g_pImport->EnumInit(mdtEvent, cl, &hEnumEvent); + if (FAILED(hr)) + { + g_pImport->EnumClose(&hEnumMethod); + g_pImport->EnumClose(&hEnumField); + printf("Unable to enum events\n"); + return FALSE; + } + NumMembers += g_pImport->EnumGetCount(&hEnumEvent); + + hr = g_pImport->EnumInit(mdtProperty, cl, &hEnumProp); + if (FAILED(hr)) + { + g_pImport->EnumClose(&hEnumMethod); + g_pImport->EnumClose(&hEnumField); + g_pImport->EnumClose(&hEnumEvent); + printf("Unable to enum properties\n"); + return FALSE; + } + NumMembers += g_pImport->EnumGetCount(&hEnumProp); + if (NumMembers > 0) + { + pMemberList = new (nothrow) mdToken[NumMembers]; + if (pMemberList == NULL) + { + // close enum before return + g_pImport->EnumClose(&hEnumMethod); + g_pImport->EnumClose(&hEnumField); + g_pImport->EnumClose(&hEnumEvent); + g_pImport->EnumClose(&hEnumProp); + return FALSE; + } + + for (i = 0; g_pImport->EnumNext(&hEnumField, &pMemberList[i]); i++); + for (; g_pImport->EnumNext(&hEnumMethod, &pMemberList[i]); i++); + for (; g_pImport->EnumNext(&hEnumEvent, &pMemberList[i]); i++); + for (; g_pImport->EnumNext(&hEnumProp, &pMemberList[i]); i++); + _ASSERTE(i == NumMembers); + + } + else + { + pMemberList = NULL; + } + + // Add class root to treeview + SubItems = NumMembers + NumInterfaces + 3; + if (!IsNilToken(crExtends)) + { + LPCSTR szClassName=""; + LPCSTR szNameSpace=""; + SubItems++; + if(TypeFromToken(crExtends)==mdtTypeRef) + { + if (FAILED(g_pImport->GetNameOfTypeRef(crExtends, &szNameSpace, &szClassName))) + { + return FALSE; + } + if(!(strcmp(szNameSpace,"System") || strcmp(szClassName, "Object"))) + { + SubItems--; + bExtendsSysObject = TRUE; + } + } + else if (TypeFromToken(crExtends) == mdtTypeDef) + { + if (FAILED(g_pImport->GetNameOfTypeDef(crExtends, &szClassName, &szNameSpace))) + { + return FALSE; + } + } + + bIsEnum = (!strcmp(szNameSpace,"System"))&&(!strcmp(szClassName,"Enum")); + + bIsValueType = (!strcmp(szNameSpace,"System"))&&(!strcmp(szClassName,"ValueType")) + && (strcmp(pszNamespace,"System") || strcmp(pszClassName,"Enum")); + } + { + HCORENUM hEnum = NULL; + rCA = new (nothrow) mdCustomAttribute[4096]; + g_pPubImport->EnumCustomAttributes(&hEnum, cl, 0, rCA, 4096, &ulCAs); + SubItems += ulCAs; + g_pPubImport->CloseEnum( hEnum); + } + for (i = 0; i < g_NumClasses; i++) + { + if(g_cl_enclosing[i] == cl) SubItems++; + } + + if(IsTdInterface(dwClassAttrs)) uImageIndex = CLASSINT_IMAGE_INDEX; + if(bIsValueType) uImageIndex = CLASSVAL_IMAGE_INDEX; + if(bIsEnum) uImageIndex = CLASSENUM_IMAGE_INDEX; + char *szptr1; + if((*pszNamespace != 0) && g_fTreeViewFCN) + sprintf_s(szString,SZSTRING_SIZE,"%s.",pszNamespace); + else + szString[0] = 0; + strcat_s(szString,SZSTRING_SIZE,pszClassName); + szptr1 = &szString[strlen(szString)]; + // Count the type parameters -- could be too many for GUI + DWORD NumTyPars; + mdGenericParam tkTyPar; + HCORENUM hEnumTyPar = NULL; + unsigned jj; + + for(jj=0; + SUCCEEDED(g_pPubImport->EnumGenericParams(&hEnumTyPar, cl, &tkTyPar, 1, &NumTyPars)) + && (NumTyPars != 0); jj++); + + if (jj > 0) + { + if(jj > 16) + szptr1 += sprintf_s(szptr1,SZSTRING_REMAINING_SIZE(szptr1),"%s%d type parameters%s",LTN(),jj,GTN()); + else + DumpGenericPars(szString,cl); + + uImageIndex = CLASS_GEN_IMAGE_INDEX; + if(IsTdInterface(dwClassAttrs)) uImageIndex = CLASSINT_GEN_IMAGE_INDEX; + if(bIsValueType) uImageIndex = CLASSVAL_GEN_IMAGE_INDEX; + if(bIsEnum) uImageIndex = CLASSENUM_GEN_IMAGE_INDEX; + } + + pClassItem = AddClassToGUI(cl, uImageIndex, pszNamespace, szString, SubItems, &hNamespaceRoot); + if (pClassItem == NULL) + return FALSE; + + hClassRoot = pClassItem->hItem; + + const size_t BUFFER_SIZE = 8192; + szPrimaryInfo = new (nothrow) char[BUFFER_SIZE]; + strcpy_s(szPrimaryInfo, BUFFER_SIZE,".class "); + + if (IsTdInterface(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "interface "); + //else if (IsTdUnmanagedValueType(dwClassAttrs)) strcat(szPrimaryInfo, "not_in_gc_heap value "); + else if (bIsValueType) strcat_s(szPrimaryInfo, BUFFER_SIZE, "value "); + else if (bIsEnum) strcat_s(szPrimaryInfo, BUFFER_SIZE, "enum "); + + if (IsTdPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "public "); + if (IsTdNotPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "private "); + if (IsTdNestedPublic(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested public "); + if (IsTdNestedPrivate(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested private "); + if (IsTdNestedFamily(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested family "); + if (IsTdNestedAssembly(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested assembly "); + if (IsTdNestedFamANDAssem(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested famandassem "); + if (IsTdNestedFamORAssem(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "nested famorassem "); + if (IsTdAbstract(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "abstract "); + if (IsTdAutoLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "auto "); + if (IsTdSequentialLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "sequential "); + if (IsTdExplicitLayout(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "explicit "); + if (IsTdAnsiClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "ansi "); + if (IsTdUnicodeClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "unicode "); + if (IsTdAutoClass(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "autochar "); + if (IsTdImport(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "import "); + if (IsTdWindowsRuntime(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "windowsruntime "); + if (IsTdSerializable(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "serializable "); +// if (IsTdEnum(dwClassAttrs)) strcat(szPrimaryInfo, "enum "); + if (IsTdSealed(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "sealed "); + if (IsTdBeforeFieldInit(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "beforefieldinit "); + if (IsTdSpecialName(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "specialname "); + if (IsTdRTSpecialName(dwClassAttrs)) strcat_s(szPrimaryInfo, BUFFER_SIZE, "rtspecialname "); + + if(g_fDumpTokens) sprintf_s(&szPrimaryInfo[strlen(szPrimaryInfo)], BUFFER_SIZE - strlen(szPrimaryInfo)," /*%08X*/",cl); + hPrimaryInfo = AddInfoItemToClass(hClassRoot, pClassItem, szPrimaryInfo, NULL); + hLast = hPrimaryInfo; + // Now add nodes for extends, implements + if (!IsNilToken(crExtends)) + { + if (!bExtendsSysObject) + { + AddClassToTreeView_PrettyPrintClass(crExtends, " extends %s ", szPrimaryInfo, BUFFER_SIZE); + hLast = AddInfoItemToClass(hLast, pClassItem, szPrimaryInfo, crExtends); + } + } + + if (NumInterfaces > 0) + { + for (i=0; g_pImport->EnumNext(&hEnumII, &ii); i++) + { + mdTypeRef crInterface; + + if (FAILED(g_pImport->GetTypeOfInterfaceImpl(ii, &crInterface))) + { + printf("Unable to get information about interface implementation\n"); + return FALSE; + } + { + AddClassToTreeView_PrettyPrintClass(crInterface, " implements %s ", szPrimaryInfo, BUFFER_SIZE); + hLast = AddInfoItemToClass(hLast, pClassItem, szPrimaryInfo, crInterface); + } + } + + // The assertion will fire if the enumerator is bad + _ASSERTE(NumInterfaces == i); + + // close the enumerator + g_pImport->EnumClose(&hEnumII); + } + delete[] szPrimaryInfo; + + BOOL fDumpRTF = g_fDumpRTF; + g_fDumpRTF = FALSE; + // add info entries for custom attributes + for(i = 0; i < ulCAs; i++) + { + char* pc; + memset(GlobalBuffer,0,GlobalBufferLen); + InGlobalBuffer = 0; + DumpCustomAttribute(rCA[i],(void *)g_hwndTreeView,false); + if(pc = strchr(GlobalBuffer,'\r')) strcpy_s(pc,6," ..."); // until the first <CR> only + //hLast = AddInfoItemToClass(hLast, pClassItem, GlobalBuffer, "#####"); // this "name" is guaranteed to be unique! + hLast = AddInfoItemToClass(hLast, pClassItem, GlobalBuffer, rCA[i]); + } + delete[] rCA; + + // Re-fetch the current class item ptr, dynamic array may have shifted + pClassItem = ClassItemByToken(cl); + + // Add nested classes + AddClassesWithEncloser(cl,pClassItem->hItem); + pClassItem = ClassItemByToken(cl); + + MemberInfo* members = NULL; + if (NumMembers != 0) + { + members = new (nothrow) MemberInfo[NumMembers]; + if (members == NULL) + { + if (pMemberList != NULL) delete[] pMemberList; + return FALSE; + } + } + // do in four passes, fields first + MemberInfo* curMem = members; + for (i = 0; i < NumMembers; i++) + { + if (TypeFromToken(pMemberList[i]) == mdtFieldDef) + { + curMem->token = pMemberList[i]; + if (FAILED(g_pImport->GetFieldDefProps(pMemberList[i], &curMem->dwAttrs))) + { + printf("Invalid FieldDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + if (FAILED(g_pImport->GetNameOfFieldDef(pMemberList[i], &curMem->pszMemberName))) + { + printf("Invalid FieldDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]); + if (FAILED(g_pImport->GetSigOfFieldDef(pMemberList[i], &curMem->cComSig, &curMem->pComSig))) + { + printf("Invalid FieldDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + curMem++; + } + else break; + } + + MemberInfo* endMem = curMem; + if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp); + + for (curMem = members; curMem < endMem;curMem++) + { + if (g_fLimitedVisibility) + { + if(g_fHidePub && IsFdPublic(curMem->dwAttrs)) continue; + if(g_fHidePriv && IsFdPrivate(curMem->dwAttrs)) continue; + if(g_fHideFam && IsFdFamily(curMem->dwAttrs)) continue; + if(g_fHideAsm && IsFdAssembly(curMem->dwAttrs)) continue; + if(g_fHideFOA && IsFdFamORAssem(curMem->dwAttrs)) continue; + if(g_fHideFAA && IsFdFamANDAssem(curMem->dwAttrs)) continue; + if(g_fHidePrivScope && IsFdPrivateScope(curMem->dwAttrs)) continue; + } + AddFieldToGUI(cl, pClassItem, pszNamespace, pszClassName, curMem->pszMemberName, NULL, curMem->token, curMem->dwAttrs); + } + + // methods second + curMem = members; + for (; i < NumMembers; i++) + { + if (TypeFromToken(pMemberList[i]) == mdtMethodDef) + { + curMem->token = pMemberList[i]; + if (FAILED(g_pImport->GetMethodDefProps(pMemberList[i], &curMem->dwAttrs))) + { + printf("Invalid MethodDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + + if (FAILED(g_pImport->GetNameOfMethodDef(pMemberList[i], &curMem->pszMemberName))) + { + printf("Invalid MethodDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]); + if (FAILED(g_pImport->GetSigOfMethodDef(pMemberList[i], &curMem->cComSig, &curMem->pComSig))) + { + printf("Invalid MethodDef %08X record\n", pMemberList[i]); + delete []members; + delete []pMemberList; + return FALSE; + } + curMem++; + } + else break; + } + + endMem = curMem; + if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp); + + for (curMem = members; curMem < endMem;curMem++) + { + if (g_fLimitedVisibility) + { + if(g_fHidePub && IsMdPublic(curMem->dwAttrs)) continue; + if(g_fHidePriv && IsMdPrivate(curMem->dwAttrs)) continue; + if(g_fHideFam && IsMdFamily(curMem->dwAttrs)) continue; + if(g_fHideAsm && IsMdAssem(curMem->dwAttrs)) continue; + if(g_fHideAsm && g_fHideFam && IsMdFamORAssem(curMem->dwAttrs)) continue; + if(g_fHideFAA && IsMdFamANDAssem(curMem->dwAttrs)) continue; + if(g_fHidePrivScope && IsMdPrivateScope(curMem->dwAttrs)) continue; + } + AddMethodToGUI(cl, pClassItem, pszNamespace, pszClassName, curMem->pszMemberName, curMem->pComSig, curMem->cComSig, curMem->token, curMem->dwAttrs); + } + // events third + curMem = members; + for (; i < NumMembers; i++) + { + if (TypeFromToken(pMemberList[i]) == mdtEvent) + { + curMem->token = pMemberList[i]; + if (FAILED(g_pImport->GetEventProps( + curMem->token, + &curMem->pszMemberName, + &curMem->dwAttrs, + (mdToken *)&curMem->pComSig))) + { + curMem->pszMemberName = "Invalid Event record"; + curMem->dwAttrs = 0; + curMem->pComSig = (PCCOR_SIGNATURE)mdTypeDefNil; + } + MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]); + curMem++; + } + else break; + } + + endMem = curMem; + if (g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp); + curMem = members; + while (curMem < endMem) + { + if (g_fLimitedVisibility) + { + HENUMInternal hAssoc; + unsigned nAssoc; + if (FAILED(g_pImport->EnumAssociateInit(curMem->token,&hAssoc))) + { + continue; + } + if (nAssoc = hAssoc.m_ulCount) + { + NewArrayHolder<ASSOCIATE_RECORD> rAssoc = new (nothrow) ASSOCIATE_RECORD[nAssoc]; + if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc))) + { + continue; + } + + for (unsigned i=0; i < nAssoc;i++) + { + if (TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) + { + DWORD dwAttrs; + if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwAttrs))) + { + continue; + } + if(g_fHidePub && IsMdPublic(dwAttrs)) continue; + if(g_fHidePriv && IsMdPrivate(dwAttrs)) continue; + if(g_fHideFam && IsMdFamily(dwAttrs)) continue; + if(g_fHideAsm && IsMdAssem(dwAttrs)) continue; + if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) continue; + if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) continue; + if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) continue; + } + AddEventToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token); + break; + } + } + g_pImport->EnumClose(&hAssoc); + } + else AddEventToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token); + curMem++; + } + // properties fourth + curMem = members; + for (; i < NumMembers; i++) + { + if (TypeFromToken(pMemberList[i]) == mdtProperty) + { + curMem->token = pMemberList[i]; + if (FAILED(g_pImport->GetPropertyProps( + curMem->token, + &curMem->pszMemberName, + &curMem->dwAttrs, + &curMem->pComSig, + &curMem->cComSig))) + { + curMem->pszMemberName = "Invalid Property record"; + curMem->dwAttrs = 0; + curMem->pComSig = NULL; + curMem->cComSig = 0; + } + MAKE_NAME_IF_NONE(curMem->pszMemberName,pMemberList[i]); + curMem++; + } + } + + endMem = curMem; + if(g_fSortByName) qsort(members, endMem - members, sizeof MemberInfo, memberCmp); + curMem = members; + while(curMem < endMem) + { + if (g_fLimitedVisibility) + { + HENUMInternal hAssoc; + unsigned nAssoc; + if (FAILED(g_pImport->EnumAssociateInit(curMem->token,&hAssoc))) + { + continue; + } + if (nAssoc = hAssoc.m_ulCount) + { + NewArrayHolder<ASSOCIATE_RECORD> rAssoc = new (nothrow) ASSOCIATE_RECORD[nAssoc]; + if (FAILED(g_pImport->GetAllAssociates(&hAssoc,rAssoc,nAssoc))) + { + continue; + } + + for (unsigned i=0; i < nAssoc;i++) + { + if (TypeFromToken(rAssoc[i].m_memberdef) == mdtMethodDef) + { + DWORD dwAttrs; + if (FAILED(g_pImport->GetMethodDefProps(rAssoc[i].m_memberdef, &dwAttrs))) + { + continue; + } + if(g_fHidePub && IsMdPublic(dwAttrs)) continue; + if(g_fHidePriv && IsMdPrivate(dwAttrs)) continue; + if(g_fHideFam && IsMdFamily(dwAttrs)) continue; + if(g_fHideAsm && IsMdAssem(dwAttrs)) continue; + if(g_fHideFOA && IsMdFamORAssem(dwAttrs)) continue; + if(g_fHideFAA && IsMdFamANDAssem(dwAttrs)) continue; + if(g_fHidePrivScope && IsMdPrivateScope(dwAttrs)) continue; + } + AddPropToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token); + break; + } + } + g_pImport->EnumClose(&hAssoc); + } + else AddPropToGUI(cl, pClassItem, pszNamespace, pszClassName, dwClassAttrs, curMem->token); + curMem++; + } + g_fDumpRTF = fDumpRTF; + if(pMemberList) delete[] pMemberList; + if(members) delete[] members; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + return hClassRoot; +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +void CreateMenus() +{ + HMENU hMenuPopup; + + g_hMenu = CreateMenu(); + + hMenuPopup = CreateMenu(); + WszAppendMenu(hMenuPopup, MF_STRING, IDM_OPEN, RstrW(IDS_OPEN)); + WszAppendMenu(hMenuPopup, MF_STRING|MF_GRAYED, IDM_DUMP, RstrW(IDS_DUMP)); + WszAppendMenu(hMenuPopup, MF_STRING|MF_GRAYED, IDM_DUMP_TREE, RstrW(IDS_DUMPTREE)); + WszAppendMenu(hMenuPopup, MF_STRING, IDM_EXIT, RstrW(IDS_EXIT)); + WszAppendMenu(g_hMenu, MF_POPUP, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_FILE)); + g_hFileMenu = hMenuPopup; + + hMenuPopup = CreateMenu(); + g_hFontMenu = CreateMenu(); + WszAppendMenu(hMenuPopup,MF_POPUP,(UINT)(UINT_PTR)g_hFontMenu,RstrW(IDS_FONTS)); + WszAppendMenu(g_hFontMenu,MF_STRING,IDM_FONT_TREE,RstrW(IDS_FONT_TREE)); + WszAppendMenu(g_hFontMenu,MF_STRING,IDM_FONT_DASM,RstrW(IDS_FONT_DASM)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fSortByName ? MF_CHECKED : MF_UNCHECKED), IDM_SORT_BY_NAME, RstrW(IDS_SORT_BY_NAME)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fTreeViewFCN ? MF_CHECKED : MF_UNCHECKED), IDM_TREEVIEWFCN, RstrW(IDS_TREEVIEWFCN)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fCAVerbal ? MF_CHECKED : MF_UNCHECKED), IDM_CAVERBAL, RstrW(IDS_CAVERBAL)); + //WszAppendMenu(hMenuPopup, MF_STRING|(g_fDumpRTF ? MF_CHECKED : MF_UNCHECKED), IDM_DUMPRTF, RstrW(IDS_DUMPRTF)); + // MF_SEPARATOR ==> last 2 params ignored + WszAppendMenu(hMenuPopup, MF_SEPARATOR,0,NULL); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePub ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PUB, RstrW(IDS_SHOW_PUB)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePriv ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PRIV, RstrW(IDS_SHOW_PRIV)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFam ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FAM, RstrW(IDS_SHOW_FAM)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideAsm ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_ASM, RstrW(IDS_SHOW_ASM)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFAA ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FAA, RstrW(IDS_SHOW_FAA)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHideFOA ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_FOA, RstrW(IDS_SHOW_FOA)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fHidePrivScope ? MF_CHECKED : MF_UNCHECKED), IDM_SHOW_PSCOPE, RstrW(IDS_SHOW_PSCOPE)); + WszAppendMenu(hMenuPopup, MF_SEPARATOR,0,NULL); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fFullMemberInfo ? MF_CHECKED : MF_UNCHECKED), IDM_FULL_INFO, RstrW(IDS_FULL_INFO)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fShowBytes ? MF_CHECKED : MF_UNCHECKED), IDM_BYTES, RstrW(IDS_BYTES)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fDumpTokens ? MF_CHECKED : MF_UNCHECKED), IDM_TOKENS, RstrW(IDS_TOKENS)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fShowSource ? MF_CHECKED : MF_UNCHECKED), IDM_SOURCELINES, RstrW(IDS_SOURCELINES)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fQuoteAllNames ? MF_CHECKED : MF_UNCHECKED), IDM_QUOTEALLNAMES, RstrW(IDS_QUOTEALLNAMES)); + WszAppendMenu(hMenuPopup, MF_STRING|(g_fTryInCode ? MF_CHECKED : MF_UNCHECKED), IDM_EXPANDTRY, RstrW(IDS_EXPANDTRY)); + if(g_fTDC) + { + + WszAppendMenu(hMenuPopup, MF_STRING, IDM_SHOW_HEADER, RstrW(IDS_SHOW_HEADER)); + WszAppendMenu(hMenuPopup, MF_STRING, IDM_SHOW_STAT, RstrW(IDS_SHOW_STAT)); + g_hMetaInfoMenu = CreateMenu(); + //MENUINFO mi; + //GetMenuInfo(g_hMetaInfoMenu,&mi); + //mi.dwStyle |= MNS_MODELESS; + //SetMenuInfo(g_hMetaInfoMenu,&mi); + WszAppendMenu(hMenuPopup, MF_POPUP, (UINT)(UINT_PTR)g_hMetaInfoMenu, RstrW(IDS_METAINFO)); + + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEX,RstrW(IDS_MI_HEX)); + WszAppendMenu(g_hMetaInfoMenu,MF_SEPARATOR,0,NULL); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpCSV ? MF_CHECKED : MF_UNCHECKED),IDM_MI_CSV,RstrW(IDS_MI_CSV)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpHeader ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEADER,RstrW(IDS_MI_HEADER)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpSchema ? MF_CHECKED : MF_UNCHECKED),IDM_MI_SCHEMA,RstrW(IDS_MI_SCHEMA)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpRaw ? MF_CHECKED : MF_UNCHECKED),IDM_MI_RAW,RstrW(IDS_MI_RAW)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? MF_CHECKED : MF_UNCHECKED),IDM_MI_HEAPS,RstrW(IDS_MI_HEAPS)); + WszAppendMenu(g_hMetaInfoMenu,MF_SEPARATOR,0,NULL); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpUnsat ? MF_CHECKED : MF_UNCHECKED),IDM_MI_UNREX,RstrW(IDS_MI_UNREX)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING|(g_ulMetaInfoFilter & MDInfo::dumpValidate ? MF_CHECKED : MF_UNCHECKED),IDM_MI_VALIDATE,RstrW(IDS_MI_VALIDATE)); + WszAppendMenu(g_hMetaInfoMenu,MF_STRING,IDM_SHOW_METAINFO,RstrW(IDS_SHOW_METAINFO)); + } + WszAppendMenu(g_hMenu, MF_POPUP|MF_GRAYED, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_VIEW)); + g_hViewMenu = hMenuPopup; + hMenuPopup = CreateMenu(); + WszAppendMenu(hMenuPopup, MF_STRING, IDM_HELP,RstrW(IDS_HELP)); + WszAppendMenu(hMenuPopup, MF_STRING, IDM_ABOUT,RstrW(IDS_ABOUT)); + WszAppendMenu(g_hMenu, MF_POPUP, (UINT)(UINT_PTR)hMenuPopup, RstrW(IDS_HELP)); +} + +BOOL LoadImages() +{ + int i; + + g_hImageList = ImageList_Create(BITMAP_WIDTH, BITMAP_HEIGHT, ILC_COLOR8, LAST_IMAGE_INDEX, 1); + if (g_hImageList == NULL) + return FALSE; + + _ASSERTE(g_hResources != NULL); + for (i = 0; i < LAST_IMAGE_INDEX; i++) + { + g_hBitmaps[i] = (HBITMAP) WszLoadImage( + g_hResources, + MAKEINTRESOURCE(i + IDB_CLASS), + IMAGE_BITMAP, + 15, + 15, + LR_LOADTRANSPARENT //LR_DEFAULTCOLOR + ); + if (g_hBitmaps[i] == NULL) + return FALSE; + int index = ImageList_Add(g_hImageList, g_hBitmaps[i], NULL); + if (index != i) + return FALSE; + } + + return TRUE; +} +// Local functions for font persistence: +char* FontSaveFileName() +{ + static char szFileName[MAX_PATH]; + static BOOL bInit = TRUE; + if(bInit) + { + (void)GetWindowsDirectoryA(szFileName,MAX_PATH); + if(szFileName[strlen(szFileName)-1]!='\\') strcat_s(szFileName,MAX_PATH,"\\"); + strcat_s(szFileName,MAX_PATH,"ildasmfnt.bin"); + bInit = FALSE; + } + return szFileName; +} +BOOL LoadGUIFonts(GUI_Info* pguiInfo) +{ + FILE* pF = NULL; + BOOL ret = FALSE; + int dummy; + if(fopen_s(&pF,FontSaveFileName(),"rb")==0) + { + ret = (fread(pguiInfo->plfDasm,sizeof(LOGFONTW),1,pF) && fread(pguiInfo->plfTree,sizeof(LOGFONTW),1,pF)); + if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->x = dummy; + if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->y = dummy; + if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->w = dummy; + if(fread(&dummy,sizeof(int),1,pF)) pguiInfo->h = dummy; + if(fread(&dummy,sizeof(int),1,pF)) g_fTreeViewFCN = (dummy != 0); + if(fread(&dummy,sizeof(int),1,pF)) g_fSortByName = (dummy != 0); + if(fread(&dummy,sizeof(int),1,pF)) g_fFullMemberInfo = (dummy != 0); + + fclose(pF); + } + return ret; +} +BOOL SaveGUIFonts(GUI_Info* pguiInfo) +{ + FILE* pF=NULL; + BOOL ret = FALSE; + int dummyFCN = (g_fTreeViewFCN ? 1:0); + int dummySBN = (g_fSortByName ? 1:0); + int dummyFMI = (g_fFullMemberInfo ? 1:0); + if(fopen_s(&pF,FontSaveFileName(),"wb")==0) + { + ret = (fwrite(pguiInfo->plfDasm,sizeof(LOGFONTW),1,pF) + && fwrite(pguiInfo->plfTree,sizeof(LOGFONTW),1,pF) + && fwrite(&(pguiInfo->x),sizeof(int),1,pF) + && fwrite(&(pguiInfo->y),sizeof(int),1,pF) + && fwrite(&(pguiInfo->w),sizeof(int),1,pF) + && fwrite(&(pguiInfo->h),sizeof(int),1,pF) + && fwrite(&dummyFCN,sizeof(int),1,pF) + && fwrite(&dummySBN,sizeof(int),1,pF) + && fwrite(&dummyFMI,sizeof(int),1,pF) + ); + fclose(pF); + } + return ret; +} +// Init various GUI variables, get handles +// if InitGUI returns FALSE, ildasm exits +#define DEFAULT_FONTS +BOOL InitGUI() +{ + INITCOMMONCONTROLSEX InitInfo; +#ifdef DEFAULT_FONTS + LOGFONTW strDefaultLogFontDasm = {-14,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FIXED_PITCH | FF_MODERN,L"Fixedsys"}; + LOGFONTW strDefaultLogFontTree = {-11,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,VARIABLE_PITCH | FF_SWISS,L"Tahoma"}; + LOGFONTA strDefaultLogFontDasmA = {-14,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,FIXED_PITCH | FF_MODERN,"Fixedsys"}; + LOGFONTA strDefaultLogFontTreeA = {-11,0,0,0,FW_REGULAR,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,VARIABLE_PITCH | FF_SWISS,"Tahoma"}; +#endif + g_DisasmBox = new DynamicArray<DisasmBox_t>; + g_ClassItemList = new DynamicArray<ClassItem_t>; + g_NamespaceList = new DynamicArray<Namespace_t>; + WszLoadLibrary(L"riched20.dll"); + + InitInfo.dwSize = sizeof(InitInfo); + InitInfo.dwICC = ICC_LISTVIEW_CLASSES; + + if (InitCommonControlsEx(&InitInfo) == FALSE) + return FALSE; + + g_hInstance = WszGetModuleHandle(NULL); + g_hResources = LoadLocalizedResourceDLLForSDK(L"ildasmrc.dll"); + + //--------- get logical fonts +#ifdef DEFAULT_FONTS + if(!LoadGUIFonts(&guiInfo)) + { + memcpy(&g_strLogFontDasm,&strDefaultLogFontDasm,sizeof(LOGFONTW)); + memcpy(&g_strLogFontTree,&strDefaultLogFontTree,sizeof(LOGFONTW)); + } + if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; } + // -------- create font for disassembly window + g_hFixedFont = CreateFontIndirectW(&g_strLogFontDasm); + // -------- create font for tree view + g_hSmallFont = CreateFontIndirectW(&g_strLogFontTree); +#else + if(LoadGUIFonts(&guiInfo)) + { + if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; } + // -------- create font for disassembly window + g_hFixedFont = CreateFontIndirect(&g_strLogFontDasm); + // -------- create font for tree view + g_hSmallFont = CreateFontIndirect(&g_strLogFontTree); + } + else + { + g_hFixedFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); + g_hSmallFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + } +#endif + if (g_hFixedFont == NULL) return FALSE; + if (g_hSmallFont == NULL) return FALSE; + + memset(&g_strChFontDasm,0,sizeof(CHOOSEFONT)); + g_strChFontDasm.lStructSize = sizeof(CHOOSEFONT); + g_strChFontDasm.lpLogFont = &g_strLogFontDasm; + g_strChFontDasm.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |CF_SHOWHELP; + if(!g_fDumpRTF) g_strChFontDasm.Flags |= CF_EFFECTS; // no color change option for RTF output! + g_strChFontDasm.rgbColors = GetSysColor(COLOR_INFOTEXT); + + memset(&g_strChFontTree,0,sizeof(CHOOSEFONTW)); + g_strChFontTree.lStructSize = sizeof(CHOOSEFONTW); + g_strChFontTree.lpLogFont = &g_strLogFontTree; + g_strChFontTree.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS |CF_SHOWHELP /*| CF_EFFECTS*/; + g_strChFontTree.rgbColors = GetSysColor(COLOR_WINDOWTEXT); + + g_hWhiteBrush = (HBRUSH) GetStockObject(WHITE_BRUSH); + if (g_hWhiteBrush == NULL) + return FALSE; + + if (LoadImages() == FALSE) + return FALSE; + + if (RegisterWindowClasses() == FALSE) + return FALSE; +#undef RegisterWindowMessageW + g_uFindReplaceMsg = RegisterWindowMessageW(FINDMSGSTRING); + + CreateMenus(); + + return TRUE; +} + +void DestroyGUI() +{ + SDELETE(g_DisasmBox); + SDELETE(g_ClassItemList); + SDELETE(g_NamespaceList); +} +// +// Set the font of a particular window to the global fixed size font +// +void SetWindowFontFixed(HWND hwnd) +{ + WszSendMessage( + hwnd, + WM_SETFONT, + (LPARAM) g_hFixedFont, + FALSE + ); +} + + +// +// Set the char dimensions variables +// +void SetCharDimensions(HWND hwnd) +{ + if (InterlockedIncrement(&g_SetCharDimensions) == 1) + { + HDC hdc; + TEXTMETRIC tm; + + hdc = GetDC(hwnd); + + GetTextMetrics(hdc, &tm); + + g_MaxCharWidth = tm.tmAveCharWidth; + g_Height = tm.tmHeight; + + ReleaseDC(hwnd, hdc); + } + else + { + // Already set + InterlockedDecrement(&g_SetCharDimensions); + } +} + + +// +// Given a member handle and a class item, find the TreeItem for that member +// +TreeItem_t *FindMemberInClass(ClassItem_t *pClassItem, HTREEITEM hMember) +{ + DWORD i; + + for (i = 0; i < pClassItem->SubItems; i++) + { + if (pClassItem->pMembers[i].hItem == hMember) + return &pClassItem->pMembers[i]; + } + + return NULL; +} + + +// +// Register the window classes +// +BOOL RegisterWindowClasses() +{ + _ASSERTE(g_hResources != NULL); + WNDCLASSW wndClass; + + wndClass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wndClass.lpfnWndProc = DisassemblyWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = g_hInstance; + wndClass.hIcon = WszLoadIcon(g_hResources,MAKEINTRESOURCE(IDI_ICON2)); + wndClass.hCursor = NULL; + wndClass.hbrBackground = g_hWhiteBrush; + wndClass.lpszMenuName = NULL; + wndClass.lpszClassName = DISASSEMBLY_CLASS_NAMEW; + if (WszRegisterClass((WNDCLASSW*)(&wndClass)) == 0) + return FALSE; + + wndClass.style = CS_DBLCLKS|CS_HREDRAW|CS_VREDRAW; + wndClass.lpfnWndProc = MainWndProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = 0; + wndClass.hInstance = g_hInstance; + wndClass.hIcon = WszLoadIcon(g_hResources,MAKEINTRESOURCE(IDI_ICON2)); + wndClass.hCursor = NULL; + wndClass.hbrBackground = g_hWhiteBrush; + wndClass.lpszMenuName = NULL; + + wndClass.lpszClassName = MAIN_WINDOW_CLASSW; + if (WszRegisterClass((WNDCLASSW*)(&wndClass)) == 0) + return FALSE; + return TRUE; +} + +// +// Dump one item to global buffer +// +void GUIDumpItemToDisassemblyEditBox(void*pvDLB, mdToken cl, mdToken mbMember) +{ + const char * pszClassName; + const char * pszNamespace; + mdTypeRef crExtends; + DWORD dwClassAttrs; + + if ((cl != mdTokenNil)&&TypeFromToken(mbMember)) + { + if (FAILED(g_pImport->GetNameOfTypeDef(cl, &pszClassName, &pszNamespace))) + { + pszClassName = pszNamespace = "Invalid TypeDef record"; + } + MAKE_NAME_IF_NONE(pszClassName,cl); + } + else + { + pszClassName = (TypeFromToken(mbMember) == mdtMethodDef) ? "Global Functions" : "Global Fields"; + } + memset(GlobalBuffer,0,GlobalBufferLen); + InGlobalBuffer = 0; + + if (TypeFromToken(mbMember) && cl && (cl != mdTypeDefNil)) + { + if (FAILED(g_pImport->GetTypeDefProps(cl, &dwClassAttrs, &crExtends))) + { + dwClassAttrs = 0; + crExtends = mdTypeDefNil; + } + } + g_Mode |= MODE_GUI; + //_ASSERTE(0); + mdToken tkVarOwner = g_tkVarOwner; + g_tkVarOwner = cl; + if(g_fDumpRTF) DumpRTFPrefix(pvDLB,FALSE); + switch (TypeFromToken(mbMember)) + { + case 0: + switch(cl) + { + case 0: + DumpManifest(pvDLB); + DumpTypedefs(pvDLB); + break; + case IDM_SHOW_HEADER: + DumpHeader(g_CORHeader,pvDLB); + DumpHeaderDetails(g_CORHeader,pvDLB); + break; + case IDM_SHOW_METAINFO: + DumpMetaInfo(g_wszFullInputFile,NULL,pvDLB); + break; + case IDM_SHOW_STAT: + DumpStatistics(g_CORHeader,pvDLB); + break; + } + break; + + case mdtTypeDef: + DumpClass(mbMember,VAL32(g_CORHeader->EntryPointToken), pvDLB, 1); //1 = title+size+pack+custom attributes + break; + case mdtFieldDef: + { + ULONG ul1,ul2; + GetClassLayout(cl,&ul1,&ul2); + DumpField(mbMember,pszClassName, pvDLB, TRUE); + } + break; + case mdtMethodDef: + DumpMethod(mbMember,pszClassName,VAL32(g_CORHeader->EntryPointToken), pvDLB, TRUE); + break; + case mdtEvent: + DumpEvent(mbMember,pszClassName, dwClassAttrs, pvDLB, TRUE); + break; + case mdtProperty: + DumpProp(mbMember,pszClassName, dwClassAttrs, pvDLB, TRUE); + break; + } + if(g_fDumpRTF) DumpRTFPostfix(pvDLB); + g_tkVarOwner = tkVarOwner; + if(g_uCodePage==0xFFFFFFFF) + { + SendMessageW((HWND)pvDLB,WM_SETTEXT,0, (LPARAM)GlobalBuffer); + } + else + { + UINT32 L = (UINT32)strlen(GlobalBuffer); + WCHAR* wz = new (nothrow) WCHAR[L+4]; + if(wz) + { + memset(wz,0,sizeof(WCHAR)*(L+2)); + int x = WszMultiByteToWideChar(CP_UTF8,0,GlobalBuffer,-1,wz,L+2); + if(g_fDumpRTF) + { + x = (int)SendMessageA((HWND)pvDLB,WM_SETTEXT,0, (LPARAM)UnicodeToAnsi(wz)); + } + else + { + SETTEXTEX ste; + ste.flags = ST_DEFAULT; + ste.codepage = 1200; + x = (int)WszSendMessage((HWND)pvDLB,EM_SETTEXTEX,(WPARAM)&ste, (LPARAM)wz); + } + delete[] wz; + } + } +} + +// +// Disassemble the given method in a new window +// + +HWND GUIDisassemble(mdTypeDef cl, mdToken mbMember, __in __nullterminated char *pszNiceMemberName) +{ + HWND hwndDisassemblyMain; + HWND hwndDisassemblyListBox; + const char * pszClassName; + const char * pszNamespace; + char* szTemp=NULL; + RECT rcl; + static char szsz[4096]; + bool fUpdate = false; + bool fMetaInfo = (TypeFromToken(mbMember)==0)&&(cl==IDM_SHOW_METAINFO); + BOOL fDumpRTF = g_fDumpRTF; + if(fMetaInfo) g_fDumpRTF = FALSE; + + //before we even try, check if this member's disasm box is already opened + DisasmBox_t* pDisasmBox = FindDisasmBox(cl, mbMember); + if(pDisasmBox) + { + if(fMetaInfo || (0 == strcmp(pszNiceMemberName,"UpdateThisDisassemblyBox"))) + { + fUpdate = true; + } + else + { + PostMessageA(pDisasmBox->hwndContainer,WM_ACTIVATE,WA_CLICKACTIVE,0); + PostMessageA(pDisasmBox->hwndContainer,WM_SETFOCUS,0,0); + return pDisasmBox->hwndContainer; + } + } + if(fUpdate) + { + SendMessageW(pDisasmBox->hwndContainer,WM_GETTEXT, 0, (LPARAM)szsz); + strcpy_s(szsz,4096,UnicodeToUtf((WCHAR*)szsz)); + + szTemp = szsz; + PostMessageA(pDisasmBox->hwndContainer,WM_CLOSE,1,0); + } + else + { + // Prepend class name to nicely formatted member name + if (mbMember != 0) + { + if (cl != mdTokenNil) + { + if (FAILED(g_pImport->GetNameOfTypeDef( + cl, + &pszClassName, + &pszNamespace))) + { + pszClassName = pszNamespace = "Invalid TypeDef record"; + } + MAKE_NAME_IF_NONE(pszClassName,cl); + if(*pszNamespace != 0) + sprintf_s(szsz,4096,"%s.",pszNamespace); + else + szsz[0] = 0; + strcat_s(szsz,4096,pszClassName); + pszClassName = (const char*)&szsz[0]; + } + else + { + pszClassName = (TypeFromToken(mbMember) == mdtMethodDef) ? "Global Functions" : "Global Fields"; + } + szTemp = new (nothrow) char[strlen(pszClassName)+strlen(pszNiceMemberName)+4]; + if(szTemp) sprintf_s(szTemp, strlen(pszClassName)+strlen(pszNiceMemberName)+4,"%s::%s", pszClassName, pszNiceMemberName); + _ASSERTE(TypeFromToken(mbMember) & (mdtMethodDef|mdtEvent|mdtProperty|mdtTypeDef|mdtFieldDef)); + } + if(!szTemp) szTemp = pszNiceMemberName; + } + _ASSERTE(szTemp); + + HMENU hMenu = CreateMenu(); + WszAppendMenu(hMenu, MF_STRING, IDM_FIND, RstrW(IDS_FIND)); + WszAppendMenu(hMenu, MF_STRING, IDM_FINDNEXT, RstrW(IDS_FINDNEXT)); + + hwndDisassemblyMain = WszCreateWindowEx( + WS_EX_CLIENTEDGE, + DISASSEMBLY_CLASS_NAMEW, + UtfToUnicode(szTemp), + WS_OVERLAPPEDWINDOW | WS_SIZEBOX, + CW_USEDEFAULT, + CW_USEDEFAULT, + 640, + 400, + NULL, + hMenu, // menu + g_hInstance, // hinst + NULL + ); + SendMessageW(hwndDisassemblyMain,WM_SETTEXT, 0, (LPARAM)(UtfToUnicode(szTemp))); + + if((!fUpdate) && szTemp &&(szTemp != pszNiceMemberName)) delete[] szTemp; + if (hwndDisassemblyMain == NULL) + { + g_fDumpRTF = fDumpRTF; + return NULL; + } + GetClientRect(hwndDisassemblyMain, &rcl); + + hwndDisassemblyListBox = WszCreateWindowEx( + 0, + (!g_fDumpRTF) ? L"RichEdit20W" : L"RichEdit20A", + RstrW(IDS_TEXTTOOLARGEFORGUI), + WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE + | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL, + rcl.left, + rcl.top, + rcl.right - rcl.left, + rcl.bottom - rcl.top, + hwndDisassemblyMain, + (HMENU) ID_LISTBOX, + g_hInstance, // hinst + NULL + ); + + DWORD e = GetLastError(); + _ASSERTE(hwndDisassemblyListBox); + if (hwndDisassemblyListBox == NULL) + { + DestroyWindow(hwndDisassemblyMain); + return NULL; + } + + if(fUpdate) + { + UpdateDisasmBox(pDisasmBox, hwndDisassemblyMain, hwndDisassemblyListBox, hMenu); + } + else + AddDisasmBox(hwndDisassemblyMain, hwndDisassemblyListBox, hMenu, cl, mbMember); + + SendMessage(hwndDisassemblyListBox,EM_SETTEXTMODE,TM_RICHTEXT|TM_MULTICODEPAGE,0); + SendMessage(hwndDisassemblyListBox,EM_SETBKGNDCOLOR,0,GetSysColor(COLOR_INFOBK)); + SetWindowFontFixed(hwndDisassemblyListBox); + SetCharDimensions(hwndDisassemblyListBox); + + GUIDumpItemToDisassemblyEditBox((void *)hwndDisassemblyListBox,cl,mbMember); + + ShowWindow(hwndDisassemblyMain, SW_SHOWNORMAL); + UpdateWindow(hwndDisassemblyMain); + + g_fDumpRTF = fDumpRTF; + return hwndDisassemblyMain; +} + +// +// Callback by the disassembler to add another entry to the disassembly window +// +void GUIAddOpcode(__inout_opt __nullterminated const char *pszString, __in_opt void *GUICookie) +{ + if(pszString) + { + ULONG L = (g_uCodePage == 0xFFFFFFFF) ? (ULONG)(wcslen((WCHAR*)pszString)*sizeof(WCHAR)) : (ULONG)strlen(pszString); + if(InGlobalBuffer+L >= GlobalBufferLen-4) + { + ULONG LL = ((L >> 12)+1)<<12; + char *pch = new (nothrow) char[GlobalBufferLen + LL]; + if(pch) + { + memcpy(pch,GlobalBuffer,InGlobalBuffer+1); + delete[] GlobalBuffer; + GlobalBuffer = pch; + GlobalBufferLen += LL; + } + } + if(g_uCodePage == 0xFFFFFFFF) + { + if(g_fDumpRTF) + { + swprintf_s((WCHAR*)&GlobalBuffer[InGlobalBuffer], (GlobalBufferLen-InGlobalBuffer)/sizeof(WCHAR), L"%s\\line\r\n",(WCHAR*)pszString); + InGlobalBuffer += L+14; + } + else + { + swprintf_s((WCHAR*)&GlobalBuffer[InGlobalBuffer], (GlobalBufferLen-InGlobalBuffer)/sizeof(WCHAR), L"%s\r\n",(WCHAR*)pszString); + InGlobalBuffer += L+4; + } + } + else + { + if(g_fDumpRTF) + { + sprintf_s(&GlobalBuffer[InGlobalBuffer],GlobalBufferLen-InGlobalBuffer,"%s\\line\r\n",pszString); + InGlobalBuffer += L+7; + } + else + { + sprintf_s(&GlobalBuffer[InGlobalBuffer],GlobalBufferLen-InGlobalBuffer,"%s\r\n",pszString); + InGlobalBuffer += L+2; + } + } + } + else + { + delete[] GlobalBuffer; + GlobalBufferLen = 0; + InGlobalBuffer = 0; + } +} + +// +// Someone has double clicked on an item +// +// It could be a method (diassemble it), or a field (ignore it), or an "extends" or "implements" +// component, in which case we select that component if available. +// +HWND DoubleClickSelectedMember(HTREEITEM hItem) +{ + HTREEITEM hClass; + ClassItem_t *pClassItem; + + static HCURSOR hWaitCursor = NULL; + + if (hWaitCursor == NULL) + hWaitCursor = WszLoadCursor(NULL,IDC_WAIT); + + // + // It could be any item, but assume it's a member item or class info and find its parent + // + hClass = TreeView_GetParent(g_hwndTreeView, hItem); + if (hClass == NULL) + return NULL; + + // + // Find the class item given the HTREEITEM + // (will return NULL if hClass is not really a class item) + // + pClassItem = FindClassItem(hClass); + if (pClassItem != NULL) + { + // Which subitem was it? + TreeItem_t *pItem = FindMemberInClass(pClassItem, hItem); + + if (pItem == NULL) + return NULL; + + if (pItem->Discriminator == TREEITEM_TYPE_MEMBER) + { + TVITEMA SelItem; + char* szText; + // Must be a method, event or property + switch (TypeFromToken(pItem->mbMember)) + { + case mdtMethodDef: + case mdtEvent: + case mdtProperty: + case mdtFieldDef: + break; + default: + return NULL; + } + + + // Get the name of this item so that we can title the disassembly window + szText = new (nothrow) char[8192]; + if(szText) + { + memset(&SelItem, 0, sizeof(SelItem)); + SelItem.mask = TVIF_TEXT; + SelItem.pszText = szText; + SelItem.hItem = pItem->hItem; + SelItem.cchTextMax = 8192; + + WCHAR* wzText = (WCHAR*)szText; + SelItem.cchTextMax /= sizeof(WCHAR); + SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem); + unsigned L = ((unsigned)wcslen(wzText)+1)*3; + char* szUTFText = new (nothrow) char[L]; + if(szUTFText) + { + memset(szUTFText,0,L); + WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL); + delete[] wzText; + szText = szUTFText; + } + } + HCURSOR hWasCursor = SetCursor(hWaitCursor); + + HWND hRet = GUIDisassemble(pClassItem->cl, pItem->mbMember, szText? szText : ""); + if(szText) delete[] szText; + + SetCursor(hWasCursor); + + return hRet; + } + else if (pItem->Discriminator == TREEITEM_TYPE_INFO) + { + if(pItem->mbMember) + { + if(pItem->mbMember != 0xFFFFFFFF) + { + // We've clicked on an "extends X" or "implements Y", so select that class + SelectClassByToken(pItem->mbMember); + } + else + { + HCURSOR hWasCursor = SetCursor(hWaitCursor); + + HWND hRet = GUIDisassemble(0, 0, "MANIFEST"); + + SetCursor(hWasCursor); + return hRet; + } + } + else + { + TVITEMA SelItem; + char* szText = new (nothrow) char[8192]; + if(szText) + { + // Get the name of this item so that we can title the disassembly window + memset(&SelItem, 0, sizeof(SelItem)); + SelItem.mask = TVIF_TEXT; + SelItem.pszText = szText; + SelItem.hItem = pItem->hItem; + SelItem.cchTextMax = 8192; + + WCHAR* wzText = (WCHAR*)szText; + SelItem.cchTextMax /= sizeof(WCHAR); + SendMessageW(g_hwndTreeView, TVM_GETITEMW, 0, (LPARAM) (LPTVITEMW) &SelItem); + unsigned L = ((unsigned)wcslen(wzText)+1)*3; + char* szUTFText = new (nothrow) char[L]; + memset(szUTFText,0,L); + WszWideCharToMultiByte(CP_UTF8,0,wzText,-1,szUTFText,L,NULL,NULL); + delete[] wzText; + szText = szUTFText; + } + HCURSOR hWasCursor = SetCursor(hWaitCursor); + + HWND hRet = GUIDisassemble(pClassItem->cl, pClassItem->cl, szText ? szText : ""); + if(szText) delete[] szText; + + SetCursor(hWasCursor); + + return hRet; + } + } + } + return NULL; +} + + +void SelectClassByName(__in __nullterminated char *pszFQName) +{ + ClassItem_t *pDestItem; + + // Find namespace + char *p = ns::FindSep(pszFQName); + if (p == NULL) + { + pDestItem = FindClassItem(NULL, pszFQName); + } + else + { + char szBuffer[MAX_CLASSNAME_LENGTH]; + strncpy_s(szBuffer, MAX_CLASSNAME_LENGTH,pszFQName, p - pszFQName); + szBuffer[ p - pszFQName ] = '\0'; + pDestItem = FindClassItem(szBuffer, p+1); + } + + if (pDestItem != NULL) + { + SendMessageA(g_hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM) (LPTVITEM) pDestItem->hItem); + } +} + +void SelectClassByToken(mdToken tk) +{ + if(TypeFromToken(tk)==mdtTypeDef) + { + ClassItem_t *pDestItem; + if(pDestItem = FindClassItem(tk)) + { + SendMessageA(g_hwndTreeView, TVM_SELECTITEM, TVGN_CARET, (LPARAM) (LPTVITEM) pDestItem->hItem); + } + } +} + +// +// Text search in rich text edit +// +void FindTextInListbox(HWND hwnd, FINDREPLACEW* lpfr) +{ + HWND hwndLB = FindAssociatedDisassemblyListBox(hwnd); + if(hwndLB) + { + FINDTEXTW strFind; + DWORD bgn,end; + SendMessage(hwndLB,EM_GETSEL,(WPARAM)&bgn,(LPARAM)&end); + if(lpfr->Flags & FR_DOWN) + { + strFind.chrg.cpMin=end; + strFind.chrg.cpMax=-1; + } + else + { + strFind.chrg.cpMin=bgn; + strFind.chrg.cpMax=0; + } + strFind.lpstrText=lpfr->lpstrFindWhat; + int pos = (int)SendMessage(hwndLB,EM_FINDTEXTW,(WPARAM)(lpfr->Flags),(LPARAM)&strFind); + if(pos >= 0) + { + //char sz[32]; + //sprintf(sz,"%d:%d",strFind.chrg.cpMin,strFind.chrg.cpMax); + //MessageBox(hwnd,sz,"Find",MB_OK); + SendMessage(hwndLB,EM_SETSEL,(WPARAM)pos,(LPARAM)(pos+wcslen(lpfr->lpstrFindWhat))); + } + } +} + +// +// Disassembly window(s) WndProc +// +LRESULT CALLBACK DisassemblyWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam +) +{ + static HBRUSH hBrush=NULL; + COLORREF crBackGr; + + static COLORREF crBackGrOld=NULL; + + if (crBackGrOld == NULL) + crBackGrOld = GetSysColor(COLOR_INFOBK); + + if(uMsg== g_uFindReplaceMsg) + { + FINDREPLACEW* lpfr = (FINDREPLACEW*)lParam; + if(!(lpfr->Flags & FR_DIALOGTERM)) + { + FindTextInListbox(hwnd,lpfr); + } + } + else + switch (uMsg) + { + case WM_CREATE: + hBrush = CreateSolidBrush(RGB(255,255,255)); + break; + + //===== Sent by Static (label) and Read-Only Edit field ===== + case WM_CTLCOLORSTATIC: + case WM_CTLCOLOREDIT: + if(hBrush) DeleteObject(hBrush); + crBackGr = GetSysColor(COLOR_INFOBK); + hBrush = CreateSolidBrush(crBackGr); + SetBkColor((HDC) wParam, crBackGr); + if(crBackGr != crBackGrOld) + { + g_strChFontDasm.rgbColors = GetSysColor(COLOR_INFOTEXT); + crBackGrOld = crBackGr; + } + SetTextColor((HDC) wParam, g_strChFontDasm.rgbColors); + return (LRESULT) hBrush; + + //====== Sent by active Edit field ============ + //case WM_CTLCOLOREDIT: + // if(hBrush) DeleteObject(hBrush); + // hBrush = CreateSolidBrush(RGB(255,255,255)); + // SetBkColor((HDC) wParam, RGB(255,255,255)); + // return (LRESULT) hBrush; + + // Ownerdraw stuff + case WM_MEASUREITEM: + { + ((MEASUREITEMSTRUCT *) (lParam))->itemHeight = g_Height; + break; + } + + // Ownerdraw stuff + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *pDIS; + WCHAR wzBuf[1024]; + int ItemID; + + pDIS = (DRAWITEMSTRUCT *) lParam; + ItemID = (int) pDIS->itemID; + + if (ItemID < 0) + { + switch (pDIS->CtlType) + { + case ODT_LISTBOX: + { + if ((pDIS->itemAction) & (ODA_FOCUS)) + DrawFocusRect (PHDC, &PRC); + break; + } + + case ODT_COMBOBOX: + { + if ((pDIS->itemAction) & ODS_FOCUS) + DrawFocusRect(PHDC, &PRC); + break; + } + } + + return TRUE; + } + + switch (pDIS->CtlType) + { + case ODT_LISTBOX: + WszSendMessage(pDIS->hwndItem, LB_GETTEXT, pDIS->itemID, (LPARAM)wzBuf); + break; + + case ODT_COMBOBOX: + WszSendMessage(pDIS->hwndItem, CB_GETLBTEXT, pDIS->itemID, (LPARAM)wzBuf); + break; + } + + int crBack,crText; + HBRUSH hbrBack; + + if ((pDIS->itemState) & (ODS_SELECTED)) + { + crBack = GetSysColor(COLOR_HIGHLIGHT); + crText = GetSysColor(COLOR_HIGHLIGHTTEXT); + } + else + { + crBack = GetSysColor(COLOR_WINDOW); + crText = GetSysColor(COLOR_WINDOWTEXT); + } + + hbrBack = CreateSolidBrush(crBack); + FillRect(PHDC, &PRC, hbrBack); + DeleteObject(hbrBack); + + // 0x00bbggrr + SetBkColor(PHDC, crBack); + + // Instruction counter + if (wcslen(wzBuf) >= PADDING && isdigit(*wzBuf)) + { + SetTextColor(PHDC, 0x00FF0000); + TextOutW(PHDC, PRC.left, PRC.top, wzBuf, 5); + + SetTextColor(PHDC, 0x00005500); + TextOutW(PHDC, PRC.left + (5*g_MaxCharWidth), PRC.top, &wzBuf[5], PADDING-5); + + SetTextColor(PHDC, crText); + TextOutW(PHDC, PRC.left + (PADDING*g_MaxCharWidth), PRC.top, &wzBuf[PADDING], (UINT32)wcslen(&wzBuf[PADDING])); + } + else + TextOutW(PHDC, PRC.left, PRC.top, wzBuf, (UINT32)wcslen(wzBuf)); + + if ((pDIS->itemState) & (ODS_FOCUS)) + DrawFocusRect(PHDC, &PRC); + + break; + } + + + case WM_COMMAND: + { + if(HIWORD(wParam) > 1) break; // we are interested in commands from menu only + switch (LOWORD(wParam)) + { + case IDM_FIND: + { + HWND hwndLB = FindAssociatedDisassemblyListBox(hwnd); + if(hwndLB) + { + FINDREPLACEW *pFR = &(FindDisasmBoxByHwnd(hwnd)->strFR); + if(pFR && (pFR->Flags&FR_DIALOGTERM)) // i.e., if the box isn't up + { + DWORD bgn,end; + WszSendMessage(hwndLB,EM_GETSEL,(WPARAM)&bgn,(LPARAM)&end); + if(end > bgn) + { + if(end - bgn > 119) + SendMessage(hwndLB,EM_SETSEL,(WPARAM)bgn,(LPARAM)(bgn+119)); + SendMessage(hwndLB,EM_GETSELTEXT,0,(LPARAM)(pFR->lpstrFindWhat)); + } + pFR->Flags &= ~FR_DIALOGTERM; + g_hFindText = FindTextW(pFR); + } + } + } + break; + case IDM_FINDNEXT: + { + FindTextInListbox(hwnd,&(FindDisasmBoxByHwnd(hwnd)->strFR)); + } + break; + } + break; + } + + case WM_SETFOCUS: + SetFocus(FindAssociatedDisassemblyListBox(hwnd)); + break; + + case WM_SIZE: + { + DWORD cxClient = LOWORD(lParam); + DWORD cyClient = HIWORD(lParam); + HWND hListView; + + // We have to size the listview also + + // Will be NULL if we are ourselves a listview + hListView = FindAssociatedDisassemblyListBox(hwnd); + + if (hListView != NULL) + { + // Resize listview window + MoveWindow( + hListView, + 0, + 0, + cxClient, + cyClient, + TRUE // repaint + ); + } + + break; + } + + case WM_CLOSE: + if(hBrush) DeleteObject(hBrush); + if(LOWORD(wParam)==0) RemoveDisasmBox(hwnd); + DestroyWindow(hwnd); // Generates the WM_DESTROY message + + // Shutdown everything if we're just viewing GUI IL and close all our boxes + if (IsGuiILOnly() && (g_NumDisasmBoxes == 0)) { + PostQuitMessage(0); + } + + break; + + default : + return WszDefWindowProc(hwnd, uMsg, wParam, lParam); + } + + return 0; +} + +BOOL CALLBACK AboutBoxProc(HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam) // second message parameter +{ + switch(uMsg) + { + case WM_INITDIALOG: + { + WCHAR str[1024]; + WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE1,WM_SETTEXT,0, + (LPARAM)RstrW(IDS_ILDASM_TITLE)); + swprintf_s(str,1024,RstrW(IDS_VERSION), VER_FILEVERSION_STR_L); str[1023]=0; + WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE2,WM_SETTEXT,0,(LPARAM)str); + WszSendDlgItemMessage(hwndDlg,IDC_ABOUT_LINE3,WM_SETTEXT,0, + (LPARAM)RstrW(IDS_LEGALCOPYRIGHT)); + } + return TRUE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case ID_ABOUT_OK: + EndDialog(hwndDlg,0); + return TRUE; + } + break; + + } + return FALSE; +} + +BOOL CALLBACK DumpOptionsProc(HWND hwndDlg, // handle to dialog box + UINT uMsg, // message + WPARAM wParam, // first message parameter + LPARAM lParam) // second message parameter +{ + static BOOL fAsmChecked; + static BOOL fMetaChecked; + static ULONG uCodePage = 0; + + if (uCodePage == 0) + uCodePage = g_uCodePage; + + switch(uMsg) + { + case WM_INITDIALOG: + WszSendDlgItemMessage(hwndDlg,IDC_RADIO1,BM_SETCHECK,(uCodePage==g_uConsoleCP ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_RADIO2,BM_SETCHECK,(uCodePage==CP_UTF8 ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_RADIO3,BM_SETCHECK,(uCodePage==0xFFFFFFFF ? BST_CHECKED : BST_UNCHECKED),0); + + + WszSendDlgItemMessage(hwndDlg,IDC_CHECK18,BM_SETCHECK,(g_fShowProgressBar ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK1, BM_SETCHECK,(g_fDumpHeader ? BST_CHECKED : BST_UNCHECKED),0); + if(g_fTDC) + { + WszSendDlgItemMessage(hwndDlg,IDC_CHECK2, BM_SETCHECK,(g_fDumpStats ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK19, BM_SETCHECK,(g_fDumpClassList ? BST_CHECKED : BST_UNCHECKED),0); + } + else + { + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK2), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK19), SW_HIDE); + } + WszSendDlgItemMessage(hwndDlg,IDC_CHECK3, BM_SETCHECK,(g_fDumpAsmCode ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK4, BM_SETCHECK,(g_fDumpTokens ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK5, BM_SETCHECK,(g_fShowBytes ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK6, BM_SETCHECK,(g_fShowSource ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK20, BM_SETCHECK,(g_fInsertSourceLines ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK7, BM_SETCHECK,(g_fTryInCode ? BST_CHECKED : BST_UNCHECKED),0); + if(!(fAsmChecked = g_fDumpAsmCode)) + { + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK4), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK5), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK6), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK7), FALSE); + } + if(g_fTDC) + { + WszSendDlgItemMessage(hwndDlg,IDC_CHECK8, BM_SETCHECK,(g_fDumpMetaInfo ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK10,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpHeader ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK11,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK12,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpCSV ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK13,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpUnsat ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK16,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpValidate ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK14,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpSchema ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK15,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpRaw ? BST_CHECKED : BST_UNCHECKED),0); + WszSendDlgItemMessage(hwndDlg,IDC_CHECK17,BM_SETCHECK,(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? BST_CHECKED : BST_UNCHECKED),0); + if(!(fMetaChecked = g_fDumpMetaInfo)) + { + //EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK9), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK10), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK11), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK12), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK13), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK14), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK15), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK16), FALSE); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK17), FALSE); + } + } + else + { + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK8), SW_HIDE); + //ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK9), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK10), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK11), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK12), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK13), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK14), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK15), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK16), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK17), SW_HIDE); + } + ShowWindow(GetDlgItem(hwndDlg,IDC_CHECK9), SW_HIDE); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDC_CHECK3: + fAsmChecked = !fAsmChecked; + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK4), fAsmChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK5), fAsmChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK6), fAsmChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK7), fAsmChecked); + return TRUE; + + case IDC_CHECK8: + fMetaChecked = !fMetaChecked; + //EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK9), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK10), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK11), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK12), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK13), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK14), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK15), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK16), fMetaChecked); + EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK17), fMetaChecked); + return TRUE; + + case IDOK: + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO1, BM_GETCHECK,0,0)) g_uCodePage = g_uConsoleCP; + else if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO2, BM_GETCHECK,0,0)) g_uCodePage = CP_UTF8; + else if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_RADIO3, BM_GETCHECK,0,0)) g_uCodePage = 0xFFFFFFFF; + uCodePage = g_uCodePage; + + g_fShowProgressBar = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK18, BM_GETCHECK,0,0)); + g_fDumpHeader = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK1, BM_GETCHECK,0,0)); + if(g_fTDC) + { + g_fDumpStats = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK2, BM_GETCHECK,0,0)); + g_fDumpClassList = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK19, BM_GETCHECK,0,0)); + } + g_fDumpAsmCode = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK3, BM_GETCHECK,0,0)); + g_fDumpTokens = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK4, BM_GETCHECK,0,0)); + g_fShowBytes = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK5, BM_GETCHECK,0,0)); + g_fShowSource = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK6, BM_GETCHECK,0,0)); + g_fInsertSourceLines = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK20, BM_GETCHECK,0,0)); + g_fTryInCode = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK7, BM_GETCHECK,0,0)); + if(g_fTDC) + { + g_fDumpMetaInfo = (BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK8, BM_GETCHECK,0,0)); + g_ulMetaInfoFilter = 0; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK10, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpHeader; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK11, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpMoreHex; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK12, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpCSV; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK13, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpUnsat; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK16, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpValidate; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK14, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpSchema; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK15, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpRaw; + if(BST_CHECKED==WszSendDlgItemMessage(hwndDlg,IDC_CHECK17, BM_GETCHECK,0,0)) g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps; + } + EndDialog(hwndDlg,1); + return TRUE; + + case IDCANCEL: + EndDialog(hwndDlg,0); + return TRUE; + } + break; + + } + return FALSE; +} + +static HWND help_hw; +void * __cdecl HelpFileLoader(_In_z_ LPCWSTR lpHelpFileName) +{ + return HtmlHelpW(help_hw, lpHelpFileName, HH_DISPLAY_TOPIC, NULL); +} + +// +// Main window WndProc +// +#define CHECK_UNCHECK(x) { x=!x; CheckMenuItem(g_hMenu, LOWORD(wParam), (x ? MF_CHECKED : MF_UNCHECKED)); } + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif +LRESULT CALLBACK MainWndProc( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam +) +{ + HWND hwndDasm; + static HCURSOR hWaitCursor = NULL; + + if (hWaitCursor == NULL) + hWaitCursor = WszLoadCursor(NULL,IDC_WAIT); + + switch (uMsg) + { + case WM_DROPFILES: + { + WCHAR wzFileName[MAX_FILENAME_LENGTH]; + DragQueryFileW((HDROP)wParam,0,wzFileName,MAX_FILENAME_LENGTH-1); + memset(g_szInputFile,0,MAX_FILENAME_LENGTH); + WszWideCharToMultiByte(CP_UTF8,0,wzFileName,-1,g_szInputFile,MAX_FILENAME_LENGTH-1,NULL,NULL); + GetInputFileFullPath(); + { + HCURSOR hWasCursor = SetCursor(hWaitCursor); + GUICleanupClassItems(); + TreeView_DeleteAllItems(g_hwndTreeView); + Cleanup(); + GUISetModule(g_szInputFile); + DumpFile(); + SetCursor(hWasCursor); + } + DragFinish((HDROP)wParam); + } + break; + + case WM_COMMAND: + { + if(HIWORD(wParam) > 1) break; // we are interested in commands from menu only + switch (LOWORD(wParam)) + { + case IDM_OPEN: + { + WCHAR wzInputFile[MAX_FILENAME_LENGTH]; + memset(wzInputFile,0,sizeof(wzInputFile)); + if(strlen(g_szInputFile)) + { + WszMultiByteToWideChar(CP_UTF8,0,g_szInputFile,-1,wzInputFile,MAX_FILENAME_LENGTH-1); + } + { + OPENFILENAMEW ofn; + WCHAR* wzFilter = RstrW(IDS_FILTER_IN); //L"PE file (*.exe,*.dll,*.mod,*.mdl,*.winmd)\0*.exe;*.dll;*.mod;*.mdl;*.winmd\0Any type (*.*)\0*.*\0\0"; + const WCHAR* wzDefltExt = L"exe"; + for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0; + memset(&ofn,0,sizeof(OPENFILENAMEW)); + ofn.lStructSize = sizeof(OPENFILENAMEW); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = wzFilter; + ofn.nFilterIndex = 0; + ofn.lpstrFile = wzInputFile; + ofn.nMaxFile = MAX_FILENAME_LENGTH-1; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.lpstrDefExt = wzDefltExt; + if(GetOpenFileName(&ofn)) + { + HCURSOR hWasCursor = SetCursor(hWaitCursor); + GUICleanupClassItems(); + TreeView_DeleteAllItems(g_hwndTreeView); + Cleanup(); + memset(g_szInputFile,0,MAX_FILENAME_LENGTH); + WszWideCharToMultiByte(CP_UTF8,0,wzInputFile,-1,g_szInputFile,MAX_FILENAME_LENGTH-1,NULL,NULL); + GetInputFileFullPath(); + GUISetModule(g_szInputFile); + DumpFile(); + SetCursor(hWasCursor); + } + } + break; + } + case IDM_ABOUT: + { + _ASSERTE(g_hResources != NULL); + WszDialogBoxParam(g_hResources,MAKEINTRESOURCE(IDD_ABOUT),hwnd,(DLGPROC)AboutBoxProc,0L); + break; + } + case IDM_DUMP: + //case IDM_DUMP_TREE: + if(g_pImport) + { + unsigned uWasCodePage = g_uCodePage; + WCHAR wzOutputFile[MAX_FILENAME_LENGTH]; + memset(wzOutputFile,0,sizeof(wzOutputFile)); + if(strlen(g_szOutputFile)) + { + WszMultiByteToWideChar(CP_UTF8,0,g_szOutputFile,-1,wzOutputFile,MAX_FILENAME_LENGTH-1); + } + { + OPENFILENAMEW ofn; + WCHAR* wzFilter = RstrW(IDS_FILTER_OUT);//L"IL file (*.il)\0*.il\0Text file (*.txt) \0*.txt\0Any type (*.*)\0*.*\0\0"; + const WCHAR* wzDefltExt = L"il"; + for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0; + memset(&ofn,0,sizeof(OPENFILENAMEW)); + ofn.lStructSize = sizeof(OPENFILENAMEW); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = wzFilter; + ofn.nFilterIndex = 0; + ofn.lpstrFile = wzOutputFile; + ofn.nMaxFile = MAX_FILENAME_LENGTH-1; + ofn.Flags = OFN_OVERWRITEPROMPT; + ofn.lpstrDefExt = wzDefltExt; + _ASSERTE(g_hResources != NULL); + if(WszDialogBoxParam(g_hResources,MAKEINTRESOURCE(IDD_DIALOG1),hwnd,(DLGPROC)DumpOptionsProc,0L) && + GetSaveFileName(&ofn)) + { + HCURSOR hWasCursor = SetCursor(hWaitCursor); + g_Mode &= ~MODE_GUI; + memset(g_szOutputFile,0,MAX_FILENAME_LENGTH); + WszWideCharToMultiByte(CP_UTF8,0,wzOutputFile,-1,g_szOutputFile,MAX_FILENAME_LENGTH-1,NULL,NULL); + g_pFile = OpenOutput(wzOutputFile); + if(g_pFile) + { + DumpFile(); // closes g_pFile upon completion + SetCursor(hWasCursor); + } + else + { + SetCursor(hWasCursor); + WszMessageBox(hwnd,wzOutputFile,RstrW(IDS_CANNOTOPENFILE),MB_OK|MB_ICONERROR | GetDasmMBRTLStyle()); + } + g_szOutputFile[0] = 0; + g_Mode |= MODE_GUI; + //g_fShowSource = FALSE; // flag could have been changed for dump + } + } + g_uCodePage = uWasCodePage; // g_uCodePage is changed in DumpOptionsProc + } + break; + + case IDM_DUMP_TREE: + if(g_pImport) + { + // Dump the tree view(fully expanded, with current sorting) to a text file + OPENFILENAMEW ofn; + WCHAR* wzFilter = RstrW(IDS_FILTER_OUT2); //L"Text file (*.txt) \0*.txt\0Any type (*.*)\0*.*\0\0"; + const WCHAR* wzDefltExt = L"txt"; + WCHAR szIndent[MAX_FILENAME_LENGTH]; + FILE* pFile; + WCHAR wzOutputFile[MAX_FILENAME_LENGTH]; + for(WCHAR* pwc = wzFilter; pwc = wcschr(pwc,'\t'); pwc++) *pwc = 0; + memset(wzOutputFile,0,sizeof(wzOutputFile)); + memset(&ofn,0,sizeof(OPENFILENAMEW)); + ofn.lStructSize = sizeof(OPENFILENAMEW); + ofn.hwndOwner = hwnd; + ofn.lpstrFilter = wzFilter; + ofn.nFilterIndex = 0; + ofn.lpstrFile = wzOutputFile; + ofn.nMaxFile = MAX_FILENAME_LENGTH-1; + ofn.Flags = OFN_OVERWRITEPROMPT; + ofn.lpstrDefExt = wzDefltExt; + if(GetSaveFileName(&ofn)) + { + HCURSOR hWasCursor = SetCursor(hWaitCursor); + pFile = g_pFile; + g_pFile = OpenOutput(wzOutputFile); + szIndent[0] = 0; + if(g_pFile) + { + g_Mode &= ~MODE_GUI; + DumpTreeItem(g_hRoot,g_pFile,szIndent); + g_Mode |= MODE_GUI; + fclose(g_pFile); + SetCursor(hWasCursor); + } + else + { + SetCursor(hWasCursor); + WszMessageBox(hwnd,wzOutputFile,RstrW(IDS_CANNOTOPENFILE),MB_OK|MB_ICONERROR | GetDasmMBRTLStyle()); + } + g_pFile = pFile; + } + } + break; + + case IDM_EXIT: + { + WszSendMessage(GetActiveWindow(),WM_CLOSE,0,0); + } + break; + + case IDM_FONT_TREE: + { + g_strChFontTree.hwndOwner = g_hwndMain; + if(ChooseFont(&g_strChFontTree)) + { + DeleteObject((HGDIOBJ)g_hSmallFont); + g_hSmallFont = CreateFontIndirect(&g_strLogFontTree); + WszSendMessage(g_hwndTreeView,WM_SETFONT,(LPARAM) g_hSmallFont,TRUE); + if(g_hwndAsmInfo) + WszSendMessage(g_hwndAsmInfo,WM_SETFONT,(LPARAM) g_hSmallFont,TRUE); + SaveGUIFonts(&guiInfo); + } + break; + } + + case IDM_FONT_DASM: + { + g_strChFontDasm.hwndOwner = g_hwndMain; + if(ChooseFont(&g_strChFontDasm)) + { + if(g_fDumpRTF) { g_strLogFontDasm.lfWeight = FW_REGULAR; g_strLogFontDasm.lfItalic = FALSE; } + DeleteObject((HGDIOBJ)g_hFixedFont); + g_hFixedFont = CreateFontIndirect(&g_strLogFontDasm); + + for (DWORD i = 0; i < g_NumDisasmBoxes; i++) + { + WszSendMessage((*g_DisasmBox)[i].hwndChild,WM_SETFONT,(LPARAM)g_hFixedFont,TRUE); + if(g_fDumpRTF) + GUIDumpItemToDisassemblyEditBox((void*)(*g_DisasmBox)[i].hwndChild, + (*g_DisasmBox)[i].tkClass,(*g_DisasmBox)[i].tkMember); + } + SaveGUIFonts(&guiInfo); + } + break; + } + + case IDM_CAVERBAL: + { + CHECK_UNCHECK(g_fCAVerbal); + for (DWORD i = 0; i < g_NumDisasmBoxes; i++) + { + GUIDumpItemToDisassemblyEditBox((void*)(*g_DisasmBox)[i].hwndChild, + (*g_DisasmBox)[i].tkClass, + (*g_DisasmBox)[i].tkMember); + } + break; + } + + case IDM_DUMPRTF: + { + CHECK_UNCHECK(g_fDumpRTF); + //GUIDumpAssemblyInfo(); + for (DWORD i = 0; i < g_NumDisasmBoxes; i++) + { + mdToken tkClass = (*g_DisasmBox)[i].tkClass; + mdToken tkMember = (*g_DisasmBox)[i].tkMember; + if((TypeFromToken(tkMember)==0)&&(tkClass==IDM_SHOW_METAINFO)) + continue; + GUIDisassemble(tkClass,tkMember,"UpdateThisDisassemblyBox"); + } + break; + } + + case IDM_SORT_BY_NAME: + { + CHECK_UNCHECK(g_fSortByName); + if(g_pImport) + { + if(!RefreshList()) goto CloseAndDestroy; + } + break; + } + + case IDM_TREEVIEWFCN: + { + CHECK_UNCHECK(g_fTreeViewFCN); + if(g_pImport) + { + if(!RefreshList()) goto CloseAndDestroy; + } + break; + } + + case IDM_SHOW_PUB: + { + CHECK_UNCHECK(g_fHidePub); +UpdateVisibilityOptions: + g_fLimitedVisibility = g_fHidePub || + g_fHidePriv || + g_fHideFam || + g_fHideFAA || + g_fHideFOA || + g_fHidePrivScope || + g_fHideAsm; + if(g_pImport) + { + if(!RefreshList()) DestroyWindow(hwnd); + } + break; + } + case IDM_SHOW_PRIV: + { + CHECK_UNCHECK(g_fHidePriv); + goto UpdateVisibilityOptions; + } + case IDM_SHOW_FAM: + { + CHECK_UNCHECK(g_fHideFam); + goto UpdateVisibilityOptions; + } + case IDM_SHOW_ASM: + { + CHECK_UNCHECK(g_fHideAsm); + goto UpdateVisibilityOptions; + } + case IDM_SHOW_FAA: + { + CHECK_UNCHECK(g_fHideFAA); + goto UpdateVisibilityOptions; + } + case IDM_SHOW_FOA: + { + CHECK_UNCHECK(g_fHideFOA); + goto UpdateVisibilityOptions; + } + case IDM_SHOW_PSCOPE: + { + CHECK_UNCHECK(g_fHidePrivScope); + goto UpdateVisibilityOptions; + } + case IDM_FULL_INFO: + { + CHECK_UNCHECK(g_fFullMemberInfo); + if(g_pImport) + { + if(!RefreshList()) DestroyWindow(hwnd); + } + break; + } + case IDM_BYTES: + { + CHECK_UNCHECK(g_fShowBytes); + break; + } + case IDM_TOKENS: + { + CHECK_UNCHECK(g_fDumpTokens); + break; + } + case IDM_SOURCELINES: + { + CHECK_UNCHECK(g_fShowSource); + break; + } + case IDM_EXPANDTRY: + { + CHECK_UNCHECK(g_fTryInCode); + break; + } + case IDM_QUOTEALLNAMES: + { + CHECK_UNCHECK(g_fQuoteAllNames); + break; + } + case IDM_SHOW_HEADER: + { + GUIDisassemble(IDM_SHOW_HEADER,0,"Headers"); + break; + } + case IDM_SHOW_STAT: + { + GUIDisassemble(IDM_SHOW_STAT,0,"Statistics"); + break; + } + case IDM_HELP: + { + help_hw = hwnd; + FindLocalizedFile(L"ildasm.chm", &HelpFileLoader); + break; + } + case IDM_SHOW_METAINFO: + { + if(g_pImport) + GUIDisassemble(IDM_SHOW_METAINFO,0,"MetaInfo"); + break; + } + case IDM_MI_HEADER: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpHeader) g_ulMetaInfoFilter &= ~MDInfo::dumpHeader; + else g_ulMetaInfoFilter |= MDInfo::dumpHeader; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpHeader ? MF_CHECKED : MF_UNCHECKED)); + if(g_ulMetaInfoFilter & MDInfo::dumpHeader) + { + // HeaderOnly specified, + // Suppress Counts,Sizes, Header,Schema and Header,Schema,Rows + g_ulMetaInfoFilter &= ~MDInfo::dumpCSV; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpSchema; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpRaw; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED); + } + return 1; //break; + } + case IDM_MI_HEX: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpMoreHex) g_ulMetaInfoFilter &= ~MDInfo::dumpMoreHex; + else g_ulMetaInfoFilter |= MDInfo::dumpMoreHex; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpMoreHex ? MF_CHECKED : MF_UNCHECKED)); + return 1; //break; + } + case IDM_MI_CSV: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpCSV) g_ulMetaInfoFilter &= ~MDInfo::dumpCSV; + else g_ulMetaInfoFilter |= MDInfo::dumpCSV; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpCSV ? MF_CHECKED : MF_UNCHECKED)); + if(g_ulMetaInfoFilter & MDInfo::dumpCSV) + { + // Counts,Sizes specified, + // Suppress HeaderOnly, Header,Schema and Header,Schema,Rows + g_ulMetaInfoFilter &= ~MDInfo::dumpHeader; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpSchema; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpRaw; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED); + } + return 1; //break; + } + case IDM_MI_UNREX: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpUnsat) g_ulMetaInfoFilter &= ~MDInfo::dumpUnsat; + else g_ulMetaInfoFilter |= MDInfo::dumpUnsat; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpUnsat ? MF_CHECKED : MF_UNCHECKED)); + return 1; //break; + } + case IDM_MI_SCHEMA: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpSchema) g_ulMetaInfoFilter &= ~MDInfo::dumpSchema; + else g_ulMetaInfoFilter |= MDInfo::dumpSchema; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpSchema ? MF_CHECKED : MF_UNCHECKED)); + if(g_ulMetaInfoFilter & MDInfo::dumpSchema) + { + // Header,Schema specified, + // suppress Counts,Sizes, HeaderOnly and Header,Schema,Rows + g_ulMetaInfoFilter &= ~MDInfo::dumpCSV; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpHeader; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpRaw; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_RAW, MF_UNCHECKED); + } + return 1; //break; + } + case IDM_MI_RAW: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpRaw) g_ulMetaInfoFilter &= ~MDInfo::dumpRaw; + else g_ulMetaInfoFilter |= MDInfo::dumpRaw; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpRaw ? MF_CHECKED : MF_UNCHECKED)); + if(g_ulMetaInfoFilter & MDInfo::dumpRaw) + { + // Header,Schema,Rows specified, + // suppress Counts,Sizes, HeaderOnly and Header,Schema + g_ulMetaInfoFilter &= ~MDInfo::dumpCSV; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_CSV, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpHeader; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_HEADER, MF_UNCHECKED); + g_ulMetaInfoFilter &= ~MDInfo::dumpSchema; + CheckMenuItem(g_hMetaInfoMenu, IDM_MI_SCHEMA, MF_UNCHECKED); + } + return 1; //break; + } + case IDM_MI_HEAPS: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpRawHeaps) g_ulMetaInfoFilter &= ~MDInfo::dumpRawHeaps; + else g_ulMetaInfoFilter |= MDInfo::dumpRawHeaps; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpRawHeaps ? MF_CHECKED : MF_UNCHECKED)); + return 1; //break; + } + case IDM_MI_VALIDATE: + { + WORD iSelection = LOWORD(wParam); + if(g_ulMetaInfoFilter & MDInfo::dumpValidate) g_ulMetaInfoFilter &= ~MDInfo::dumpValidate; + else g_ulMetaInfoFilter |= MDInfo::dumpValidate; + CheckMenuItem(g_hMetaInfoMenu, iSelection, (g_ulMetaInfoFilter & MDInfo::dumpValidate ? MF_CHECKED : MF_UNCHECKED)); + return 1; //break; + } + + } + + break; + } + + case WM_SETFOCUS: + SetFocus(g_hwndTreeView); + break; + + case WM_SIZE: + { + DWORD cxClient = LOWORD(lParam); + DWORD cyClient = HIWORD(lParam); + DWORD dy; + + dy = cyClient >> 3; + if(dy < 50) dy = 50; + if(cyClient < dy+4) cyClient = dy+4; + + // Resize listview window + MoveWindow( + g_hwndTreeView, + 0, + 0, + cxClient, + cyClient-dy-2, + TRUE // repaint + ); + // Resize AsmInfo window + MoveWindow( + g_hwndAsmInfo, + 0, + cyClient-dy-1, + cxClient, + dy, + TRUE // repaint + ); + + break; + } + + case WM_NOTIFY: + { + if (wParam == ID_TREEVIEW) + { + NMHDR * pNMHDR = (NMHDR*) lParam; + switch (pNMHDR->code) + { + case TVN_KEYDOWN: + { + NMTVKEYDOWN *pKeyDown = (NMTVKEYDOWN *) pNMHDR; + + if (pKeyDown->wVKey == '\r') + { + if(DoubleClickSelectedMember(g_CurSelItem) == NULL) + TreeView_Expand(g_hwndTreeView,g_CurSelItem,TVE_TOGGLE); + } + break; + } + + case NM_DBLCLK: + { + hwndDasm = DoubleClickSelectedMember(g_CurSelItem); + if(hwndDasm) + { + PostMessageA(hwndDasm,WM_ACTIVATE,WA_CLICKACTIVE,0); + PostMessageA(hwndDasm,WM_SETFOCUS,0,0); + } + break; + } + + case TVN_SELCHANGEDW: + case TVN_SELCHANGEDA: + { + NMTREEVIEW *pTV = (NMTREEVIEW *) pNMHDR; + /* + TVITEM SelItem; + char szText[256]; + + memset(&SelItem, 0, sizeof(SelItem)); + SelItem.mask = TVIF_TEXT; + SelItem.pszText = szText; + SelItem.cchTextMax = sizeof(szText)-1; + SelItem.hItem = pTV->itemNew.hItem; + + g_CurSelItem = SelItem.hItem; + SendMessageA(g_hwndTreeView, TVM_GETITEM, 0, (LPARAM)&SelItem); + */ + g_CurSelItem = pTV->itemNew.hItem; + break; + } + } + } + + break; + } + + case WM_CLOSE: + CloseAndDestroy: + // HTML help window is closed automatically + { + RECT r; + ShowWindow(hwnd,SW_RESTORE); + GetWindowRect(hwnd,(LPRECT)&r); + guiInfo.x = r.left; + guiInfo.y = r.top; + guiInfo.w = r.right - r.left; + guiInfo.h = r.bottom - r.top; + SaveGUIFonts(&guiInfo); + } + DestroyWindow(hwnd); // Generates the WM_DESTROY message + break; + + case WM_DESTROY : + PostQuitMessage(0); // Puts a WM_QUIT in the queue + break; + + default : + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } + + return 0; +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + + +// +// Create the treeview in the main window +// +HWND CreateTreeView(HWND hwndParent) +{ + HWND hwndTree; + RECT rcl; + DWORD tvs = + TVS_HASLINES + |TVS_HASBUTTONS + |TVS_LINESATROOT + |TVS_SHOWSELALWAYS + // |TVS_TRACKSELECT + // |TVS_SINGLEEXPAND + |TVS_DISABLEDRAGDROP + ; + unsigned cy,dy; + + GetClientRect(hwndParent, &rcl); + cy = rcl.bottom - rcl.top; + dy = cy >> 3; + hwndTree = WszCreateWindowEx( + 0, + WC_TREEVIEWW, + NULL, + WS_VISIBLE|WS_CHILD|WS_BORDER|tvs, + 0, + 0, + rcl.right - rcl.left, + cy-dy-2, //rcl.bottom - rcl.top, + hwndParent, + (HMENU) ID_TREEVIEW, + g_hInstance, + NULL + ); + g_hwndAsmInfo = NULL; + if (hwndTree == NULL) + return NULL; + + WszSendMessage(hwndTree,WM_SETFONT,(LPARAM) g_hSmallFont,FALSE); + + TreeView_SetBkColor(hwndTree,-1); + TreeView_SetImageList(hwndTree, g_hImageList, TVSIL_NORMAL); + + g_hwndAsmInfo = WszCreateWindowEx( + 0, //WS_EX_TOOLWINDOW, + g_fDumpRTF ? L"RichEdit20A" : L"EDIT", + NULL, + WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE | WS_BORDER //| WS_CAPTION | WS_OVERLAPPEDWINDOW + | ES_MULTILINE | ES_READONLY | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL, + 0, + cy-dy-1, + rcl.right - rcl.left, + dy, + hwndParent, + (HMENU) ID_LISTBOX, + g_hInstance, // hinst + NULL + ); + if(g_hwndAsmInfo) + { + WszSendMessage(g_hwndAsmInfo,WM_SETFONT,(LPARAM) g_hSmallFont,FALSE); + } + + return hwndTree; +} + + +// +// Add one item to a treeview +// +HTREEITEM AddOneItem(HTREEITEM hParent, const char *pszText, HTREEITEM hInsAfter, int iImage, HWND hwndTree, BOOL fExpanded) +{ + HTREEITEM hItem; + WCHAR* wz = UtfToUnicode(pszText); + ULONG lLen = (ULONG)wcslen(wz); + TVINSERTSTRUCTW tvIns; + memset(&tvIns, 0, sizeof(tvIns)); + + tvIns.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM; + tvIns.item.pszText = wz; + tvIns.item.cchTextMax = lLen; + tvIns.item.iImage = iImage; + tvIns.item.iSelectedImage = iImage; + + tvIns.hInsertAfter = hInsAfter; + tvIns.hParent = hParent; + + hItem = (HTREEITEM)WszSendMessage(hwndTree, TVM_INSERTITEMW, 0, (LPARAM)(&tvIns)); + + return hItem; +} + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:22018) // Suppress PREFast warning about Integer overflow/underflow +#endif +//ulen cannot be greater than GlobalBufferLen by the definition of ulen. Therefore it's safe to disable this warning here. +void AddMethodToGUI( + mdTypeDef cl, + ClassItem_t * pClassItem, + const char *pszNamespace, + const char *pszClassName, + const char *pszMethodName, + PCCOR_SIGNATURE pComSig, + unsigned cComSig, + mdMethodDef mbMethod, + DWORD dwAttrs +) +{ + HTREEITEM hParent; + char* szName; + ULONG ulLen,ulImageIndex; + BOOL wasDumpRTF; + + memset(GlobalBuffer,0,GlobalBufferLen); + sprintf_s(GlobalBuffer, GlobalBufferLen,g_fFullMemberInfo ? "method %s : ": "%s : ",pszMethodName); + InGlobalBuffer = (UINT32)strlen(GlobalBuffer); + ulLen = InGlobalBuffer; + wasDumpRTF = g_fDumpRTF; + g_fDumpRTF = FALSE; + mdToken tkVarOwner = g_tkVarOwner; + g_tkVarOwner = cl; + DumpMethod(mbMethod, pszClassName,VAL32(g_CORHeader->EntryPointToken),(void *)g_hwndTreeView,FALSE); + g_tkVarOwner = tkVarOwner; + g_fDumpRTF = wasDumpRTF; + GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n + + szName = &GlobalBuffer[ulLen]; + + if(strstr(szName,"instance ") == szName) strcpy_s(szName,GlobalBufferLen-ulLen,szName+9); + + szName = GlobalBuffer; + + hParent = pClassItem->hItem; + + _ASSERTE(pClassItem->CurMember < pClassItem->SubItems); + + if((strchr(szName, '<'))&&(strchr(szName, '>'))) + { + ulImageIndex = IsMdStatic(dwAttrs) ? STATIC_METHOD_GEN_IMAGE_INDEX : METHOD_GEN_IMAGE_INDEX; + } + else + { + ulImageIndex = IsMdStatic(dwAttrs) ? STATIC_METHOD_IMAGE_INDEX : METHOD_IMAGE_INDEX; + } + + pClassItem->pMembers[pClassItem->CurMember].hItem = AddOneItem( + hParent, szName, TVI_LAST, ulImageIndex, g_hwndTreeView, FALSE + ); + pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER; + pClassItem->pMembers[pClassItem->CurMember].mbMember = mbMethod; + pClassItem->CurMember++; +} + +#ifdef _PREFAST_ +#pragma warning(pop) +#endif +BOOL NamespaceMatch(const char *pszNamespace, __in __nullterminated char *pszString) +{ + if (strncmp(pszNamespace, pszString, strlen(pszNamespace)) == 0) + { + if (pszString[ strlen(pszNamespace) ] == NAMESPACE_SEPARATOR_CHAR) + return TRUE; + } + + return FALSE; +} + +void AddFieldToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + const char *pszFieldName, + const char *pszSignature, + mdFieldDef mbField, + DWORD dwAttrs +) +{ + DWORD Dimensions; + ULONG ul1,ul2; + BOOL wasDumpRTF; + HTREEITEM hParent = pClassItem->hItem; + + Dimensions = 0; + + memset(GlobalBuffer,0,GlobalBufferLen); + sprintf_s(GlobalBuffer,GlobalBufferLen,g_fFullMemberInfo ? "field %s : " : "%s : ",pszFieldName); + InGlobalBuffer = (UINT32)strlen(GlobalBuffer); + GetClassLayout(cl,&ul1,&ul2); + wasDumpRTF = g_fDumpRTF; + g_fDumpRTF = FALSE; + DumpField(mbField, pszClassName,(void *)g_hwndTreeView,FALSE); + g_fDumpRTF = wasDumpRTF; + GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n + char* pch = strchr(GlobalBuffer,'\r'); + if(pch) strcpy_s(pch,5," ..."); + _ASSERTE(pClassItem->CurMember < pClassItem->SubItems); + + pClassItem->pMembers[pClassItem->CurMember].mbMember = mbField; + pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER; + pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem( + hParent, + GlobalBuffer, //szType, + TVI_LAST, + (dwAttrs & mdStatic) ? STATIC_FIELD_IMAGE_INDEX : FIELD_IMAGE_INDEX, + g_hwndTreeView, + FALSE + ); +} + +void AddEventToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + DWORD dwClassAttrs, + mdEvent mbEvent +) +{ + DWORD Dimensions; + BOOL wasDumpRTF; + HTREEITEM hParent = pClassItem->hItem; + + Dimensions = 0; + + memset(GlobalBuffer,0,GlobalBufferLen); + if(g_fFullMemberInfo) strcpy_s(GlobalBuffer,GlobalBufferLen,"event "); + InGlobalBuffer = (UINT32)strlen(GlobalBuffer); + wasDumpRTF = g_fDumpRTF; + g_fDumpRTF = FALSE; + DumpEvent(mbEvent, pszClassName, dwClassAttrs, (void *)g_hwndTreeView, FALSE); //FALSE=don't dump the body + g_fDumpRTF = wasDumpRTF; + GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n + + _ASSERTE(pClassItem->CurMember < pClassItem->SubItems); + + pClassItem->pMembers[pClassItem->CurMember].mbMember = mbEvent; + pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER; + pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem( + hParent, + GlobalBuffer, //szType, + TVI_LAST, + EVENT_IMAGE_INDEX, + g_hwndTreeView, + FALSE + ); +} + +void AddPropToGUI( + mdTypeDef cl, + ClassItem_t *pClassItem, + const char *pszNamespace, + const char *pszClassName, + DWORD dwClassAttrs, + mdProperty mbProp +) +{ + DWORD Dimensions; + BOOL wasDumpRTF; + HTREEITEM hParent = pClassItem->hItem; + + Dimensions = 0; + + memset(GlobalBuffer,0,GlobalBufferLen); + if(g_fFullMemberInfo) strcpy_s(GlobalBuffer,GlobalBufferLen,"prop "); + InGlobalBuffer = (UINT32)strlen(GlobalBuffer); + wasDumpRTF = g_fDumpRTF; + g_fDumpRTF = FALSE; + DumpProp(mbProp, pszClassName, dwClassAttrs, (void *)g_hwndTreeView, FALSE); //FALSE=don't dump the body + g_fDumpRTF = wasDumpRTF; + GlobalBuffer[InGlobalBuffer-2] = 0; // get rid of \r\n + + _ASSERTE(pClassItem->CurMember < pClassItem->SubItems); + + pClassItem->pMembers[pClassItem->CurMember].mbMember = mbProp; + pClassItem->pMembers[pClassItem->CurMember].Discriminator = TREEITEM_TYPE_MEMBER; + pClassItem->pMembers[pClassItem->CurMember++].hItem = AddOneItem( + hParent, + GlobalBuffer, //szType, + TVI_LAST, + PROP_IMAGE_INDEX, + g_hwndTreeView, + FALSE + ); +} + + + +HTREEITEM FindCreateNamespaceRoot(const char *pszNamespace) +{ + DWORD i; + HTREEITEM hRoot; + DWORD l = 0,ll; + + if (!pszNamespace || !*pszNamespace) + return g_hRoot; // not in a namespace, use tree root + + hRoot = g_hRoot; + for (i = 0; i < g_NumNamespaces; i++) + { + if (!strcmp(pszNamespace, (*g_NamespaceList)[i].pszNamespace)) + return (*g_NamespaceList)[i].hRoot; + } + for (i = 0; i < g_NumNamespaces; i++) + { + if(strstr(pszNamespace,(*g_NamespaceList)[i].pszNamespace) == pszNamespace) + { + ll = (DWORD)strlen((*g_NamespaceList)[i].pszNamespace); + if((ll > l)&&(pszNamespace[ll] == '.')) + { + hRoot = (*g_NamespaceList)[i].hRoot; + l = ll; + } + } + } + + hRoot = AddOneItem(hRoot, pszNamespace, TVI_LAST, NAMESPACE_IMAGE_INDEX, g_hwndTreeView, TRUE); + (*g_NamespaceList)[g_NumNamespaces].pszNamespace = pszNamespace; + (*g_NamespaceList)[g_NumNamespaces].hRoot = hRoot; + g_NumNamespaces++; + + return hRoot; +} + + +Namespace_t *FindNamespace(const char *pszNamespace) +{ + DWORD i; + + for (i = 0; i < g_NumNamespaces; i++) + { + if (!strcmp(pszNamespace, (*g_NamespaceList)[i].pszNamespace)) + return &(*g_NamespaceList)[i]; + } + + return NULL; +} + + +void GUICleanupClassItems() +{ + DWORD i; + WCHAR* sz=L"\0\0"; + + for (i = 0; i < g_NumClassItems; i++) + { + if((*g_ClassItemList)[i].pMembers) + { + delete[] (*g_ClassItemList)[i].pMembers; + (*g_ClassItemList)[i].pMembers = NULL; + } + } + for (i = 0; i < g_NumDisasmBoxes; i++) + { + PostMessageA((*g_DisasmBox)[i].hwndContainer,WM_CLOSE,0,0); + } + WszSendMessage(g_hwndAsmInfo,WM_SETTEXT,0,(LPARAM)sz); + EnableMenuItem(g_hMenu,(UINT)(UINT_PTR)g_hViewMenu, MF_GRAYED); + EnableMenuItem(g_hFileMenu,IDM_DUMP,MF_GRAYED); + EnableMenuItem(g_hFileMenu,IDM_DUMP_TREE,MF_GRAYED); +} + +// +// Add a new class tree node +// +ClassItem_t *AddClassToGUI( + mdTypeDef cl, + UINT uImageIndex, + const char *pszNamespace, + const char *pszClassName, + DWORD cSubItems, + HTREEITEM *phRoot // Returns the namespace root (NOT the class root) +) +{ + HTREEITEM hRoot; + + if(*phRoot) + hRoot = *phRoot; + else + { + hRoot = FindCreateNamespaceRoot(pszNamespace); + _ASSERTE(hRoot != NULL); + + *phRoot = hRoot; + } + + (*g_ClassItemList)[g_NumClassItems].hItem = AddOneItem(hRoot, pszClassName, TVI_LAST, uImageIndex, g_hwndTreeView, FALSE); + (*g_ClassItemList)[g_NumClassItems].cl = cl; + (*g_ClassItemList)[g_NumClassItems].SubItems = cSubItems; + (*g_ClassItemList)[g_NumClassItems].CurMember = 0; + + (*g_ClassItemList)[g_NumClassItems].pMembers = new (nothrow) TreeItem_t[cSubItems]; + + g_NumClassItems++; + + return &(*g_ClassItemList)[g_NumClassItems-1]; +} + + +void AddGlobalFunctions() +{ + HRESULT hr = S_OK; + HENUMInternal hEnumMethod; + mdToken FuncToken; + DWORD i; + HTREEITEM hNamespaceRoot = NULL; + DWORD NumGlobals; + + ClassItem_t* pClassItem = &(*g_ClassItemList)[0]; + + if (SUCCEEDED(g_pImport->EnumGlobalFieldsInit(&hEnumMethod))) + { + NumGlobals = g_pImport->EnumGetCount(&hEnumMethod); + MemberInfo* fields = new (nothrow) MemberInfo[NumGlobals]; + MemberInfo* curField = fields; + + for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++) + { + curField->token = FuncToken; + if (FAILED(g_pImport->GetFieldDefProps(FuncToken, &curField->dwAttrs)) || + FAILED(g_pImport->GetNameOfFieldDef(FuncToken, &curField->pszMemberName))) + { + curField->pszMemberName = "Invalid FieldDef record"; + } + MAKE_NAME_IF_NONE(curField->pszMemberName,FuncToken); + //curField->pComSig = g_pImport->GetSigOfFieldDef(FuncToken, &curMethod->cComSig); + curField++; + } + g_pImport->EnumClose(&hEnumMethod); + + _ASSERTE(curField - fields == (int) NumGlobals); + + if(g_fSortByName) qsort(fields, NumGlobals, sizeof MemberInfo, memberCmp); + + for(curField = fields; curField < &fields[NumGlobals];curField++) + { + if(g_fLimitedVisibility) + { + if(g_fHidePub && IsFdPublic(curField->dwAttrs)) continue; + if(g_fHidePriv && IsFdPrivate(curField->dwAttrs)) continue; + if(g_fHideFam && IsFdFamily(curField->dwAttrs)) continue; + if(g_fHideAsm && IsFdAssembly(curField->dwAttrs)) continue; + if(g_fHideFOA && IsFdFamORAssem(curField->dwAttrs)) continue; + if(g_fHideFAA && IsFdFamANDAssem(curField->dwAttrs)) continue; + if(g_fHidePrivScope && IsFdPrivateScope(curField->dwAttrs)) continue; + } + AddFieldToGUI(NULL, pClassItem, NULL, "Global Fields", curField->pszMemberName, NULL, curField->token, curField->dwAttrs); + } + delete[] fields; + } + if (FAILED(g_pImport->EnumGlobalFunctionsInit(&hEnumMethod))) + return; + + NumGlobals = g_pImport->EnumGetCount(&hEnumMethod); + MemberInfo* methods = new (nothrow) MemberInfo[NumGlobals]; + MemberInfo* curMethod = methods; + + for (i = 0; g_pImport->EnumNext(&hEnumMethod, &FuncToken); i++) + { + curMethod->token = FuncToken; + if (FAILED(g_pImport->GetMethodDefProps(FuncToken, &curMethod->dwAttrs)) || + FAILED(g_pImport->GetNameOfMethodDef(FuncToken, &curMethod->pszMemberName))) + { + curMethod->pszMemberName = "Invalid MethodDef record"; + } + MAKE_NAME_IF_NONE(curMethod->pszMemberName,FuncToken); + if (FAILED(g_pImport->GetSigOfMethodDef(FuncToken, &curMethod->cComSig, &curMethod->pComSig))) + { + curMethod->pszMemberName = "Invalid MethodDef record"; + curMethod->cComSig = 0; + curMethod->pComSig = NULL; + } + curMethod++; + } + g_pImport->EnumClose(&hEnumMethod); + + _ASSERTE(curMethod - methods == (int) NumGlobals); + + if(g_fSortByName) qsort(methods, NumGlobals, sizeof MemberInfo, memberCmp); + + for(curMethod = methods; curMethod < &methods[NumGlobals];curMethod++) + { + if(g_fLimitedVisibility) + { + if(g_fHidePub && IsMdPublic(curMethod->dwAttrs)) continue; + if(g_fHidePriv && IsMdPrivate(curMethod->dwAttrs)) continue; + if(g_fHideFam && IsMdFamily(curMethod->dwAttrs)) continue; + if(g_fHideAsm && IsMdAssem(curMethod->dwAttrs)) continue; + if(g_fHideFOA && IsMdFamORAssem(curMethod->dwAttrs)) continue; + if(g_fHideFAA && IsMdFamANDAssem(curMethod->dwAttrs)) continue; + if(g_fHidePrivScope && IsMdPrivateScope(curMethod->dwAttrs)) continue; + } + AddMethodToGUI(NULL, pClassItem, NULL, "Global Functions", curMethod->pszMemberName, curMethod->pComSig, curMethod->cComSig, curMethod->token, curMethod->dwAttrs); + } + delete[] methods; + return; +} + + +BOOL CreateMainWindow() +{ + DWORD dwStyle, dwStyleEx; + +// If only showing GUI's IL window, than we don't want to see the main window +// However, main window still manages our data, so we have to still create it. :( +// But we can "pretend" it's not there by hiding it (no WS_VISIBLE, and add WS_EX_TOOLWINDOW) + if (IsGuiILOnly()) { + dwStyle = WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_POPUP | WS_SIZEBOX; + dwStyleEx = WS_EX_TOOLWINDOW; + } else { + dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CAPTION | WS_POPUP | WS_SIZEBOX; + dwStyleEx = WS_EX_CLIENTEDGE; + } + g_hwndMain = WszCreateWindowEx(dwStyleEx, + MAIN_WINDOW_CLASSW, + L"IL DASM ", //MAIN_WINDOW_CAPTIONW, + dwStyle, + guiInfo.x, + guiInfo.y, + guiInfo.w, + guiInfo.h, + NULL, + g_hMenu, // menu + g_hInstance, // hinst + NULL + ); + if (g_hwndMain == NULL) + return FALSE; + DragAcceptFiles(g_hwndMain,TRUE); + SendMessageA(g_hwndMain,WM_SETTEXT, 0, (LPARAM)"IL DASM "); + return TRUE; +} + + +// +// Given a CL token, find the classitem for it +// +ClassItem_t *FindClassItem(mdTypeDef cl) +{ + DWORD i; + + for (i = 0; i < g_NumClassItems; i++) + { + if ((*g_ClassItemList)[i].cl == cl) + return &(*g_ClassItemList)[i]; + } + + return NULL; +} + + +// +// Given a class name, find the classitem for it (may fail) +// +ClassItem_t *FindClassItem(__in_opt __nullterminated char *pszFindNamespace, __in __nullterminated char *pszFindName) +{ + DWORD i; + + for (i = 0; i < g_NumClassItems; i++) + { + const char *pszClassName; + const char *pszNamespace; + + if((*g_ClassItemList)[i].cl) + { + + if (FAILED(g_pImport->GetNameOfTypeDef( + (*g_ClassItemList)[i].cl, + &pszClassName, + &pszNamespace))) + { + pszClassName = pszNamespace = "Invalid TypeDef record"; + } + MAKE_NAME_IF_NONE(pszClassName,(*g_ClassItemList)[i].cl); + + if (!strcmp(pszFindName, pszClassName)) + { + if ((((pszFindNamespace == NULL)||(*pszFindNamespace == 0)) + &&((pszNamespace == NULL)||(*pszNamespace == 0))) + ||(!strcmp(pszFindNamespace, pszNamespace))) + return &(*g_ClassItemList)[i]; + } + } + } + //MessageBox(NULL,pszFindName,"Class Not Found",MB_OK); + return NULL; +} + + +ClassItem_t *FindClassItem(HTREEITEM hItem) +{ + DWORD i; + + for (i = 0; i < g_NumClassItems; i++) + { + if ((*g_ClassItemList)[i].hItem == hItem) + return &(*g_ClassItemList)[i]; + } + + return NULL; +} + + +// +// Init GUI components +// +BOOL CreateGUI() +{ + + if (InitGUI() == FALSE) + return FALSE; + + // Register the window class for the main window. + if (CreateMainWindow() == FALSE) + return FALSE; + + g_hwndTreeView = CreateTreeView(g_hwndMain); + if (g_hwndTreeView == NULL) + return FALSE; + + return 0; +} + + +// +// This is the main loop which the disassembler sits in when in GUI mode +// +void GUIMainLoop() +{ + MSG msg; + HACCEL hAccel = NULL; + + _ASSERTE(g_hResources != NULL); + hAccel = WszLoadAccelerators(g_hResources,L"FileAccel"); + // Accelerator tables are released when the app exits + while (WszGetMessage(&msg, (HWND) NULL, 0, 0)) + { + // Dispatch message to appropriate window + if((g_hFindText == NULL)|| !WszIsDialogMessage(g_hFindText,&msg)) + { + if(hAccel && WszTranslateAccelerator(g_hwndMain,hAccel,&msg)); + else + { + TranslateMessage(&msg); + WszDispatchMessage(&msg); + } + } + } + GUICleanupClassItems(); +} +// Dump one tree item to a text file (calls itself recursively) +void DumpTreeItem(HTREEITEM hSelf, FILE* pFile, __inout __nullterminated WCHAR* szIndent) +{ + HTREEITEM hNext; + TVITEMEXW tvi; + static WCHAR szText[2048]; + WCHAR* wzString = (WCHAR*)GlobalBuffer; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_TEXT; + tvi.hItem = hSelf; + tvi.pszText = szText; + tvi.cchTextMax = 2047; + if(WszSendMessage(g_hwndTreeView,TVM_GETITEMW,0,(LPARAM)(&tvi))) + { + WCHAR* szType = NULL; + if(hSelf == g_hRoot) szType = L"MOD"; + else + { + switch(tvi.iImage) + { + case CLASS_IMAGE_INDEX: szType = L"CLS"; break; + case EVENT_IMAGE_INDEX: szType = L"EVT"; break; + case FIELD_IMAGE_INDEX: szType = L"FLD"; break; + case NAMESPACE_IMAGE_INDEX: szType = L"NSP"; break; + case METHOD_IMAGE_INDEX: szType = L"MET"; break; + case PROP_IMAGE_INDEX: szType = L"PTY"; break; + case STATIC_FIELD_IMAGE_INDEX: szType = L"STF"; break; + case STATIC_METHOD_IMAGE_INDEX: szType = L"STM"; break; + case CLASSENUM_IMAGE_INDEX: szType = L"ENU"; break; + case CLASSINT_IMAGE_INDEX: szType = L"INT"; break; + case CLASSVAL_IMAGE_INDEX: szType = L"VCL"; break; + } + } + if(szType) swprintf_s(wzString,4096,L"%s___[%s] %s",szIndent,szType,szText); + else swprintf_s(wzString,4096,L"%s %s",szIndent,szText); + } + else swprintf_s(wzString,4096,L"%sGetItemW failed",szIndent); + printLineW(pFile,wzString); + *wzString = 0; + if(hNext = TreeView_GetChild(g_hwndTreeView,hSelf)) + { + wcscat_s(szIndent,MAX_FILENAME_LENGTH,L" |"); + + do { + DumpTreeItem(hNext,pFile,szIndent); + } while(hNext = TreeView_GetNextSibling(g_hwndTreeView,hNext)); + + szIndent[wcslen(szIndent)-4] = 0; + printLineW(pFile,szIndent); + } +} +#endif |