win32 api讲解 (深入理解dna)

深入理解安卓,深入理解jwt

前言

在上一节中我们对资源表进行了解析,在这一节里面我们来了解通用控件。

准备工作

首先新建一个资源脚本

深入理解安卓,深入理解jwt

创建一个dialog

深入理解安卓,深入理解jwt

在父窗口里新建两个窗口

深入理解安卓,深入理解jwt

添加一些按钮,修改字体后如下图所示

深入理解安卓,深入理解jwt

然后添加Dialog的相关函数

深入理解安卓,深入理解jwt

深入理解安卓,深入理解jwt

然后大体的框架就已经搭建了出来

深入理解安卓,深入理解jwt

标准控件和通用控件

对于windows标准的控件总是可用的

Static
Group Box
Button
Check Box
Radio Button
Edit
ComboBox
ListBox

因为如果把所有的控件在编译的时候全部加进exe就会使exe变得十分大,所以windows把通用控件放在了Comctrl32.dll里面

新建一个列表控件作为进程的显示窗口

深入理解安卓,深入理解jwt

再新建一个列表控件作为模块的显示窗口

深入理解安卓,深入理解jwt

这里再把样式改为报告

深入理解安卓,深入理解jwt

因为通用控件在dll里,所以还需要包含头文件

#include <commctrl.h>            
#pragma comment(lib,"comctl32.lib")

深入理解安卓,深入理解jwt

另外我们需要给windows指定我们需要使用哪一个通用控件,就需要通过INITCOMMONCONTROLSEX进行初始化

INITCOMMONCONTROLSEX

typedef struct tagINITCOMMONCONTROLSEX {
    DWORD dwSize;
    DWORD dwICC;
} INITCOMMONCONTROLSEX, *LPINITCOMMONCONTROLSEX;

第一个参数为INITCOMMONCONTROLSEX的大小,第二个参数就是使用哪一个通用控件

深入理解安卓,深入理解jwt

例如这里我应该使用的是ICC_LISTVIEW_CLASSES这个控件,但是每次找的话都会很麻烦,这里windows给我们提供了一个包含常用的通用控件的类型,即ICC_WIN95_CLASSES

INITCOMMONCONTROLSEX icex;            
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);            
icex.dwICC = ICC_WIN95_CLASSES;            
InitCommonControlsEx(&icex);

即可使用通用控件生成界面

深入理解安卓,深入理解jwt

这里再设置列,添加如下代码

void InitProcessListView(HWND hDlg)
{
    LV_COLUMN lv;                                
    HWND hListProcess;                                

    //初始化                                
    memset(&lv,0,sizeof(LV_COLUMN));                                
    //获取IDC_LIST_PROCESS句柄                                
    hListProcess = GetDlgItem(hDlg,IDC_LIST_PROCESS);                                
    //设置整行选中                                
    SendMessage(hListProcess,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);                                

    //第一列                                
    lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;                                
    lv.pszText = TEXT("进程");                //列标题                
    lv.cx = 200;                                //列宽
    lv.iSubItem = 0;                                
    //ListView_InsertColumn(hListProcess, 0, &lv);                                
    SendMessage(hListProcess,LVM_INSERTCOLUMN,0,(DWORD)&lv);                                
    //第二列                                
    lv.pszText = TEXT("PID");                                
    lv.cx = 100;                                
    lv.iSubItem = 1;                                
    //ListView_InsertColumn(hListProcess, 1, &lv);                                
    SendMessage(hListProcess,LVM_INSERTCOLUMN,1,(DWORD)&lv);                                
    //第三列                                
    lv.pszText = TEXT("镜像基址");                                
    lv.cx = 100;                                
    lv.iSubItem = 2;                                
    ListView_InsertColumn(hListProcess, 2, &lv);                                
    //第四列                                
    lv.pszText = TEXT("镜像大小");                                
    lv.cx = 100;                                
    lv.iSubItem = 3;                                
    ListView_InsertColumn(hListProcess, 3, &lv);                                

}

    case WM_INITDIALOG:
        {
            //设置ProcerssListView的风格
            InitProcessListView(hDlg);

            break;
        }

