0

我通过实现IInternetProtocol接口并在 HKEY_CLASSES_ROOT\PROTOCOLS\Handler 中注册 COM 对象来实现我的自定义协议处理程序。

我希望能够处理请求并保持浏览器窗口不变(即它必须保留在带有我的自定义协议链接的页面上)。

这种行为通常通过返回 HTTP 204 响应来实现。

我为此实现了IWinInetHttpInfo接口。它处理 HTTP_QUERY_REQUEST_METHOD、HTTP_QUERY_CONTENT_TYPE、HTTP_QUERY_VERSION、HTTP_QUERY_RAW_HEADERS_CRLF、HTTP_QUERY_STATUS_CODE 请求。

但这无济于事。Internet Explorer 仍然使用我的自定义协议的 URL 将原始页面切换为空白页面。

请问有什么帮助吗?

代码:

SchemeHandlerImpl::SchemeHandlerImpl()
{
    m_headers =
        "HTTP/1.1 204 No Content\r\n"
        "Content-Length: 0\r\n"
        "Connection: close\r\n"
        "\r\n";

    m_response = "";
}

STDMETHODIMP SchemeHandlerImpl::Abort(HRESULT, DWORD)
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Continue(PROTOCOLDATA *)
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Resume()
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Start(
        LPCWSTR url,
        IInternetProtocolSink *sink,
        IInternetBindInfo *,
        DWORD grfPI,
        HANDLE_PTR)
{
    m_responsePos = 0;
    sink->ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
    sink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, (ULONG)m_response.size());
    sink->ReportData(BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
                     (ULONG)m_response.size(), (ULONG)m_response.size());
    sink->ReportResult(S_OK, 0, nullptr);
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Suspend()
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Terminate(DWORD)
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::LockRequest(DWORD)
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::Read(LPVOID pv, ULONG to_read, ULONG *read)
{
    if (to_read > (m_response.size() - m_responsePos))
        to_read = m_response.size() - m_responsePos;
    if (to_read)
    {
        std::memcpy(pv, &m_response.front() + m_responsePos, to_read);
        m_responsePos += to_read;
    }
    *read = to_read;
    return to_read ? S_OK : S_FALSE;
}

STDMETHODIMP SchemeHandlerImpl::Seek(LARGE_INTEGER, DWORD, ULARGE_INTEGER*)
{
    return E_NOTIMPL;
}

STDMETHODIMP SchemeHandlerImpl::UnlockRequest()
{
    return S_OK;
}

STDMETHODIMP SchemeHandlerImpl::QueryInfo(
        DWORD dwOption,
        LPVOID pBuffer,
        DWORD  *pcbBuf,
        DWORD  *pdwFlags,
        DWORD *pdwReserved)
{
    if (LOWORD(dwOption) == HTTP_QUERY_REQUEST_METHOD)
    {
        wchar_t result[] = L"GET";
        std::memcpy(pBuffer, result, sizeof(result)-2);
        *pcbBuf = sizeof(result)-2;
        return S_OK;
    }

    if (LOWORD(dwOption) == HTTP_QUERY_CONTENT_TYPE)
    {
        wchar_t result[] = L"text/html";
        std::memcpy(pBuffer, result, sizeof(result)-2);
        *pcbBuf = sizeof(result)-2;
        return S_OK;
    }

    if (LOWORD(dwOption) == HTTP_QUERY_VERSION)
    {
        wchar_t result[] = L"HTTP/1.1";
        std::memcpy(pBuffer, result, sizeof(result)-2);
        *pcbBuf = sizeof(result)-2;
        return S_OK;
    }

    if (LOWORD(dwOption) == HTTP_QUERY_RAW_HEADERS_CRLF)
    {
        if (dwOption & HTTP_QUERY_FLAG_REQUEST_HEADERS)
            return E_NOTIMPL;

        std::wstring wheaders(m_headers.cbegin(), m_headers.cend());
        auto size = wheaders.size() * 2;
        if (*pcbBuf < size)
            return E_INVALIDARG;

        std::memcpy(pBuffer, &wheaders.front(), size);
        *pcbBuf = size;
        return S_OK;
    }

    if (LOWORD(dwOption) == HTTP_QUERY_STATUS_CODE)
    {
        if (dwOption & HTTP_QUERY_FLAG_NUMBER)
        {
            UINT code = 204;
            std::memcpy(pBuffer, &code, 4);
            *pcbBuf = 4;
            return S_OK;
        }
        else
        {
            wchar_t code[] = L"204";
            std::memcpy(pBuffer, code, sizeof(code)-2);
            *pcbBuf = sizeof(code)-2;
            return S_OK;
        }
    }

    return E_FAIL;
}

STDMETHODIMP SchemeHandlerImpl::QueryOption(
        DWORD dwOption,
        LPVOID pBuffer,
        DWORD  *pcbBuf)
{
    return INET_E_DEFAULT_ACTION;
}
4

1 回答 1

0

IInternetProtocolSink::ReportResult(INET_E_DATA_NOT_AVAILABLE, 204, nullptr) 完成了这项工作!

于 2016-05-28T05:57:48.833 回答