www.gusucode.com > VC++通过树菜控件显示Windows协议栈信息源码程序 > VC++通过树菜控件显示Windows协议栈信息源码程序\code\EnumProtocalView.cpp
// EnumProtocalView.cpp : implementation of the CEnumProtocalView class // Download by http://www.NewXing.com #include "stdafx.h" #include "EnumProtocal.h" #include "EnumProtocalDoc.h" #include "EnumProtocalView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView IMPLEMENT_DYNCREATE(CEnumProtocalView, CTreeView) BEGIN_MESSAGE_MAP(CEnumProtocalView, CTreeView) //{{AFX_MSG_MAP(CEnumProtocalView) //}}AFX_MSG_MAP // Standard printing commands ON_COMMAND(ID_FILE_PRINT, CTreeView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CTreeView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, CTreeView::OnFilePrintPreview) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView construction/destruction CEnumProtocalView::CEnumProtocalView() { WSACleanup(); } CEnumProtocalView::~CEnumProtocalView() { } BOOL CEnumProtocalView::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS; return CTreeView::PreCreateWindow(cs); } ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView drawing void CEnumProtocalView::OnDraw(CDC* pDC) { CEnumProtocalDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here } void CEnumProtocalView::OnInitialUpdate() { CTreeView::OnInitialUpdate(); WSADATA wsa; WSAStartup(MAKEWORD(2,2),&wsa); AddAllProtocals(); // TODO: You may populate your TreeView with items by directly accessing // its tree control through a call to GetTreeCtrl(). } ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView printing BOOL CEnumProtocalView::OnPreparePrinting(CPrintInfo* pInfo) { // default preparation return DoPreparePrinting(pInfo); } void CEnumProtocalView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add extra initialization before printing } void CEnumProtocalView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { // TODO: add cleanup after printing } ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView diagnostics #ifdef _DEBUG void CEnumProtocalView::AssertValid() const { CTreeView::AssertValid(); } void CEnumProtocalView::Dump(CDumpContext& dc) const { CTreeView::Dump(dc); } CEnumProtocalDoc* CEnumProtocalView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CEnumProtocalDoc))); return (CEnumProtocalDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CEnumProtocalView message handlers LPCTSTR CEnumProtocalView::GetProtoDesc(int iProtocol) { // WINSOCK2.H switch(iProtocol) { case IPPROTO_IP: return "IPPROTO_IP"; case IPPROTO_ICMP: return "IPPROTO_ICMP"; case IPPROTO_IGMP: return "IPPROTO_IGMP"; case IPPROTO_GGP: return "IPPROTO_GGP"; case IPPROTO_TCP: return "IPPROTO_TCP"; case IPPROTO_PUP: return "IPPROTO_PUP"; case IPPROTO_UDP: return "IPPROTO_UDP"; case IPPROTO_IDP: return "IPPROTO_IDP"; case IPPROTO_ND: return "IPPROTO_ND"; case IPPROTO_RAW: return "IPPROTO_RAW"; // Novell - WSIPX.H case NSPROTO_IPX: return "NSPROTO_IPX"; case NSPROTO_SPX: return "NSPROTO_SPX"; case NSPROTO_SPXII: return "NSPROTO_SPXII"; //DecNet - WS2DNET.H case ISOPROTO_TP_CONS: return "ISOPROTO_TP_CONS"; case ISOPROTO_TP4_CLNS: return "ISOPROTO_TP4_CLNS"; case ISOPROTO_CLTP_CLNS: return "ISOPROTO_CLTP_CLNS"; case ISOPROTO_X25: return "ISOPROTO_X25"; // ATM - WS2ATM.H case ATMPROTO_AAL5: return "ATMPROTO_AAL5"; // RSVP - WS2RSVP.H case IPPROTO_RSVP: return "IPPROTO_RSVP"; default: return("Unknown Protocol Description"); } } void CEnumProtocalView::AddAllProtocals() { LPBYTE pBuf; //保存网络协议信息的缓冲区 DWORD dwLen; //缓冲区的长度 LPWSAPROTOCOL_INFO pInfo; HTREEITEM hParent; HTREEITEM hParent2; HTREEITEM hParent3; //通过第一次调用WSAEnumProtocols以获得所需缓冲区的大小 dwLen = 0; int nRet = WSAEnumProtocols(NULL, NULL, //指定WSAPROTOCOL_INFO结构为空 &dwLen); if (nRet == SOCKET_ERROR) { // 调用失败 if (WSAGetLastError() != WSAENOBUFS) { CString strTemp; strTemp.Format("EnumProtocals() failed:%d",WSAGetLastError()); AfxMessageBox(strTemp); return; } } //检查缓冲区的大小是否可以容纳信息 if (dwLen < sizeof(WSAPROTOCOL_INFO)) { AfxMessageBox("Internal error"); return; } dwLen++; pBuf = (LPBYTE) malloc(dwLen); //申请所需的内存 if (pBuf == NULL) { AfxMessageBox("Couldn't allocate protocol buffer"); return; } //进行第二次实际的调用,nRet返回协议的个数 nRet = WSAEnumProtocols(NULL, (LPWSAPROTOCOL_INFO)pBuf, &dwLen); if (nRet == SOCKET_ERROR) { //调用失败 free(pBuf); CString strTemp; strTemp.Format("EnumProtocals() failed:%d",WSAGetLastError()); AfxMessageBox(strTemp); return; } //遍历各协议的信息,把不同层次的协议信息加到树形视图中 pInfo = (LPWSAPROTOCOL_INFO)pBuf; for(int nCount = 0; nCount < nRet; nCount++) { // 每个协议从根开始添加 hParent = AddTreeItem(GetTreeCtrl().m_hWnd, TVI_ROOT, pInfo->szProtocol); // 接着添加该协议所支持的特性 hParent2 = AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Service Flags"); //定义宏以便添加协议支持的特性 #define ADDSF(f, s1, s2) \ AddTreeItem(GetTreeCtrl().m_hWnd, \ hParent2, \ (pInfo->dwServiceFlags1 & f) ? \ s1 : s2) //提供无连接服务 ADDSF(XP1_CONNECTIONLESS, "Connectionless", "Connection-oriented"); //保证发送出去的所有数据都将到达既定接收端 ADDSF(XP1_GUARANTEED_DELIVERY, "Delivery guaranteed", "Delivery NOT guaranteed"); //保证数据按其发送顺序到达接收端,且数据不会重复 ADDSF(XP1_GUARANTEED_ORDER, "Order guaranteed", "Order NOT guaranteed"); //实现消息边界 ADDSF(XP1_MESSAGE_ORIENTED, "Message boundaries preserved", "Message boundaries NOT preserved"); if (pInfo->dwServiceFlags1 & XP1_PSEUDO_STREAM) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Message oriented with boundaries ignored"); //支持支持二相关闭 ADDSF(XP1_GRACEFUL_CLOSE, "Can perform graceful close", "Abortive close only"); //该协议提供带外数据 ADDSF(XP1_EXPEDITED_DATA, "Supports expedited data", "Doesn't support expedited data"); //支持面向连接服务 ADDSF(XP1_CONNECT_DATA, "Supplies connect data", "Doesn't supply connect data"); ADDSF(XP1_DISCONNECT_DATA, "Supplies disconnect data", "Doesn't supply disconnect data"); //支持广播 ADDSF(XP1_SUPPORT_BROADCAST, "Supports broadcasts", "Doesn't support broadcasts"); // 支持多播 if (pInfo->dwServiceFlags1 & XP1_SUPPORT_MULTIPOINT) { hParent3 = AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Supports multicast"); //支持多播特性包括两个方面:可以打开控制面板或不可以 AddTreeItem(GetTreeCtrl().m_hWnd, hParent3, (pInfo->dwServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) ? "Control plane rooted" : "Control plane non-rooted"); AddTreeItem(GetTreeCtrl().m_hWnd, hParent3, (pInfo->dwServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) ? "Data plane rooted" : "Data plane non-rooted"); } else AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Doesn't support multicast"); //支持服务质量控制 ADDSF(XP1_QOS_SUPPORTED, "Supports quality of service", "Doesn't support quality of service"); //单向发送 if (pInfo->dwServiceFlags1 & XP1_UNI_SEND) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Unidirectional in the send direction"); //单向接收 if (pInfo->dwServiceFlags1 & XP1_UNI_RECV) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Unidirectional in the recv direction"); //单向发送和接收 if (!(pInfo->dwServiceFlags1 & XP1_UNI_SEND) && !(pInfo->dwServiceFlags1 & XP1_UNI_RECV)) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Bidirectional sending and receiving"); if (pInfo->dwServiceFlags1 & XP1_IFS_HANDLES) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Socket descriptors are IFS handles"); ADDSF(XP1_PARTIAL_MESSAGE, "Supports MSG_PARTIAL", "Doesn't support MSG_PARTIAL"); //协议提供商 hParent2 = AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Provider Flags"); if (pInfo->dwProviderFlags & PFL_MULTIPLE_PROTO_ENTRIES) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "This is one behavior of two or" " more for this protocol"); if (pInfo->dwProviderFlags & PFL_RECOMMENDED_PROTO_ENTRY) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "This is the recommended entry" " for this protocol."); //显示隐藏的目录入口 if (pInfo->dwProviderFlags & PFL_HIDDEN) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "WS2 SPI ERROR." " Hidden catalog entry shown"); //设置协议参数为0 if (pInfo->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO) AddTreeItem(GetTreeCtrl().m_hWnd, hParent2, "Use zero as protocol parameter"); AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "GUID: %s", GUIDtoString((GUID *)&pInfo->ProviderId)); //目录入口 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Catalog entry: %ld", pInfo->dwCatalogEntryId); // 协议链 switch(pInfo->ProtocolChain.ChainLen) { case 0: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Layered protocol"); break; case 1: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Base protocol"); break; default: if (pInfo->ProtocolChain.ChainLen > 1) AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Protocol chain"); else AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SPI ERROR:" " Invalid ChainLen"); } //协议的版本信息 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Version: %d", pInfo->iVersion); // 地址族 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Address family: %s", GetDescription(pInfo->iAddressFamily)); //这里调用GetDescription获得相应地址索引的描述。 // SOCKADDR的最大尺寸 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Min/Max Address length: %d/%d", pInfo->iMinSockAddr, pInfo->iMaxSockAddr); // 支持的套接字类型 switch(pInfo->iSocketType) { case SOCK_STREAM: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SOCK_STREAM"); break; case SOCK_DGRAM: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SOCK_DGRAM"); break; case SOCK_RAW: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SOCK_RAW"); break; case SOCK_RDM: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SOCK_RDM"); break; case SOCK_SEQPACKET: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "SOCK_SEQQPACKET"); break; default: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Unknown"); } // 协议 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Protocol: %s", GetProtoDesc(pInfo->iProtocol)); //这里调用GetProtoDesc函数获取相应的协议的描述 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Protocol Max Offset: %d", pInfo->iProtocolMaxOffset); // 网络子节顺序 switch(pInfo->iNetworkByteOrder) { case BIGENDIAN: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Big Endian"); break; case LITTLEENDIAN: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Little Endian"); break; default: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Unknown"); } //支持的安全特性 AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Security scheme: %d", pInfo->iSecurityScheme); // 报文的最大尺寸 switch(pInfo->dwMessageSize) { case 0: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Max message siz≥e" " not applicable"); break; case 1: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Max message size based on MTU"); break; case 0xFFFFFFFF: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "No limit on max message size"); break; default: AddTreeItem(GetTreeCtrl().m_hWnd, hParent, "Unknown max message size: %ld", pInfo->dwMessageSize); } // 读取下一个协议 pInfo++; } //操作结束,释放内存 free(pBuf); return; } HTREEITEM CEnumProtocalView::AddTreeItem(HWND hWndTree, HTREEITEM hParent, LPSTR lpszFormat, ...) { va_list Marker; char szBuf[256]; TV_ITEM tvi; TV_INSERTSTRUCT tvis; // Format the string va_start(Marker, lpszFormat); vsprintf(szBuf, lpszFormat, Marker); va_end(Marker); // Fill in the TV_ITEM structure tvi.mask = TVIF_TEXT; tvi.pszText = szBuf; tvi.cchTextMax = lstrlen(szBuf); // Fill in the TV_INSERTSTRUCT tvis.item = tvi; tvis.hInsertAfter = TVI_LAST; tvis.hParent = hParent; return (TreeView_InsertItem(hWndTree, &tvis)); } LPCTSTR CEnumProtocalView::GUIDtoString(GUID *pGUID) { static char szStr[33]; wsprintf(szStr, "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", pGUID->Data1, pGUID->Data2, pGUID->Data3, pGUID->Data4[0], pGUID->Data4[1], pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7]); return(szStr); } LPCTSTR CEnumProtocalView::GetDescription(int nAddressFamily) { switch(nAddressFamily) { case AF_UNSPEC: return "AF_UNSPEC"; case AF_UNIX: return "AF_UNIX"; case AF_INET: return "AF_INET"; case AF_IMPLINK: return "AF_IMPLINK"; case AF_PUP: return "AF_PUP"; case AF_CHAOS: return "AF_CHAOS"; // AF_NS, "AF_NS", // Same as AF_IPX case AF_IPX: return "AF_IPX"; case AF_ISO: return "AF_ISO"; case AF_ECMA: return "AF_ECMA"; case AF_DATAKIT: return "AF_DATAKIT"; case AF_CCITT: return "AF_CCITT"; case AF_SNA: return "AF_SNA"; case AF_DECnet: return "AF_DECnet"; case AF_DLI: return "AF_DLI"; case AF_LAT: return "AF_LAT"; case AF_HYLINK: return "AF_HYLINK"; case AF_APPLETALK: return "AF_APPLETALK"; case AF_NETBIOS: return "AF_NETBIOS"; case AF_VOICEVIEW: return "AF_VOICEVIEW"; case AF_FIREFOX: return "AF_FIREFOX"; case AF_UNKNOWN1: return "AF_UNKNOWN1 Somebody is using this!"; case AF_BAN: return "AF_BAN"; case AF_ATM: return "AF_ATM"; case AF_INET6: return "AF_INET6"; default: return("Unknown Protocol Type"); } }