深入理解安卓,深入理解jwt

这里如果要显示数据的话应该用遍历进程的方法,但是这里还没有涉及到,就自己写代码添加进程进去显示

VOID EnumProcess(HWND hListProcess)
{
    LV_ITEM vitem;                        

    //初始化                        
    memset(&vitem,0,sizeof(LV_ITEM));                        
    vitem.mask = LVIF_TEXT;                        

    vitem.pszText = "csrss*ex.e**";                        
    vitem.iItem = 0;                        
    vitem.iSubItem = 0;                        
    //ListView_InsertItem(hListProcess, &vitem);                        
    SendMessage(hListProcess, LVM_INSERTITEM,0,(DWORD)&vitem);                        

    vitem.pszText = TEXT("448");                        
    vitem.iItem = 0;                        
    vitem.iSubItem = 1;                        
    ListView_SetItem(hListProcess, &vitem);                        

    vitem.pszText = TEXT("56590000");                        
    vitem.iItem = 0;                        
    vitem.iSubItem = 2;                        
    ListView_SetItem(hListProcess, &vitem);                        

    vitem.pszText = TEXT("000F0000");                        
    vitem.iItem = 0;                        
    vitem.iSubItem = 3;                        
    ListView_SetItem(hListProcess, &vitem);                        

    vitem.pszText = TEXT("winlogon*ex.e**");                        
    vitem.iItem = 1;                        
    vitem.iSubItem = 0;                        
    //ListView_InsertItem(hListProcess, &vitem);                        
    SendMessage(hListProcess, LVM_INSERTITEM,0,(DWORD)&vitem);                        

    vitem.pszText = TEXT("456");                        
    vitem.iSubItem = 1;                        
    ListView_SetItem(hListProcess, &vitem);                        

    vitem.pszText = TEXT("10000000");                        
    vitem.iSubItem = 2;                        
    ListView_SetItem(hListProcess, &vitem);                        

    vitem.pszText = TEXT("000045800");                        
    vitem.iSubItem = 3;                        
    ListView_SetItem(hListProcess, &vitem);                        

}

再编译生成即可发现已经生成

深入理解安卓,深入理解jwt

ListView的使用

这里提一个点,使用ListView_InsertColumnSendMessage的效果相同

ListView_InsertColumn(hListProcess, 1, &lv);    
SendMessage(hListModules,LVM_INSERTCOLUMN,1,(DWORD)&lv);

这里再写一个模块函数InitProcessListView

VOID InitModulesListView(HWND hDlg)
{
    LV_COLUMN lv;
    HWND hListModules;

    //初始化                                
    memset(&lv,0,sizeof(LV_COLUMN));                                
    //获取IDC_LIST_PROCESS句柄                                
    hListModules = GetDlgItem(hDlg,IDC_LIST_MOUDLE);                                
    //设置整行选中                                
    SendMessage(hListModules,LVM_SETEXTENDEDLISTVIEWSTYLE,LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);

    //第一列                                
    lv.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;                                
    lv.pszText = TEXT("模块名称");                //列标题                
    lv.cx = 238;                                //列宽
    lv.iSubItem = 0;                                
    //ListView_InsertColumn(hListProcess, 0, &lv);                                
    SendMessage(hListModules,LVM_INSERTCOLUMN,0,(DWORD)&lv);                                
    //第二列                                
    lv.pszText = TEXT("模块位置");                                
    lv.cx = 238;                                
    lv.iSubItem = 1;                                
    //ListView_InsertColumn(hListProcess, 1, &lv);    
    SendMessage(hListModules,LVM_INSERTCOLUMN,1,(DWORD)&lv);

}

调用函数初始化

