我想用GetExtendedTcpTable函数获取系统当前TCP的连接信息,我是这样做的
#define TABLE_SIZE 1024typedef struct {  
DWORD dwState;  
DWORD dwLocalAddr;  
DWORD dwLocalPort;  
DWORD dwRemoteAddr;  
DWORD dwRemotePort;  
DWORD dwOwningPid;
} MIB_TCPROW_OWNER_PID,  *PMIB_TCPROW_OWNER_PID;typedef struct {  
DWORD               dwNumEntries;  
MIB_TCPROW_OWNER_PID   table[TABLE_SIZE];
} MIB_TCPTABLE_OWNER_PID,  *PMIB_TCPTABLE_OWNER_PID;typedef enum 
{
  TCP_TABLE_BASIC_LISTENER,
  TCP_TABLE_BASIC_CONNECTIONS,
  TCP_TABLE_BASIC_ALL,
  TCP_TABLE_OWNER_PID_LISTENER,
  TCP_TABLE_OWNER_PID_CONNECTIONS,
  TCP_TABLE_OWNER_PID_ALL,
  TCP_TABLE_OWNER_MODULE_LISTENER,
  TCP_TABLE_OWNER_MODULE_CONNECTIONS,
  TCP_TABLE_OWNER_MODULE_ALL
}TCP_TABLE_CLASS,  *PTCP_TABLE_CLASS;
typedef DWORD (*PGetExtendedTcpTable)(
  PVOID pTcpTable,
  PDWORD pdwSize,
  BOOL bOrder,
  ULONG ulAf,
  TCP_TABLE_CLASS TableClass,
  ULONG Reserved
);//main函数:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;    MIB_TCPROW_OWNER_PID tableTCP;
    WSADATA WSAData;
    HINSTANCE hLibrary = LoadLibrary("Iphlpapi.dll");
    PGetExtendedTcpTable  pFuncGetTCPTable;
    pFuncGetTCPTable = (PGetExtendedTcpTable)::GetProcAddress(hLibrary, "GetExtendedTcpTable");
    WSAStartup(MAKEWORD(1, 1), &WSAData );
    DWORD dwSize;
    pFuncGetTCPTable(&tableTCP, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); //函数调用 return nRetCode;
}
但是在调试的时候,每次走到函数调用(也就是pFuncGetTCPTable(&tableTCP, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); )的时候都会中断,提示信息如下:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.这个问题捆饶我好几天了,恳请个为帮忙. 任何建议都欢迎!

解决方案 »

  1.   

    是函数指针,显示加载动态库时候,从动态库中获取的函数GetExtendedTcpTable的地址.
      

  2.   

    tableTCP只一个 MIB_TCPROW_OWNER_PID的大小,dwSize是个in,out的参数, 其值也正确。应该先传一个NULL, 0(dwSize), 得到需要的dwSize, 然后分配内存,再调用一次。
      

  3.   

    你的问题解决了么?
    我完全重现你的问题,整待解决了中似乎是MS的一个bug啊。因为MSDN说GetExtendedTcpTable声明在Iphlpapi.h中,但实际却找不到(已经是最近SDK了),但在.dll和.lib中都能找到。显然是MS的一个bug。迫不得己,才用动态加载的方式。但却运行错误。
      现在怀疑MSDN中关于GetExtenedTcpTable函数的参数说明是否正确?
      

  4.   

    主要的问题应该是Iphlpapi.lib和Iphlpapi.dll中声明的函数是以C语言名称修饰的,而你使用的是C++的编译器,所以显式和隐式调用都会有问题。你可以通过extern声明方式予以声明,例如 
    extern "C" DWORD __stdcall    GetExtendedTcpTable(
      PVOID pTcpTable,
      PDWORD pdwSize,
      ULONG bOrder,
      ULONG ulAf,
      ULONG TableClass,
      ULONG Reserved
    );关于C和C++函数声明方式的问题,可以去看http://blog.csdn.net/thomasliu83/archive/2006/03/08/618403.aspx
      

  5.   

    把这个改一下就行了:
    typedef   DWORD   (*PGetExtendedTcpTable)( 
        PVOID   pTcpTable, 
        PDWORD   pdwSize, 
        BOOL   bOrder, 
        ULONG   ulAf, 
        TCP_TABLE_CLASS   TableClass, 
        ULONG   Reserved 
    ); 
    改为:
    typedef   DWORD   (WINAPI*PGetExtendedTcpTable)( 
        PVOID   pTcpTable, 
        PDWORD   pdwSize, 
        BOOL   bOrder, 
        ULONG   ulAf, 
        TCP_TABLE_CLASS   TableClass, 
        ULONG   Reserved 
    ); 
    调用dll中的函数要特别小心这里
      

  6.   

    这个WINAPI其实就是__stdcall,这是win32 API中函数的默认调用方式,意思是由被调函数清栈(即函数GetExtendedTcpTable它返回的时候自己会清栈),
    而c/c++默认的调用方式为__cdecl,意思是由主调函数清栈(主函数_tmain会完成调用函数的清栈工作)。此时,你没有为函数GetExtendedTcpTable原型前加入WINAPI,c/c++编译器会加入清栈部分代码,而win32 API中的函数都是__stdcall调用方式,函数内部会完成清栈工作,这样,一次压栈对应了2次清栈,打破了堆栈的平衡,不出错才怪。如果你在函数GetExtendedTcpTable原型前加入WINAPI,则c/c++编译器知道该函数内部会自己清栈,所以编译后不会再在主函数_tmain中加入函数GetExtendedTcpTable的清栈代码,堆栈得到平衡,调用也就成功了。不知道这样说你明白了没有
      

  7.   

    这个WINAPI其实就是__stdcall,这是win32 API中函数的默认调用方式,意思是由被调函数清栈(即函数GetExtendedTcpTable它返回的时候自己会清栈),
    而c/c++默认的调用方式为__cdecl,意思是由主调函数清栈(主函数_tmain会完成调用函数的清栈工作)。此时,你没有为函数GetExtendedTcpTable原型前加入WINAPI,c/c++编译器会加入清栈部分代码,而win32 API中的函数都是__stdcall调用方式,函数内部会完成清栈工作,这样,一次压栈对应了2次清栈,打破了堆栈的平衡,不出错才怪。如果你在函数GetExtendedTcpTable原型前加入WINAPI,则c/c++编译器知道该函数内部会自己清栈,所以编译后不会再在主函数_tmain中加入函数GetExtendedTcpTable的清栈代码,堆栈得到平衡,调用也就成功了。不知道这样说你明白了没有