0

I'm trying to edit PluginSysInfo from the Rainmeter API to include IPv6 support. I have modified the code from SysInfo.cpp to do so as far as I know the included link has the edits I've made to SysInfo.cpp.

When I build it in Visual Studio "identifier GetTcp6Table undefined" and "identifier PMIB_IP6TABLE undefined" even though they are in the include file #include <WinSock2.h>.

https://pastebin.com/N30HYRVe

#include <algorithm>
#include <windows.h>
#include <WinSock2.h>
...
MEASURE_IP6_ADDRESS
...
    else if (_wcsicmp(L"IP6_ADDRESS", type) == 0)
    {
        defaultData = 0;
        measure->type = MEASURE_IP6_ADDRESS;
    }
...
 
case MEASURE_IP6_ADDRESS:
            if (NO_ERROR == GetTcp6Table((PMIB_IP6TABLE)tmpBuffer, &tmpBufferLen, FALSE))
            {
                PMIB_IP6TABLE TcpTable = (PMIB_IP6TABLE)tmpBuffer;
                if (measure->useBestInterface)
                {
                    for (UINT i = 0; i < TcpTable->dwNumEntries; ++i)
                    {
                        if (TcpTable->table[i].dwIndex == measure->data)
                        {
                            DWORD ip = TcpTable->table[i].dwAddr;
                            wsprintf(sBuffer, L"%x:%x:%x:%x"/*:%x:%x:%x:%x"*/, ip % 65535, (ip >> 8) % 65535, (ip >> 16) % 65535, (ip >> 24) % 65535);
                            return sBuffer;
                        }
                    }
                }
dxiv
  • 16,984
  • 2
  • 27
  • 49
Whitequill Riclo
  • 788
  • 2
  • 8
  • 19
  • The [documentation](https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcp6table) says you need `#include `. – tadman Jun 23 '20 at 04:16
  • I have looked at the documentation I don't seem to be putting 2 and 2 together though. – Whitequill Riclo Jun 23 '20 at 04:38
  • @WhitequillRiclo Function `GetTcp6Table` is declared in `iphlpapi.h`, which in turn requires `winsock2.h`. If you open the `iphlpapi.h` file you'll find a comment "*The following definitions require Winsock2*" right before the declaration of `GetTcp6Table`. Originally, you `#include`'d those headers *before* `windows.h`, now you moved them *after* `windows.h`, but have still *not* defined `WIN32_LEAN_AND_MEAN` which causes the conflict explained in the quote at the end of my answer. – dxiv Jun 23 '20 at 04:57

1 Answers1

0

There is a known conflict between the Win32 headers <winsock2.h> and <windows.h>, see for example 1, 2.

The Microsoft documentation recommends to use one of two #include sequences.

  • Without <windows.h>:
#include <winsock2.h>
#include <ws2tcpip.h>
  • With <windows.h>:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>

Since GetTcp6Table requires <iphlpapi.h> OP's case should use the latter one.

Quoting from the same documentation:

The Iphlpapi.h header file is required if an application is using the IP Helper APIs. When the Iphlpapi.h header file is required, the #include line for the Winsock2.h header file should be placed before the #include line for the Iphlpapi.h header file.

The Winsock2.h header file internally includes core elements from the Windows.h header file, so there is not usually an #include line for the Windows.h header file in Winsock applications. If an #include line is needed for the Windows.h header file, this should be preceded with the #define WIN32_LEAN_AND_MEAN macro. For historical reasons, the Windows.h header defaults to including the Winsock.h header file for Windows Sockets 1.1. The declarations in the Winsock.h header file will conflict with the declarations in the Winsock2.h header file required by Windows Sockets 2.0. The WIN32_LEAN_AND_MEAN macro prevents the Winsock.h from being included by the Windows.h header.


[ EDIT ]   Following up on the comment, below is a complete snippet that builds correctly.

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <winwock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <stdlib.h> // _countof

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")

int main()
{
    BYTE tmpBuffer[7168];
    ULONG tmpBufferLen = _countof(tmpBuffer);

    return NO_ERROR == GetTcp6Table((PMIB_TCP6TABLE)tmpBuffer, &tmpBufferLen, FALSE);
}
dxiv
  • 16,984
  • 2
  • 27
  • 49
  • I've updated the linked code on pastebin. I still seem to be having the same problems. I'm a python3 dev. I'm not used to C++. – Whitequill Riclo Jun 24 '20 at 05:50
  • @WhitequillRiclo I edited a complete code snippet into the answer. Note that the first argument to [`GetTcp6Table`](https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-gettcp6table) is `PMIB_TCP6TABLE`, not `PMIB_IP6TABLE`. – dxiv Jun 24 '20 at 16:59
  • a little off topic but; what does `PMIB_TCP6TABLE` read from? cause it doesn't give the unicast address when I use `DWORD ip = TcpTable->table[measure->data].dwLocalPort;` Otherwise, the problem is completely solved. – Whitequill Riclo Jun 28 '20 at 07:30
  • The IP would not be in `dwLocalPort`, see the [MIB_TCP6ROW structure](https://learn.microsoft.com/en-us/windows/win32/api/tcpmib/ns-tcpmib-mib_tcp6row) for details. – dxiv Jun 28 '20 at 07:41