Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Odd "undefined reference" error

So I'm trying to make a really simple abstraction library on top of the Windows API using C. I made a simple Makefile and when I try to make the project using Msys, I get this:

winapi.o: In function `get_client_pid':
(long path)/winapi.c:13: undefined reference to `GetExtendedTcpTable'
(long path)/winapi.c:31: undefined reference to `GetExtendedTcpTable'
collect2.exe: error: ld returned 1 exit status
make: *** [lib] Error 1

and get_client_pid() is defined in winapi.c as

#include <stdint.h>
#include <stdio.h>
#include <windows.h>
#include <Iphlpapi.h>

#define true 1
#define false 0


    uint32_t get_client_pid()
    {
        MIB_TCPTABLE_OWNER_PID *tcpTable;
        PDWORD tableSize;
        DWORD ret = GetExtendedTcpTable(tcpTable, 
                                        tableSize, 
                                        true, 
                                        2, 
                                        TCP_TABLE_OWNER_PID_ALL,
                                        0);

        if (ret == NO_ERROR) {
            printf("ERROR get_client_pid: No error with table size at 0?\n");
            return 0;
        }
        if (ret != ERROR_INSUFFICIENT_BUFFER) {
            printf("ERROR get_client_pid: No insufficient buffer with table size at 0?\n");
            return 0;
        }
        printf("TABLE SIZE %d\n", *tableSize);
        tcpTable = malloc(*tableSize);

        ret = GetExtendedTcpTable(  tcpTable,
                                    tableSize, 
                                    true,
                                    2,
                                    TCP_TABLE_OWNER_PID_ALL,
                                    0);

        if (ret != NO_ERROR) {
            printf("ERROR get_client_pid: GetExtendedTcpTable error: %d\n", ret);
            free(tcpTable);
            return 0;
        }

        int i;
        for (i = 0; i < tcpTable->dwNumEntries; i++) {
            MIB_TCPROW_OWNER_PID row = tcpTable->table[i];
            if (row.dwRemotePort == 0x208 && row.dwRemoteAddr == 0x100007F) {
                printf("FOUND PROCESS: %d\n", row.dwOwningPid);
                free(tcpTable);
                return row.dwOwningPid;
            }
        }

        free(tcpTable);
        return 0;
    }

As this is a linker error, I'll add my makefile:

current_dir = $(shell pwd)

all: test

test: lib
    gcc -c -g tests.c
    gcc -o tests.exe tests.o -L$(current_dir) -lwinapi

lib:
    gcc -c -g winapi.c
    gcc -shared -o winapi.dll winapi.o -lIphlpapi -luser32

clean:
    rm *.o

I have to say that I tried every possible place to insert "-lIphlpapi" in case the linking was somehow in the wrong order but that didn't help.

like image 983
vuolen Avatar asked Jan 13 '16 20:01

vuolen


People also ask

How do you fix a undefined reference error?

So when we try to assign it a value in the main function, the linker doesn't find the symbol and may result in an “unresolved external symbol” or “undefined reference”. The way to fix this error is to explicitly scope the variable using '::' outside the main before using it.

How do you fix undefined references in C++?

You can fix undefined reference in C++ by investigating the linker error messages and then providing the missing definition for the given symbols. Note that not all linker errors are undefined references, and the same programmer error does not cause all undefined reference errors.

What does undefined reference to main mean in C++?

Undefined reference to main() means that your program lacks a main() function, which is mandatory for all C++ programs.

What does undefined symbol mean in C++?

Generating an Executable Output File A symbol remains undefined when a symbol reference in a relocatable object is never matched to a symbol definition.


1 Answers

MinGW defines WINVER as 0x400 (Windows NT) in windef.h, and this means that some newer features of Windows will not link.

#ifndef WINVER
#define WINVER 0x0400
/*
 * If you need Win32 API features newer the Win95 and WinNT then you must
 * define WINVER before including windows.h or any other method of including
 * the windef.h header.
 */
#endif

So you need to define WINVER yourself to the version of Windows you are targeting before including any Windows headers.

Use one of the following definitions:

#define WINVER 0x0500 // Windows 2000
#define WINVER 0x0501 // Windows XP
#define WINVER 0x0502 // Windows Server 2003
#define WINVER 0x0600 // Windows Vista, Windows Server 2008
#define WINVER 0x0601 // Windows 7
#define WINVER 0x0602 // Windows 8
#define WINVER 0x0603 // Windows 8.1
#define WINVER 0x0A00 // Windows 10
like image 149
Martin Broadhurst Avatar answered Oct 29 '22 23:10

Martin Broadhurst