autodefine "off" $include "windowssdk.inc" CONST BTN_FOLDER = 1000 CONST LB_DLLS = 1001 CONST LV_1 = 1002 DECLARE EXTERN dup ALIAS _DUP$(path:POINTER),POINTER DECLARE EXTERN _ibstrcpy(szdest:POINTER,szsrc:POINTER) DIALOG d1 CREATEDIALOG d1,0,0,640,480,0x80CA0880,0,"Dll Viewer",&d1_handler CONTROL d1,@LISTBOX,"",10,30,150,440,0x50B10143|@BORDER,LB_DLLS CONTROL d1,@STATIC,"Select a DLL:",10,8,68,13,0x5000010B,2 CONTROL d1,@LISTVIEW,"",170,6,460,462,0x5081000D|@BORDER,LV_1 CONTROL d1,@BUTTON,"Folder...",90,4,70,20,0x50010000,BTN_FOLDER DOMODAL d1 END CONST SEM_FAILCRITICALERRORS = 1 SUB d1_handler(),INT select @MESSAGE case @IDINITDIALOG CENTERWINDOW d1 SETCONTROLCOLOR d1,BTN_FOLDER,RGB(0,0,255),RGB(192,192,192) ISTRING path[260] GetSystemDirectory(path,260) EnumDLLs(d1,path) ControlCmd(d1, LV_1, @LVINSERTCOLUMN,0,"#") ControlCmd(d1, LV_1, @LVINSERTCOLUMN,1,"Function Pointer") ControlCmd(d1, LV_1, @LVINSERTCOLUMN,2,"Function Name") ControlCmd(d1, LV_1, @LVSETCOLWIDTH,0,35) ControlCmd(d1, LV_1, @LVSETCOLWIDTH,1,100) ControlCmd(d1, LV_1, @LVSETCOLWIDTH,2,-2) SendMessage(d1, 0x1000 + 54,0,0x420,LV_1) ' if you try to LoadLibrary() with invalid image file the system displays the critical-error-handler message box SetErrorMode(SEM_FAILCRITICALERRORS) case @IDCLOSEWINDOW FreeHeap(GetProp(d1.hWnd, "PATH")) RemoveProp(d1.hWnd, "PATH") CloseDialog(d1) case @IDCONTROL if (@CONTROLID = LB_DLLS) and (@NOTIFYCODE=@LBNSELCHANGE) ShowDLLExports(d1, GetSelected(d1,LB_DLLS)) endif /*add-on*/ if (@CONTROLID = BTN_FOLDER) and (@NOTIFYCODE=0) _ibstrcpy(path, GetProp(d1.hWnd, "PATH")) if FolderRequest(d1.hWnd, "Change Folder", path, path, 0) FreeHeap(GetProp(d1.hWnd, "PATH")) EnumDLLs(d1,path) endif endif /*add-on*/ if (@CONTROLID = LV_1) and (@NOTIFYCODE=@LVNCOLUMNCLICK) lvSort() endif endselect return 0 ENDSUB CONST LB_RESETCONTENT = 0x184 CONST LB_DIR = 0x18D CONST DDL_ARCHIVE = 32 CONST DDL_HIDDEN = 2 CONST DDL_SYSTEM = 4 CONST WM_SETREDRAW = 0xB Const LVM_SORTITEMSEX = 0x1000 + 81 ' custom sum CONST DDL_MY = DDL_ARCHIVE|DDL_HIDDEN|DDL_SYSTEM SUB EnumDLLs(d1:WINDOW,path:STRING) ControlCmd(d1, LV_1, @LVDELETEALL) SetProp(d1.hWnd, "PATH", dup(path)) SendMessage(d1, LB_RESETCONTENT,0,0,LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.dll", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.ax", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.cpl", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.acm", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.ocx", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.sys", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.tsp", LB_DLLS) SendMessage(d1, LB_DIR, DDL_MY, path+"\\*.xvd", LB_DLLS) setcaption d1, path ENDSUB SUB ShowDLLExports(d1:WINDOW,index:INT) ' enumerates all exports of kernel32.dll POINTER ImageBase POINTER OH_pointer /*Optional Header*/ POINTER PE_pointer /*COFF File Header*/ POINTER EXP_pointer /*Export Table address*/ POINTER NamePointerRVA /* pointer to string* pointers array */ POINTER ExportAddressTableRVA POINTER dir POINTER pszFile INT NumberOfNamePointers ControlCmd(d1, LV_1, @LVDELETEALL) dir = GetProp(d1.hWnd, "PATH") pszFile = *dir + "\\" + GetString(d1, LB_DLLS, index) setcaption d1, *pszFile ImageBase = LoadLibrary(pszFile) FreeHeap(pszFile) if (ImageBase = 0) SetCaption(d1, "Failed to load DLL") return endif if left$(*ImageBase, 2) <> "MZ" SetCaption(d1, "Not Executable") return endif PE_pointer = ImageBase + *(ImageBase+0x3C) if left$(*PE_pointer, 4) <> "PE" SetCaption(d1, "Not PE") return endif PE_pointer += 4 /*COFF File Header*/ OH_pointer = PE_pointer + 20 /*Optional Header*/ EXP_pointer = ImageBase + *(OH_pointer + 96) /*Export Table address*/ NumberOfNamePointers = *(EXP_pointer + 24) NamePointerRVA = ImageBase + *(EXP_pointer + 32) ExportAddressTableRVA = ImageBase + *(EXP_pointer + 28) ShowExports( _ d1, _ ImageBase, _ ExportAddressTableRVA, _ NamePointerRVA, _ NumberOfNamePointers) FreeLibrary(ImageBase) ENDSUB SUB ShowExports(d1:WINDOW, ImageBase:UINT, fntable:POINTER, strtable:POINTER, count:INT) INT item ' do not repaint listview every time we add an item SendMessage(d1, WM_SETREDRAW, FALSE, 0, LV_1) item=0 while count if (*fntable < 0) ControlCmd(d1, LV_1, @LVDELETEALL) SetCaption(d1, "Error! Invalid Offset") SendMessage(d1, WM_SETREDRAW, TRUE, 0, LV_1) return endif ControlCmd(d1, LV_1, @LVINSERTITEM, item, using(" #", item)) ControlCmd(d1, LV_1, @LVSETTEXT, item, 1, "0x"+hex$(ImageBase + *fntable)) ControlCmd(d1, LV_1, @LVSETTEXT, item, 2, *(ImageBase + *strtable)) fntable += 4 strtable+= 4 count-- item++ wend ' listview will be always sorted as selected SendMessage(d1, LVM_SORTITEMSEX, 0, &LVSortCallback3state, LV_1) SendMessage(d1, WM_SETREDRAW, TRUE, 0, LV_1) ENDSUB /* tools */ Declare import, SHBrowseForFolder(lpbi:POINTER),INT Declare import, SHGetPathFromIDList(pITEMIDLIST:UINT, PATH:POINTER),INT ' fills memory with given character $command _memset(...) /*(memory, char, count*/ const BFFM_INITIALIZED = 1 const BFFM_SETSELECTION = (0x400 + 102) const BFFM_VALIDATEFAILED = 3 TYPE BROWSEINFO UINT hOwner UINT pidlRoot POINTER pszDisplayName POINTER lpszTitle UINT ulFlags UINT lpfn UINT lParam UINT iImage ENDTYPE SUB FolderRequest(hWnd:uint, title:pointer, dir:pointer, initial:pointer, flags:uint),int INT r r = FALSE UINT item_list BROWSEINFO bi _memset(&bi, 0, len(bi)) bi.hOwner = hWnd bi.lpszTitle = title bi.ulFlags = flags IF flags = 0 Then bi.ulFlags = 9 | 0x42 bi.lpfn = &BrowseRequestCallback bi.lParam = initial ' Display the browser item_list = SHBrowseForFolder(&bi) IF item_list r = SHGetPathFromIDList(item_list, dir) CoTaskMemFree(item_list) Endif Return r EndSub SUB BrowseRequestCallback(hWnd:uint, uMsg:uint, lParam:uint, lpData:uint),int ' UINT dwStyle ' ISTRING szText[261] Select uMsg Case BFFM_INITIALIZED ' Set start directory SendMessage hWnd, BFFM_SETSELECTION, TRUE, lpData Case BFFM_VALIDATEFAILED Return 1 EndSelect Return 0 EndSub '////////////// listview sorting function /////////////// ' move global variables to window property INT LastClickedColumn, ClickedColumn, SortAscDesc UINT LVhWnd Const LVM_GETITEM = 4101 Const LVIF_TEXT = 1 TYPE NMLISTVIEW /*hacked!*/ NMHDR hdr INT iItem INT iSubItem[7] ENDTYPE TYPE LVITEM /*hacked!*/ UINT mask INT iItem INT iSubItem[3] POINTER pszText INT cchTextMax[7] ENDTYPE SUB lvSort() INT ColumnChanged ColumnChanged = 0 LVhWnd = *@LPARAM.hWndFrom ClickedColumn = *@LPARAM.iSubItem IF LastClickedColumn <> ClickedColumn LastClickedColumn = ClickedColumn SortAscDesc = 1 ColumnChanged = 1 Endif IF ColumnChanged=0 SortAscDesc++ IF SortAscDesc = 2 Then SortAscDesc= -1 Endif SendMessage(LVhWnd, LVM_SORTITEMSEX, 0, &LVSortCallback3state) EndSub SUB LVSortCallback3state(lParam1:int, lParam2:int, lParamSort:uint),int LVITEM lvi1, lvi2 ISTRING txt1[260], txt2[260] INT CompareResult lvi1.iItem = lParam1 lvi2.iItem = lParam2 IF (SortAscDesc = 0) lvi1.iSubItem = 0 'sort by first column lvi2.iSubItem = 0 'else sort by clicked column else lvi1.iSubItem = ClickedColumn 'the last clicked column lvi2.iSubItem = ClickedColumn 'the last clicked column Endif lvi1.mask = LVIF_TEXT lvi2.mask = LVIF_TEXT lvi1.pszText = &txt1 lvi2.pszText = &txt2 lvi1.cchTextMax = 260 lvi2.cchTextMax = 260 SendMessage(LVhWnd, LVM_GETITEM, 0, &lvi1) SendMessage(LVhWnd, LVM_GETITEM, 0, &lvi2) IF (SortAscDesc <> 0) CompareResult = lstrcmpi(&txt1, &txt2) CompareResult *= SortAscDesc Else CompareResult = val(txt1) > val(txt2) 'the first column is a numeric value Endif Return CompareResult EndSub