HttpSendRequest 失败并出现错误 12015

发布于 2024-10-21 04:28:26 字数 4024 浏览 5 评论 0原文

我创建了一个 Win32 服务,它使用 WinInet 向远程主机发送 HTTP 请求。在我的计算机(WinXP SP2)上,在我们的 QoS 团队(Win2003 服务器)的测试工作站上,它工作正常 - 通过代理和直接、带身份验证和不带身份验证的代理)。

但是我们的一些客户在 Win2003 服务器上使用此服务 and_proxy_with_authorization 时遇到了问题 - 所有 HttpSendRequest 调用均失败,并且 GetLastError 返回 12015(ERROR_INTERNET_LOGIN_FAILURE,连接并登录 FTP 服务器的请求失败) )。至此,从 IE 地址行手动发送的同等 HTTP 请求成功。

代理配置似乎是正确的。这是初始化代码:

m_hNet = InternetOpen(m_strAgent.c_str(),
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,
            NULL,
            0);

        // Respect explicit proxy
        if (Cfg::m_bUseProxy)
        {
            char szProxy[MAX_PATH] = {0};
            strncpy(szProxy, m_strProxyServer.c_str(), MAX_PATH - 1);

            INTERNET_PROXY_INFO proxyinfo;
            proxyinfo.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
            proxyinfo.lpszProxy = szProxy;
            proxyinfo.lpszProxyBypass = NULL;

            BOOL B = InternetSetOption(m_hNet, INTERNET_OPTION_PROXY, (LPVOID)(&proxyinfo), sizeof(proxyinfo));
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::Proxy failed <proxy=%s><le=%d>",
                    m_strProxyServer.c_str(),
                    GetLastError());
            }
        }


        // Validate handle
        if (NULL == m_hNet)
        {
            devent(TS::LL_CRITICAL, "[Err] InternetOpen failed <le=%d>",
                GetLastError());
            return false;
        }


        // Try to get connection handle
        m_hConnect = InternetConnect(m_hNet,
            m_strHostName.c_str(),
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0);


        // Validate handle
        if (NULL == m_hConnect)
        {
            devent(TS::LL_CRITICAL, "[Err] InternetConnect failed <le=%d>",
                GetLastError());
            Cleanup();
            return false;
        }

        // Respect proxy authentication
        if (Cfg::m_bUseAuth)
        {
            BOOL B;
            B = InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_USERNAME, (LPVOID*)Cfg::m_strProxyLogin.c_str(), Cfg::m_strProxyLogin.length() + 1);
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::ProxyUserName failed <login=%s><le=%d>",
                    Cfg::m_strProxyLogin.c_str(),
                    GetLastError());
            }

            B = InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_PASSWORD, (LPVOID*)Cfg::m_strProxyPassword.c_str(), Cfg::m_strProxyPassword.length() + 1);
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::ProxyPassword failed <pass=%s><le=%d>",
                    Cfg::m_strProxyPassword.c_str(),
                    GetLastError());
            }
        }

这是发送:

// Try to get request handle
        m_hRequest = HttpOpenRequest(m_hConnect,
            "POST",
            m_strReqObject.c_str(),
            NULL,
            NULL,
            NULL,
            INTERNET_FLAG_NO_CACHE_WRITE,
            0);

        // Validate handle
        if (NULL == m_hRequest)
        {
            devent(TS::LL_CRITICAL, "[Err] OpenRequest failed <le=%d>",
                GetLastError());
            return false;
        }

        // Try to get response
        BOOL bOk = HttpSendRequest(m_hRequest,
            strSpecificHeaders.c_str(),
            strSpecificHeaders.length(),
            (LPVOID)strRequest.c_str(),
            (DWORD)strRequest.length());

        if (0 == bOk)
        {
            devent(TS::LL_CRITICAL, "[Err] SendRequest failed <le=%d>",
                GetLastError());

            CloseHandle(m_hRequest);
            return false;
        }

我已经用谷歌搜索了两天,但不仅没有找到解决方案,而且还没有找到任何人的类似问题。我也无法在类似的工作站上重现问题。最后,我不明白为什么 msdn 错误描述中的“FTP-Server”?

有什么想法吗?

I have created a Win32 Service which uses WinInet to send HTTP-requests to remote host. On my computer (WinXP SP2), on test workstations in our QoS-team (Win2003 Server) it works fine - over proxy and direct, proxy with auth and without).

But some of our customers, that uses this service and_proxy_with_authorization on Win2003 Server, have a problem - all calls of HttpSendRequest fails and GetLastError returns 12015 (ERROR_INTERNET_LOGIN_FAILURE, The request to connect and log on to an FTP server failed). Herewith, equal HTTP-request, manually sent from IE address-line, succeeded.

Proxy configuration seems to be correct. Here is initialization code:

