主程序中的 
long CMainDialog::OnSend(WPARAM wParam, LPARAM lParam)和dll 中的 
::SendMessage(g_hWndCaller, HM_RECEIVE, 0, 0);有什么关系 ?谁帮我分析下 上面2句代码 和上下文,
只要你耐心!怎么报答都行
主程序:#include "IPPack.h"
#include "resource.h"
#include "EnumProcessDlg.h"#include "IPPackLib.h"
#include "ShareMemory.h"CMyApp theApp;
// dll导出函数
BOOL SetHook(BOOL bInstall, DWORD dwThreadId = 0, HWND hWndCaller = NULL)
{
// 定义导出函数的类型
typedef (WINAPI *PFNSETHOOK)(BOOL, DWORD, HWND);
// 导出函数的DLL文件名。调试时可设置为../10IPPackLib/debug/10IPPackLib.dll
char szDll[] = "10IPPackLib.dll"; // 加载DLL模块
BOOL bNeedFree = FALSE;
HMODULE hModule = ::GetModuleHandle(szDll);
if(hModule == NULL)
{
hModule = ::LoadLibrary(szDll);
bNeedFree = TRUE;
} // 获取SetHook函数的地址
PFNSETHOOK mSetHook = (PFNSETHOOK)::GetProcAddress(hModule, "SetHook");
if(mSetHook == NULL) // 文件不正确?
{
if(bNeedFree)
::FreeLibrary(hModule);
return FALSE;
} // 调用SetHook函数
BOOL bRet = mSetHook(bInstall, dwThreadId, hWndCaller); // 如果卸载,释放上面加载的模块
if(!bInstall)
::FreeLibrary(hModule); return bRet;
}BOOL CMyApp::InitInstance()
{
CMainDialog dlg;
m_pMainWnd = &dlg;
dlg.DoModal(); return FALSE; // 返回FALSE阻止程序进入消息循环
}CMainDialog::CMainDialog(CWnd* pParentWnd):CDialog(IDD_MAINDIALOG, pParentWnd)
{
}BEGIN_MESSAGE_MAP(CMainDialog, CDialog)
// 按钮的单击事件
ON_BN_CLICKED(IDC_TARGET, OnTarget)
ON_BN_CLICKED(IDC_PAUSE, OnPause)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
ON_BN_CLICKED(IDC_TOPMOST, OnTopMost)
ON_BN_CLICKED(IDC_CLOSE, OnClose)
// 列表视图的单击和删除事件
ON_NOTIFY(NM_CLICK, IDC_LISTDATA, OnClickListData)
ON_NOTIFY(LVN_DELETEITEM, IDC_LISTDATA, OnDeleteItemList)  
// 两个自定义消息
ON_MESSAGE(HM_RECEIVE, OnReceive)
ON_MESSAGE(HM_SEND, OnSend)
END_MESSAGE_MAP()BOOL CMainDialog::OnInitDialog()
{
// 让父类进行内部初始化
CDialog::OnInitDialog(); // 设置图标
SetIcon(theApp.LoadIcon(IDI_MAIN), FALSE); // 创建状态栏,设置它的属性(CStatusBarCtrl类封装了对状态栏控件的操作)
m_bar.Create(WS_CHILD|WS_VISIBLE|SBS_SIZEGRIP, CRect(0, 0, 0, 0), this, 101);
m_bar.SetBkColor(RGB(0xa6, 0xca, 0xf0)); // 背景色
int arWidth[] = { 250, -1 };
m_bar.SetParts(2, arWidth); // 分栏
m_bar.SetText(" Windows程序设计进阶之路!", 1, 0); // 第二个栏的文本 // 取得列表视图窗口的控制权,设置它的分栏
m_listData.SubclassWindow(::GetDlgItem(m_hWnd, IDC_LISTDATA));
m_listData.SetExtendedStyle(LVS_EX_FULLROWSELECT);
m_listData.InsertColumn(0, "编号", LVCFMT_LEFT, 38);
m_listData.InsertColumn(2, "类型", LVCFMT_LEFT, 80);
m_listData.InsertColumn(3, "数据", LVCFMT_LEFT, 180); // 注册热键CTRL+F9。当用户按此热键时,主窗口显示或者隐藏
if(!::RegisterHotKey(m_hWnd, 11, MOD_CONTROL, VK_F9))
{
MessageBox("注册热键CTRL+F9失败!");
} // 初始化状态数据
InitData();
// 更新用户界面
UIControl(); return TRUE;
}void CMainDialog::InitData()
{
m_bOpen = FALSE; // 没有打开
m_bPause = FALSE; // 没有暂停
}void CMainDialog::UIControl()
{
if(m_bOpen)
{
GetDlgItem(IDC_PAUSE)->EnableWindow(TRUE);
GetDlgItem(IDC_CLOSE)->EnableWindow(TRUE); if(!m_bPause)
m_bar.SetText(" 正在截拦网络数据...", 0, 0);
else
m_bar.SetText(" 暂停截拦网络数据", 0, 0);
}
else
{
GetDlgItem(IDC_PAUSE)->EnableWindow(FALSE);
GetDlgItem(IDC_CLOSE)->EnableWindow(FALSE); m_bar.SetText(" 您还没有打开目标程序", 0, 0);
} if(m_bPause)
{
GetDlgItem(IDC_PAUSE)->SetWindowText("恢复");
}
else
{
GetDlgItem(IDC_PAUSE)->SetWindowText("暂停");
}
}
void CMainDialog::OnTarget()
{
CEnumProcessDlg dlg(this);
// 弹出选择进程对话框
if(dlg.DoModal() == IDOK)
{
// 如果为其它进程安装了钩子,先卸载
if(m_bOpen)
{
SetHook(FALSE);
InitData();
}
// 为用户选择进程的主线程安装钩子
if(SetHook(TRUE, dlg.m_dwThreadId, m_hWnd))
{
m_bOpen = TRUE;
m_bPause = FALSE;
}
else
{
MessageBox(" 安装钩子出错!");
}
}
// 更新用户界面
UIControl();
}long CMainDialog::OnReceive(WPARAM wParam, LPARAM lParam)
{
CShareMemory sm("IPPACK_RECEIVE");
CMessageData *pData = (CMessageData*)sm.GetBuffer(); // 如果暂停截获,则返回
if(m_bPause)
return 0; // 可以在这里过滤数据,比如
// DoCopyFilter(pData); // 如果没有关闭发送,则显示截获到的数据
BOOL bNoSend = IsDlgButtonChecked(IDC_CLOSERECV);
if(!bNoSend)
{
// 得到已有的项目数量,以便添加一个新项
int nIndex = m_listData.GetItemCount();
if(nIndex == 100)
return 0; 

// 添加新项
char sz[32] = "";
// 转化整型数据为字符串。第三个参数10指的是以十进制方式显示的字符串
itoa(nIndex+1, sz, 10);
m_listData.InsertItem(nIndex, sz, 0);

// 设置新项文本
// 设置要显示的数据(只显示一部分即可,从共享内存中取出)
char szText[128] = "";
int nCopy = min(pData->nDataLength, 127);
strncpy(szText, pData->data(), nCopy);
// 设置文本
m_listData.SetItemText(nIndex, 1, "接受");
m_listData.SetItemText(nIndex, 2, szText);

// 保存共享内存中的数据到进程堆中,以便用户查询
// 取得数据长度,最大保存500个字节(可以根据需要自己设置)
int nTotal = sizeof(CMessageData) + pData->nDataLength;
nTotal = min(nTotal, 500);
// 在进程堆中申请空间,复制共享内存中的数据
BYTE* pByte = new BYTE[nTotal];
memcpy(pByte, pData, nTotal);
// 将首地址关联到新项中
m_listData.SetItemData(nIndex, (DWORD)pByte);
}

return 0;
}long CMainDialog::OnSend(WPARAM wParam, LPARAM lParam)
{
CShareMemory sm("IPPACK_SEND");
CMessageData *pData = (CMessageData*)sm.GetBuffer(); if(m_bPause)
return 0; // ... 可以在这里过滤数据 BOOL bNoSend = IsDlgButtonChecked(IDC_CLOSESEND);
if(!bNoSend)
{
int nIndex = m_listData.GetItemCount();
if(nIndex == 100)
return 0; 

// 添加新项
char sz[32] = "";
itoa(nIndex+1, sz, 10);
m_listData.InsertItem(nIndex, sz, 0);

// 设置新项文本
char szText[128] = "";
int nCopy = min(pData->nDataLength, 127);
strncpy(szText, pData->data(), nCopy);
m_listData.SetItemText(nIndex, 1, "发送");
m_listData.SetItemText(nIndex, 2, szText);


// 保存共享内存中的数据到进程堆中,以便用户查询
int nTotal = sizeof(CMessageData) + pData->nDataLength;
nTotal = min(nTotal, 500);
BYTE* pByte = new BYTE[nTotal];
memcpy(pByte, pData, nTotal);
m_listData.SetItemData(nIndex, (DWORD)pByte);
}
return 0;
}void CMainDialog::OnClickListData(NMHDR* pNMHDR, LRESULT* pResult) 
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // pNMListView->iItem的值为用户单击项目的索引
int nIndex = pNMListView->iItem;
if (nIndex >= 0)
{
// 以16进制的形式显示数据到编辑框
CMessageData* pData = (CMessageData*)m_listData.GetItemData(nIndex); // 为字符串申请空间
// 一个字节要占用3个字符(2个16进制数和1个空格),如“16 12 b2 c7”。所以要乘以3
char* pBuf = new char[pData->nDataLength*3 + 1]; // 转化截获的数据为16进制字符串的形式
char* pTemp = pBuf;
char* psz = pData->data();
for(int i=0; i<pData->nDataLength; i++, psz++)
{
wsprintf(pTemp, "%02x ", (BYTE)(*psz));
pTemp += 3;
}
*pTemp = '\0';

// 显示数据到编辑框中
GetDlgItem(IDC_SPECIFICDATA)->SetWindowText(pBuf); // 释放内存空间
delete[] pBuf;
} *pResult = 0;
}void CMainDialog::OnClear()
{
// 删除列表试图中的所有项,清空编辑框
m_listData.DeleteAllItems();
GetDlgItem(IDC_SPECIFICDATA)->SetWindowText("");
}void CMainDialog::OnDeleteItemList(NMHDR* pNMHDR, LRESULT* pResult) 
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // 取得要删除项目的关联数据,也可以用下面的代码
//  int nIndex = pNMListView->iItem;
// pByte = (PBYTE)m_listData.GetItemData(nIndex);
BYTE* pByte = (PBYTE)pNMListView->lParam; // 释放内存空间
delete[] pByte; *pResult = 0;
}
void CMainDialog::OnCancel()
{
// 确保钩子被卸载
if(m_bOpen)
SetHook(FALSE);
CDialog::OnCancel();
}void CMainDialog::OnClose()
{
// 用户单击关闭按钮时本函数被调用
// 重置所有状态
if(m_bOpen)
{
SetHook(FALSE);
InitData();
OnClear();
}
UIControl();
}void CMainDialog::OnPause()
{
m_bPause = !m_bPause;
UIControl();
}void CMainDialog::OnTopMost()
{
BOOL bTopMost = ::IsDlgButtonChecked(m_hWnd, IDC_TOPMOST);
if(bTopMost)
{
::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, 
SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
}
else
{
::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 
SWP_NOMOVE|SWP_NOSIZE|SWP_NOREDRAW);
}
}
dll程序:
int WINAPI hook_send(SOCKET s, const char FAR *buf, int len, int flags)
{
// 申请指定长度的共享内存空间
CShareMemory sm("IPPACK_SEND", sizeof(CMessageData) + len, TRUE);
// 取得指向共享内存的指针
CMessageData *pData = (CMessageData*)sm.GetBuffer(); // 设置参数
pData->dwThreadId = ::GetCurrentThreadId();
pData->socket = s;
pData->nDataLength = len;
memcpy(pData->data(), buf, pData->nDataLength); // 通知主窗口,进行过滤
::SendMessage(g_hWndCaller, HM_SEND, 0, 0); // 调用原来的函数,发送数据
g_send.Unhook();
int nRet = ::send(pData->socket, pData->data(), pData->nDataLength, flags);
g_send.Rehook(); return nRet;
}
CULHook g_send("Ws2_32.dll", "send", (PROC)hook_send);CULHook::CULHook(LPSTR pszModName, LPSTR pszFuncName, PROC pfnHook)
{ // jmp eax == 0xFF, 0xE0
// 生成新的执行代码
BYTE btNewBytes[8] = { 0xB8, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xE0, 0x00 }; 
memcpy(m_btNewBytes, btNewBytes, 8);
*(DWORD *)(m_btNewBytes + 1) = (DWORD)pfnHook;  // 加载指定模块,取得API函数地址
m_hModule = ::LoadLibrary(pszModName);
if(m_hModule == NULL)
{
m_pfnOrig = NULL;
return;
}
m_pfnOrig = ::GetProcAddress(m_hModule, pszFuncName);
// 修改原API函数执行代码的前8个字节,使它跳向我们的函数
if(m_pfnOrig != NULL)
{
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION    mbi;
::VirtualQuery( m_pfnOrig, &mbi, sizeof(mbi) );
::VirtualProtect(m_pfnOrig, 8, PAGE_READWRITE, &dwOldProtect); // 保存原来的执行代码
memcpy(m_btOldBytes, m_pfnOrig, 8);
// 写入新的执行代码
::WriteProcessMemory(::GetCurrentProcess(), (void *)m_pfnOrig, 
m_btNewBytes, sizeof(DWORD)*2, NULL); 

::VirtualProtect(m_pfnOrig, 8, mbi.Protect, 0);
}
}