2016-05-24 4 views
0

Ich implementiere meinen benutzerdefinierten Protokollhandler, indem ich die Schnittstelle IInternetProtocol implementiert und das COM-Objekt in HKEY_CLASSES_ROOT \ PROTOCOLS \ Handler registriert.Abbrechen der Navigation im Protokollhandler

Ich möchte in der Lage sein, die Anfrage zu bearbeiten und das Browserfenster so zu lassen, wie es ist (d. H. Es muss auf der Seite mit dem Link zu meinem benutzerdefinierten Protokoll bleiben).

Ein solches Verhalten wird normalerweise durch das Zurücksenden der HTTP 204-Antwort erreicht.

Ich habe IWinInetHttpInfo Schnittstelle für diese implementiert. Es verarbeitet HTTP_QUERY_REQUEST_METHOD-, HTTP_QUERY_CONTENT_TYPE-, HTTP_QUERY_VERSION-, HTTP_QUERY_RAW_HEADERS_CRLF-, HTTP_QUERY_STATUS_CODE-Anfragen.

Aber das hilft nicht. Internet Explorer wechselt die ursprüngliche Seite weiterhin zu einer leeren Seite mit der URL meines benutzerdefinierten Protokolls.

Irgendwelche Hilfe, bitte?

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->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; 
} 
+0

Funktioniert es, wenn Sie eine 205 (Inhalt zurücksetzen) zurückgeben, die die Seite, die die Anforderung generiert hat, neu laden soll? Sind Sie sicher, dass die gesendete Antwort keinen Nachrichtentext hat? Siehe: [HTTP 204] (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5) und [Nachrichtentext] (https://www.w3.org/Protocols/rfc2616 /rfc2616-sec4.html#sec4.3) – theB

+0

Nein, 205 funktioniert auch nicht. Ja, die Antwort hat keinen Körper. –

+0

Hmm ... HTTP 404 verhält sich genauso. –

Antwort

0

IInternetProtocolSink :: ReportResult (INET_E_DATA_NOT_AVAILABLE, 204, nullptr) macht den Job!

Verwandte Themen