m_hNet = InternetOpen(m_strAgent.c_str(),
            INTERNET_OPEN_TYPE_PRECONFIG,
            NULL,
            NULL,
            0);

        // Respect explicit proxy
        if (Cfg::m_bUseProxy)
        {
            char szProxy[MAX_PATH] = {0};
            strncpy(szProxy, m_strProxyServer.c_str(), MAX_PATH - 1);

            INTERNET_PROXY_INFO proxyinfo;
            proxyinfo.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
            proxyinfo.lpszProxy = szProxy;
            proxyinfo.lpszProxyBypass = NULL;

            BOOL B = InternetSetOption(m_hNet, INTERNET_OPTION_PROXY, (LPVOID)(&proxyinfo), sizeof(proxyinfo));
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::Proxy failed <proxy=%s><le=%d>",
                    m_strProxyServer.c_str(),
                    GetLastError());
            }
        }


        // Validate handle
        if (NULL == m_hNet)
        {
            devent(TS::LL_CRITICAL, "[Err] InternetOpen failed <le=%d>",
                GetLastError());
            return false;
        }


        // Try to get connection handle
        m_hConnect = InternetConnect(m_hNet,
            m_strHostName.c_str(),
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0);


        // Validate handle
        if (NULL == m_hConnect)
        {
            devent(TS::LL_CRITICAL, "[Err] InternetConnect failed <le=%d>",
                GetLastError());
            Cleanup();
            return false;
        }

        // Respect proxy authentication
        if (Cfg::m_bUseAuth)
        {
            BOOL B;
            B = InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_USERNAME, (LPVOID*)Cfg::m_strProxyLogin.c_str(), Cfg::m_strProxyLogin.length() + 1);
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::ProxyUserName failed <login=%s><le=%d>",
                    Cfg::m_strProxyLogin.c_str(),
                    GetLastError());
            }

            B = InternetSetOption(m_hConnect, INTERNET_OPTION_PROXY_PASSWORD, (LPVOID*)Cfg::m_strProxyPassword.c_str(), Cfg::m_strProxyPassword.length() + 1);
            if (!B)
            {
                devent(TS::LL_HIGH, "[Wrn] InternetSetOption::ProxyPassword failed <pass=%s><le=%d>",
                    Cfg::m_strProxyPassword.c_str(),
                    GetLastError());
            }
        }

And this is sending:

// Try to get request handle
        m_hRequest = HttpOpenRequest(m_hConnect,
            "POST",
            m_strReqObject.c_str(),
            NULL,
            NULL,
            NULL,
            INTERNET_FLAG_NO_CACHE_WRITE,
            0);

        // Validate handle
        if (NULL == m_hRequest)
        {
            devent(TS::LL_CRITICAL, "[Err] OpenRequest failed <le=%d>",
                GetLastError());
            return false;
        }

        // Try to get response
        BOOL bOk = HttpSendRequest(m_hRequest,
            strSpecificHeaders.c_str(),
            strSpecificHeaders.length(),
            (LPVOID)strRequest.c_str(),
            (DWORD)strRequest.length());

        if (0 == bOk)
        {
            devent(TS::LL_CRITICAL, "[Err] SendRequest failed <le=%d>",
                GetLastError());

            CloseHandle(m_hRequest);
            return false;
        }

I have googled two days, but not found not only solutions but also similar problems by anybody. Also i cannot reproduce problem on similar workstations. And finally, i cant understand why "FTP-Server" in msdn error desc?

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

明天过后 2024-10-28 04:28:26

WinInet 专为应用程序空间用户使用而设计,并与 WinInet 选项的注册表位置相关联(基于登录的用户帐户)。

在线 MSDN 文档在每个 WinInet 页面上都明确指出:

注意 WinINet 不支持服务器实现。此外,不应从服务中使用它。对于服务器实现或服务,请使用 Microsoft Windows HTTP 服务 ( WinHTTP)

WinInet 和 WinHTTP 之间的 API 差异非常小,您很快就会掌握。

  • 函数重命名(例如 HttpOpenRequest -> WinHttpOpenRequest)
  • 所有 WinHttp 方法都是 Unicode 仅
  • 使用 WinHttp.lib,WinHttp.dll 而不是 WinInet.lib, WinInet.dll

还有一些其他微妙之处,但您不会感到困扰。

我知道你的问题表明该代码适用于已经将其作为服务运行的人。但文档明确指出“不要这样做”的事实可能表明某些版本的 Windows 可能不支持它,特别是更高版本,并且某些 Service Pack 或自动更新可能会导致当前工作实例失败。

我大胆猜测,WinInet 甚至可能需要一些安全令牌和特权来完成任务,并且 Windows Server 200x 的某些安装可能具有默认设置,不向作为服务帐户运行的用户提供这些令牌。

我强烈建议尝试将快速测试服务移植到 WinHTTP 并在客户端的 Windows Server 实现上进行测试,看看是否可以解决问题。

WinInet is designed for use by Application space users, and has ties back to Registry locations for the WinInet options (based on logged in user account).

The online MSDN Documentation clearly states on every WinInet page:

Note WinINet does not support server implementations. In addition, it should not be used from a service. For server implementations or services use Microsoft Windows HTTP Services (WinHTTP).

The difference in API between WinInet and WinHTTP are very small, you will pick it up very quickly.

  • Functions renamed (e.g. HttpOpenRequest -> WinHttpOpenRequest)
  • All WinHttp methods are Unicode only
  • uses WinHttp.lib,WinHttp.dll instead of WinInet.lib, WinInet.dll

There are a few other subtleties, but you won't struggle.

I know your question suggests the code works for people already with it running it as a service. But the fact that the documentation specifically says "don't do it" may suggest that some versions of Windows may not support it, specifically the later versions, and that some Service Packs or Automatic Updates may cause the current working instances to fail.

I would hazzard a guess that there may even be some Security Tokens and Privileges that WinInet needs under the hood to complete tasks, and some installs of Windows Server 200x may have the default setup to not provide those tokens to users running as a service account.

I really recommend trying to port a quick test service to WinHTTP and testing on your client's Windows Server implementation to see if that resolves the problem.

最冷一天 2024-10-28 04:28:26

在完全不同的策略上... ERROR_INTERNET_LOGIN_FAILURE 也可能表明防火墙已阻止该连接。

Egg Head Cafe 描述了可能的解决方案

On a completely different tack... The ERROR_INTERNET_LOGIN_FAILURE can also suggest that a firewall has blocked that connection.

A possible solution was described here at Egg Head Cafe

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文