Home > database >  Why timeout param doesn't work in GetAddrInfoExW()?
Why timeout param doesn't work in GetAddrInfoExW()?

Time:11-08

When I try to call:

timeval timeout{ 0, 999 };
::GetAddrInfoExW(L"my_name", L"", NS_DNS, nullptr, nullptr, &pResult, &timeout, nullptr, nullptr, nullptr);

I got 10022 "Invalid params".

However, if I replace "&timeout" with "nullptr", I got 0 (OK).

Why the timeout causes EINVAL error?

UNICODE macro is defined, my system is Windows 10.

CodePudding user response:

if timeout not 0, the lpOverlapped must be also not 0. the code can be next

#include <ws2tcpip.h>

struct QUERY_CONTEXT : OVERLAPPED
{
    PADDRINFOEX _pResult;
    ULONG _dwThreadId = GetCurrentThreadId();

    ~QUERY_CONTEXT()
    {
        if (PADDRINFOEX pResult = _pResult)
        {
            FreeAddrInfoEx(_pResult);
        }
    }

    static void CALLBACK QueryCompleteCallback(   
        _In_ ULONG dwError,   
        _In_ ULONG /*dwBytes*/,   
        _In_ OVERLAPPED* lpOverlapped   
        )
    {
        static_cast<QUERY_CONTEXT*>(lpOverlapped)->OnComplete(dwError);
    }

    void OnComplete(_In_ ULONG dwError)
    {
        DbgPrint("OnComplete(%u)\n");

        if (PADDRINFOEX pResult = _pResult)
        {
            do 
            {
                WCHAR buf[64];
                ULONG len = _countof(buf);
                if (!WSAAddressToStringW(pResult->ai_addr, (ULONG)pResult->ai_addrlen, 0, buf, &len))
                {
                    DbgPrint("%S\n", buf);
                }
            } while (pResult = pResult->ai_next);
        }

        PostThreadMessageW(_dwThreadId, WM_QUIT, dwError, 0);

        delete this;
    }

    ULONG Query(_In_ PCWSTR pName, _In_opt_ timeval *timeout)
    {
        ULONG dwError = GetAddrInfoExW(pName, 0, NS_DNS, 0, 0, 
            &_pResult, timeout, this, QueryCompleteCallback, 0);

        //
        //  If GetAddrInfoExW() returns  WSA_IO_PENDING, GetAddrInfoExW will invoke
        //  the completion routine. If GetAddrInfoExW returned anything else we must
        //  invoke the completion directly.
        //

        if (dwError != WSA_IO_PENDING)
        {
            QueryCompleteCallback(dwError, 0, this);
        }

        return dwError;
    }
};

///////////////////////////////////////

    WSADATA wd;
    if (NOERROR == WSAStartup(WINSOCK_VERSION, &wd))
    {
        if (QUERY_CONTEXT* pqc = new QUERY_CONTEXT {})
        {
            timeval timeout{ 1 };
            pqc->Query(L"stackoverflow.com", &timeout);
        }
        MessageBoxW(0, 0, 0, 0);
        WSACleanup();
    }

also for dns query more efficient direct use DnsQueryEx function (GetAddrInfoExW internally call DnsQueryEx, but before this - alot of another code executed)

  • Related