411 lines
7.8 KiB
C++
411 lines
7.8 KiB
C++
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
// PARTICULAR PURPOSE.
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved
|
|
//
|
|
|
|
#include "XMLHttpRequest2Callback.h"
|
|
|
|
CXMLHttpRequest2Callback::CXMLHttpRequest2Callback()
|
|
{
|
|
m_hr = S_OK;
|
|
m_dwStatus = 0;
|
|
m_hComplete = NULL;
|
|
}
|
|
|
|
CXMLHttpRequest2Callback::~CXMLHttpRequest2Callback()
|
|
{
|
|
if (m_hComplete)
|
|
{
|
|
CloseHandle(m_hComplete);
|
|
m_hComplete = NULL;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::RuntimeClassInitialize()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initalize the call back instance.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HANDLE hEvent = NULL;
|
|
|
|
//
|
|
// Callers needing to receive completion or status events on a STA or UI
|
|
// thread must use a mechanism that will not block the threads window message
|
|
// pump. One example is by posting a window message to the STA or UI thread
|
|
// window handle.
|
|
//
|
|
|
|
hEvent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
|
|
|
|
if (hEvent == NULL)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
m_hComplete = hEvent;
|
|
hEvent = NULL;
|
|
|
|
Exit:
|
|
|
|
if (hEvent)
|
|
{
|
|
CloseHandle(hEvent);
|
|
hEvent = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::OnRedirect(
|
|
__RPC__in_opt IXMLHTTPRequest2 *pXHR,
|
|
__RPC__in_string const WCHAR *pwszRedirectUrl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This funciton is called when the HTTP request is being redirected to a new URL.
|
|
|
|
This callback function must not throw any exceptions.
|
|
|
|
Arguments:
|
|
|
|
pXHR - The interface pointer of IXMLHTTPRequest2 object.
|
|
|
|
pwszRedirectUrl - The new URL for the HTTP request.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(pXHR);
|
|
UNREFERENCED_PARAMETER(pwszRedirectUrl);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::OnHeadersAvailable(
|
|
__RPC__in_opt IXMLHTTPRequest2 *pXHR,
|
|
DWORD dwStatus,
|
|
__RPC__in_string const WCHAR *pwszStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends a request using the Request Handle specified and implements
|
|
proxy failover if supported.
|
|
|
|
This callback function must not throw any exceptions.
|
|
|
|
Arguments:
|
|
|
|
pXHR - The interface pointer of IXMLHTTPRequest2 object.
|
|
|
|
dwStatus - The value of HTTP status code.
|
|
|
|
pwszStatus - The description text of HTTP status code.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(pwszStatus);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
PWSTR pwszHeaders = NULL;
|
|
PWSTR pwszSingleHeader = NULL;
|
|
|
|
if (pXHR == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Demonstrate how to get all response headers.
|
|
//
|
|
|
|
hr = pXHR->GetAllResponseHeaders(&pwszHeaders);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Demonstrate how to get a specific response header.
|
|
//
|
|
|
|
hr = pXHR->GetResponseHeader(L"server", &pwszSingleHeader);
|
|
if (FAILED(hr) &&
|
|
hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
|
|
if (pwszHeaders != NULL)
|
|
{
|
|
CoTaskMemFree(pwszHeaders);
|
|
pwszHeaders = NULL;
|
|
}
|
|
|
|
if (pwszSingleHeader != NULL)
|
|
{
|
|
CoTaskMemFree(pwszSingleHeader);
|
|
pwszSingleHeader = NULL;
|
|
}
|
|
|
|
m_dwStatus = dwStatus;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::ReadFromStream(
|
|
_In_opt_ ISequentialStream *pStream
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Demonstrate how to read from the HTTP response stream.
|
|
|
|
Arguments:
|
|
|
|
pStream - the data stream read form the http response.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BYTE buffer[MAX_BUFFER_LENGTH];
|
|
DWORD cbRead = 0;
|
|
|
|
if (pStream == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
for(;;)
|
|
{
|
|
hr = pStream->Read(buffer, MAX_BUFFER_LENGTH - 1, &cbRead);
|
|
|
|
if (FAILED(hr) ||
|
|
cbRead == 0)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
buffer[cbRead] = 0;
|
|
}
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::OnDataAvailable(
|
|
__RPC__in_opt IXMLHTTPRequest2 *pXHR,
|
|
__RPC__in_opt ISequentialStream *pResponseStream
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called when a portion of the entity body has been received.
|
|
The application can begin processing the data at this point,
|
|
or wait until the whole response is complete.
|
|
|
|
This callback function must not throw any exceptions.
|
|
|
|
Arguments:
|
|
|
|
pXHR - The interface pointer of IXMLHTTPRequest2 object.
|
|
|
|
pResponseStream - a pointer to the input stream.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(pXHR);
|
|
|
|
//
|
|
// This sample function is processing data as it is received by reading from
|
|
// the response stream. If real-time chunk-by-chunk processing (such as for
|
|
// streaming applications) is not needed, then the entire response is available
|
|
// from the OnResponseReceived callback. Receiving will be suspended until
|
|
// this callback function returns and this callback will be invoked multiple
|
|
// times during a request. This callback function must not block and
|
|
// should not perform costly operations such as UI updates.
|
|
//
|
|
|
|
return ReadFromStream(pResponseStream);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::OnResponseReceived(
|
|
__RPC__in_opt IXMLHTTPRequest2 *pXHR,
|
|
__RPC__in_opt ISequentialStream *pResponseStream
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the entire entity body has been received.
|
|
At this point the application can begin processing the data by calling Read
|
|
on the response ISequentialStream or store a reference to the ISequentialStream
|
|
for later processing.
|
|
|
|
This callback function must not throw any exceptions.
|
|
|
|
Arguments:
|
|
|
|
pXHR - The interface pointer of IXMLHTTPRequest2 object.
|
|
|
|
pResponseStream - a pointer to the input stream.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(pXHR);
|
|
UNREFERENCED_PARAMETER(pResponseStream);
|
|
|
|
m_hr = S_OK;
|
|
SetEvent(m_hComplete);
|
|
return m_hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::OnError(
|
|
__RPC__in_opt IXMLHTTPRequest2 *pXHR,
|
|
HRESULT hrError
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when an error occurs during the HTTP request. The error is indicated in hrError.
|
|
|
|
This callback function must not throw any exceptions.
|
|
|
|
Arguments:
|
|
|
|
pXHR - The interface pointer of IXMLHTTPRequest2 object.
|
|
|
|
hrError - The errocode for the httprequest.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(pXHR);
|
|
|
|
m_hr = hrError;
|
|
SetEvent(m_hComplete);
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CXMLHttpRequest2Callback::WaitForComplete(
|
|
_Out_ PDWORD pdwStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Waiting for completion of the request. Once it's done, get the execution
|
|
result of final call backs, and http status code if it's available.
|
|
|
|
N.B. Callers needing to receive completion or status events on a STA or UI
|
|
thread must use a mechanism that will not block the threads window message
|
|
pump. One example is by posting a window message to the STA or UI thread
|
|
window handle.
|
|
|
|
Arguments:
|
|
|
|
pdwStatus - Supplies a pointer to access the status code.
|
|
|
|
Return Value:
|
|
|
|
HRESULT.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pdwStatus == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
dwError = WaitForSingleObject(m_hComplete, INFINITE);
|
|
|
|
if (dwError == WAIT_FAILED)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
else if (dwError != WAIT_OBJECT_0)
|
|
{
|
|
hr = E_ABORT;
|
|
goto Exit;
|
|
}
|
|
|
|
if (FAILED(m_hr))
|
|
{
|
|
hr = m_hr;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = S_OK;
|
|
*pdwStatus = m_dwStatus;
|
|
|
|
Exit:
|
|
|
|
return hr;
|
|
}
|