Cancel navigation in protocol handler
<p>I'm implementing my custom protocol handler by implementing <strong>IInternetProtocol</strong> interface and registering COM object in HKEY_CLASSES_ROOT\PROTOCOLS\Handler.</p>

<p>I want to be able to process the request and just leave the browser window as is (i.e. it must stay on the page with the link to my custom protocol).</p>

<p>Such a behavior normally achieved by returning HTTP 204 response.</p>

<p>I have implemented <strong>IWinInetHttpInfo</strong> interface for this. It processes HTTP_QUERY_REQUEST_METHOD, HTTP_QUERY_CONTENT_TYPE, HTTP_QUERY_VERSION, HTTP_QUERY_RAW_HEADERS_CRLF, HTTP_QUERY_STATUS_CODE requests.</p>

<p>But this does not help. Internet Explorer still switches the original page to a blank one with the URL of my custom protocol.</p>

<p>Any help, please?</p>

<p>Code:</p>

<pre><code>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-&gt;ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, L"text/html");
    sink-&gt;ReportData(BSCF_FIRSTDATANOTIFICATION, 0, (ULONG)m_response.size());
    sink-&gt;ReportData(BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
                     (ULONG)m_response.size(), (ULONG)m_response.size());
    sink-&gt;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 &gt; (m_response.size() - m_responsePos))
        to_read = m_response.size() - m_responsePos;
    if (to_read)
    {
        std::memcpy(pv, &amp;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 &amp; HTTP_QUERY_FLAG_REQUEST_HEADERS)
            return E_NOTIMPL;

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

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

    if (LOWORD(dwOption) == HTTP_QUERY_STATUS_CODE)
    {
        if (dwOption &amp; HTTP_QUERY_FLAG_NUMBER)
        {
            UINT code = 204;
            std::memcpy(pBuffer, &amp;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;
}
</code></pre>