深入理解安卓,深入理解jwt

即可得到界面

深入理解安卓,深入理解jwt

WM_NOTIFY

该消息类型与WM_COMMAND类型相似,都是由子窗口向父窗口发送的消息。WM_NOTIFY可以包含比WM_COMMAND更丰富的信息,Windows通用组件中有很多消息,都是通过WM_NOTIFY来描述的。一般标准控件在父窗口执行使用WM_COMMAND,通用控件在父窗口执行使用WM_NOTIFY

WM_NOTIFY消息中的参数如下:

wParam:控件ID

lParam:指向一个结构

typedef struct tagNMHDR {                     
        HWND hwndFrom; //发送通知消息的控制窗口句柄                    
        UINT idFrom;   //发送通知消息的控制ID值                    
        UINT code;     //通知码,如LVM_SELCHANGED                    
    } NMHDR;

这个结构体能满足一般的要求,但能描述的信息还是有限的,如果不能满足要求还可以使用另外更复杂的结构进行标识(注意这里windows会自动帮我们替换)

以下结构体都有一个共同的特点,第一个成员都是NMHDR,即WM_NOTIFY这个通用结构体,这里体现了C++继承的思想

    typedef struct tagNMLVCACHEHINT {            
        NMHDR   hdr;            
        int     iFrom;            
        int     iTo;            
    } NMLVCACHEHINT, *PNMLVCACHEHINT;            

    typedef struct tagLVDISPINFO {            
        NMHDR hdr;            
        LVITEM item;            
    } NMLVDISPINFO, FAR *LPNMLVDISPINFO;            

    typedef struct _NMLVFINDITEM {            
        NMHDR hdr;            
        int iStart;            
        LVFINDINFO lvfi;            
    } NMLVFINDITEM, *PNMLVFINDITEM;

这里首先写一个获取InitProcessListView这个模块进程的PID的函数

首先对从堆栈分配空间的缓冲区进行初始化操作

深入理解安卓,深入理解jwt

然后选择行,这里使用SendMessage()赋值给dwRowId,然后判断dwRowId的值即可得到选取的行

当我选取第一行的时候dwRowId的值为0,选取第二行的时候dwRowId的值为1

深入理解安卓,深入理解jwt

深入理解安卓,深入理解jwt

而当我没有选择有数据的行的时候,dwRowId的值就为-1

深入理解安卓,深入理解jwt

所以这里就可以写一个if语句进行条件的判断,当dwRowId的值为-1的时候直接弹出Error的弹窗

深入理解安卓,深入理解jwt

然后获取选中行的PID,要得到PID首先要确定PID所在的列,然后指定存储缓冲区的位置和大小,然后使用SendMessageMessageBox实现弹窗

深入理解安卓,深入理解jwt

效果如下

深入理解安卓,深入理解jwt

深入理解安卓,深入理解jwt

完整代码如下

VOID EnumMoudules(HWND hListProcess,WPARAM wParam,LPARAM lParam)
{
    DWORD dwRowId;
    TCHAR szPid[0x20];
    LV_ITEM lv;

    //初始化
    memset(&lv, 0 , sizeof(LV_ITEM));
    memset(szPid, 0, 0x20);

    //获取选择行
    dwRowId = SendMessage(hListProcess, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
    if (dwRowId == -1)
    {
        MessageBox(NULL, TEXT("Please choose process!"), TEXT("Error"), MB_OK);

        return;
    }

    //获取PID
    lv.iSubItem = 1;        //获取列
    lv.pszText = szPid;        //指定存储查询结果的缓冲区
    lv.cchTextMax = 0x20;    //指定缓冲区大小
    SendMessage(hListProcess, LVM_GETITEMTEXT, dwRowId, (DWORD)&lv);

    MessageBox(NULL, szPid, TEXT("PID"), MB_OK);
}

本文由 Drunkmars 原创发布转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/265424安全客 - 有思想的安全新媒体