📄 response.cpp
字号:
if (FALSE == m_pASPState->m_pACB->AddHeader(m_pASPState->m_pACB->ConnID,
pszName, pszValue))
{
ASP_ERR(IDS_E_NOMEM); // only reason call can fail
myleave(155);
}
ret = S_OK;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: CResponse::AddHeaders died, err = %d, GLE=%X\r\n",err,GetLastError()));
MyFree(pszName);
MyFree(pszValue);
return ret;
}
STDMETHODIMP CResponse::AppendToLog(BSTR bstrLogData)
{
HRESULT ret = DISP_E_EXCEPTION;
// Codepage note: IIS converts this to ANSI string to keep log in ANSI format, so do we.
PSTR pszLogData = NULL;
DWORD cbLogData = 0;
if (NULL == bstrLogData)
{
ret = S_OK;
goto done;
}
pszLogData = MySzDupWtoA(bstrLogData);
if (NULL == pszLogData)
{
ASP_ERR(IDS_E_NOMEM);
goto done;
}
cbLogData = strlen(pszLogData);
if (FALSE == m_pASPState->m_pACB->ServerSupportFunction(m_pASPState->m_pACB->ConnID,
HSE_APPEND_LOG_PARAMETER,(LPVOID) pszLogData,
&cbLogData, NULL))
{
ASP_ERR(IDS_E_NOMEM);
goto done;
}
ret = S_OK;
done:
MyFree(pszLogData);
return ret;
}
STDMETHODIMP CResponse::Clear()
{
if (FALSE == m_pASPState->m_fBufferedResponse)
{
ASP_ERR(IDS_E_BUFFER_ON);
return DISP_E_EXCEPTION;
}
if (FALSE == m_pASPState->m_pACB->Clear(m_pASPState->m_pACB->ConnID))
{
ASP_ERR(IDS_E_HTTPD);
return DISP_E_EXCEPTION;
}
return S_OK;
}
STDMETHODIMP CResponse::End()
{
EXCEPINFO ex = {0, 0, NULL, NULL, NULL, 0, NULL, NULL, E_THREAD_INTERRUPT};
if (FALSE == m_pASPState->m_fSentHeaders)
{
m_pASPState->SendHeaders();
}
m_pASPState->m_pACB->Flush(m_pASPState->m_pACB->ConnID);
m_pASPState->m_piActiveScript->InterruptScriptThread(SCRIPTTHREADID_CURRENT ,&ex,0);
return S_OK;
}
STDMETHODIMP CResponse::Flush()
{
if (FALSE == m_pASPState->m_fBufferedResponse)
{
ASP_ERR(IDS_E_BUFFER_ON);
return DISP_E_EXCEPTION;
}
if (m_pASPState->m_fSentHeaders == FALSE)
{
if (FALSE == m_pASPState->SendHeaders())
return DISP_E_EXCEPTION;
}
if (FALSE == m_pASPState->m_pACB->Flush(m_pASPState->m_pACB->ConnID))
{
ASP_ERR(IDS_E_HTTPD); // something went wrong on send(), given
// this it's unlikely error code will make
// it to user either but we'll try
return DISP_E_EXCEPTION;
}
return S_OK;
}
STDMETHODIMP CResponse::Redirect(BSTR bstrURL)
{
DEBUG_CODE_INIT;
HRESULT ret = DISP_E_EXCEPTION;
PSTR pszRedirect = NULL;
if (NULL == bstrURL)
return S_OK;
// after sending headers, it's too late for this
if (TRUE == m_pASPState->m_fSentHeaders)
{
ASP_ERR(IDS_E_SENT_HEADERS);
myleave(171);
}
// Codepage note: Use specified code page, like IIS.
pszRedirect = MySzDupWtoA(bstrURL,-1,m_pASPState->m_lCodePage);
if (NULL == pszRedirect)
{
ASP_ERR(IDS_E_NOMEM);
myleave(172);
}
if (! m_pASPState->SendHeaders(FALSE))
myleave(175);
if (FALSE == m_pASPState->m_pACB->ServerSupportFunction(m_pASPState->m_pACB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
(LPVOID) pszRedirect,0,0))
{
ASP_ERR(IDS_E_HTTPD);
myleave(173);
}
// Make sure web server doesn't send any data after this request.
m_pASPState->m_fSentHeaders = TRUE;
m_pASPState->m_pACB->Clear(m_pASPState->m_pACB->ConnID);
ret = S_OK;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: CASPState::Redirect failed, err = %d\r\n",err));
MyFree(pszRedirect);
if (SUCCEEDED(ret))
End(); // CResponse::End. don't process anything more on this page
// on success.
return ret;
}
// No Unicode to ASCII conversion. Send data raw.
STDMETHODIMP CResponse::BinaryWrite(VARIANT varData)
{
return m_pASPState->BinaryWrite(varData);
}
STDMETHODIMP CASPState::BinaryWrite(VARIANT varData)
{
DEBUG_CODE_INIT;
HRESULT ret = DISP_E_EXCEPTION;
HRESULT hr;
VARTYPE vt;
VARIANT *pvarKey;
DWORD nLen = 0;
VARIANT varKeyCopy;
SAFEARRAY* pvarBuffer = NULL;
long lLBound = 0;
long lUBound = 0;
void *lpData = NULL;
DWORD cch = 0;
VariantInit(&varKeyCopy);
vt = varData.vt;
if (vt != (VT_ARRAY|VT_UI1))
{
if (FAILED(VariantResolveDispatch(&varKeyCopy, &varData)))
{
m_aspErr = IDS_E_PARSER;
myleave(100);
}
pvarKey = &varKeyCopy;
vt = V_VT(pvarKey);
if (FAILED(hr = VariantChangeType(pvarKey, pvarKey,0, VT_ARRAY|VT_UI1)))
{
if (GetScode(hr) == E_OUTOFMEMORY)
{
m_aspErr = IDS_E_NOMEM;
myleave(101);
}
else
{
m_aspErr = IDS_E_UNKNOWN;
myleave(107);
}
// otherwise it's an unknown error, the default
}
}
else {
pvarKey = &varData;
}
pvarBuffer = V_ARRAY(pvarKey);
// If any of these fail, we leave the error as the default Unknown
if (SafeArrayGetDim(pvarBuffer) != 1)
myleave(102);
if (FAILED(SafeArrayGetLBound(pvarBuffer, 1, &lLBound)))
myleave(104);
if (FAILED(SafeArrayGetUBound(pvarBuffer, 1, &lUBound)))
myleave(105);
if (FAILED(SafeArrayAccessData(pvarBuffer, &lpData)))
myleave(106);
cch = lUBound - lLBound + 1;
DEBUGCHK(cch > 0);
if (m_fBufferedResponse == FALSE &&
m_fSentHeaders == FALSE)
{
if (FALSE == SendHeaders())
myleave(116);
}
if (! m_pACB->WriteClient(m_pACB->ConnID, (LPVOID) lpData, &cch, 0))
{
m_aspErr = IDS_E_HTTPD;
myleave(108);
}
m_cbBody += cch;
ret = S_OK;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: CResponse::BinaryWrite failed, err = %d",err));
if (pvarBuffer)
SafeArrayUnaccessData(pvarBuffer);
VariantClear(&varKeyCopy);
return ret;
}
// Performs Unicode to ASCII conversion before sending across the wire.
STDMETHODIMP CResponse::Write(VARIANT varData)
{
return m_pASPState->Write(varData);
}
// Helper function to actually push bits across the wire and handle HTTP header policy, etc...
HRESULT CASPState::WriteToClient(PSTR pszBody, DWORD dwSpecifiedLength) {
DWORD dwWriteLen = dwSpecifiedLength ? dwSpecifiedLength : strlen(pszBody);
// If we're not buffering this and we haven't sent headers yet, send them now.
if (m_fBufferedResponse == FALSE && m_fSentHeaders == FALSE) {
if (FALSE == SendHeaders())
return DISP_E_EXCEPTION;
}
if (! m_pACB->WriteClient(m_pACB->ConnID, (LPVOID) pszBody, &dwWriteLen, 0)) {
m_aspErr = IDS_E_HTTPD;
return DISP_E_EXCEPTION;
}
m_cbBody += dwWriteLen;
return S_OK;
}
// Exposed to caller.
STDMETHODIMP CASPState::Write(VARIANT varData)
{
DEBUG_CODE_INIT;
HRESULT ret = DISP_E_EXCEPTION;
VARTYPE vt;
VARIANT *pvarKey = &varData;
VARIANT varKeyCopy;
PSTR pszVal = NULL;
VariantInit(&varKeyCopy);
vt = varData.vt;
if ((vt != VT_BSTR) && (vt != VT_I2) && (vt != VT_I4))
{
if (FAILED(VariantResolveDispatch(&varKeyCopy, &varData)))
{
m_aspErr = IDS_E_PARSER;
myleave(112);
}
pvarKey = &varKeyCopy;
}
vt = V_VT(pvarKey);
if (vt != VT_BSTR)
{
// Coerce other types to VT_BSTR
if (FAILED(VariantChangeTypeEx(pvarKey, pvarKey, m_lcid, 0, VT_BSTR)))
myleave(113);
}
// The case where we have empty data, just get out.
if (SysStringLen(pvarKey->bstrVal) == 0)
myretleave(S_OK,0);
// Codepage note: We actually do use user set codepage in this instance,
// because it's in the body of the request and not the headers. Like IIS.
pszVal = MySzDupWtoA(pvarKey->bstrVal, -1, m_lCodePage);
if (NULL == pszVal)
{
m_aspErr = IDS_E_NOMEM;
myleave(115);
}
ret = WriteToClient(pszVal);
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"ASP: Response::Write failed, err = %d\r\n",err));
MyFree(pszVal);
VariantClear(&varKeyCopy);
return ret;
}
// IStream
HRESULT STDMETHODCALLTYPE CResponse::Write(const void __RPC_FAR *pv,ULONG cb,ULONG __RPC_FAR *pcbWritten) {
if (!pv || !cb || !pcbWritten)
return STG_E_INVALIDPOINTER;
HRESULT hr = m_pASPState->WriteToClient((PSTR)pv,cb);
if (hr == S_OK) {
*pcbWritten = cb;
return S_OK;
}
*pcbWritten = 0;
return STG_E_CANTSAVE;
}
HRESULT STDMETHODCALLTYPE CResponse::Read(void __RPC_FAR *pv, ULONG cb, ULONG __RPC_FAR *pcbRead) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER __RPC_FAR *plibNewPosition) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::SetSize(ULARGE_INTEGER libNewSize) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::CopyTo(IStream __RPC_FAR *pstm,ULARGE_INTEGER cb,ULARGE_INTEGER __RPC_FAR *pcbRead,ULARGE_INTEGER __RPC_FAR *pcbWritten) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::Commit(DWORD grfCommitFlags) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::Revert(void) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,DWORD dwLockType) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::UnlockRegion(ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::Stat(STATSTG __RPC_FAR *pstatstg, DWORD grfStatFlag) {
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CResponse::Clone(IStream __RPC_FAR *__RPC_FAR *ppstm) {
return E_NOTIMPL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -