Hervé
Hervé

Reputation: 21

Trying to get socket from wininet HTTP connection

We have a legacy application that implements an SSL tunnel over Web proxies. It uses the wininet API and it worked fine for years on XP, but now it fails on Windows 7. I've tried to isolate the code and made a small program to reproduce the problem. It's a small C program compiled with MSVC 9. See below.

On Windows 7, once connected to the proxy (status code 200), I just cannot get the socket descriptor from the API. All I get is an INVALID_SOCKET, even though all wininet functions returned successfully and GetLastError() returned 0.

On the XP machine, all works fine and the returned socket is valid.

Does anyone have any idea? Thank you very much in advance.

#include <windows.h>
#include <wininet.h>
#include <stdio.h>

const char *_connect()
{
    HINTERNET hOpen = 0;
    HINTERNET hConnect = 0;
    HINTERNET hRequest = 0;
    int remotePort = 443;
    const char *remoteHost = "a.b.c.d"; // Cannot disclose
    hOpen = InternetOpen("wininet-test", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
    if (!hOpen) return "InternetOpen";
    hConnect = InternetConnect(hOpen, remoteHost, remotePort, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) return "InternetConnect";
    {
        DWORD flags =
            INTERNET_FLAG_CACHE_IF_NET_FAIL |
            INTERNET_FLAG_IGNORE_CERT_CN_INVALID |
            INTERNET_FLAG_IGNORE_CERT_DATE_INVALID |
            INTERNET_FLAG_KEEP_CONNECTION |
            INTERNET_FLAG_NO_CACHE_WRITE |
            INTERNET_FLAG_PRAGMA_NOCACHE |
            INTERNET_FLAG_RELOAD |
            INTERNET_FLAG_RESYNCHRONIZE |
            INTERNET_FLAG_SECURE;
        char url[100];
        sprintf(url, "http://%s:%d/", remoteHost, remotePort);
        hRequest = HttpOpenRequest(hConnect, "GET", "connect.html", "HTTP/1.0", url, 0, flags, 0);
        if (!hRequest) return "HttpOpenRequest";
    }
    {
        DWORD flags=0;
        DWORD bufferLength = sizeof(flags);
        if (!InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, &bufferLength)) {
            return "InternetQueryOption";
        }
        flags |= (SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_REVOCATION);
        if (!InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags))) {
            return "InternetSetOption";
        }
    }
    if (!HttpSendRequest(hRequest, 0, 0, 0, 0)) {
        return "HttpSendRequest";
    } else {
        char buffer[4];
        DWORD bufferSize = sizeof(buffer);
        if (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, &buffer, &bufferSize, NULL)) {
        return "HttpQueryInfo";
        } else if (atoi(buffer) != 200) {
            return "status code";
        }
    }
    {
        INTERNET_DIAGNOSTIC_SOCKET_INFO idsi;
        DWORD bufferSize = sizeof(idsi);
        if (!InternetQueryOption(hRequest, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &idsi, &bufferSize)) {
            return "InternetQueryOption";
        } else if (idsi.Socket == INVALID_SOCKET) {
            /* This is always the case on our Windows 7 platform, why? */
            return "invalid socket";
        }
    }
    return 0;
}

int main(int argc, const char **argv)
{
    const char *error = _connect();
    if (error) {
        printf("ERROR: %s (%d)\n", error, GetLastError());
    } else {
        printf("SUCCESS\n");
    }
    return 0;
}

Upvotes: 2

Views: 4665

Answers (3)

Reuven Abliyev
Reuven Abliyev

Reputation: 135

From MS Docs

INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO 67

Retrieves an INTERNET_DIAGNOSTIC_SOCKET_INFO structure that contains data about a specified HTTP Request. This flag is used by InternetQueryOption.

Windows 7: This option is no longer supported.

Upvotes: 3

Remy Lebeau
Remy Lebeau

Reputation: 597951

Is the HTTP request using keep-alives? If not, then my guess would be that WinInet under Win7 is invalidating the socket handle after closing it when receiving the server's response, whereas XP does not invalidate the socket.

Upvotes: 2

alk
alk

Reputation: 70981

Are your sure your project is not compiling for unicode? In case it does you need to change your char declaration to wchar_t and prefix your constants with L like:

const wchar_t * pszTmp = L"hello world";

Upvotes: 0

Related Questions